diff --git a/src/main/java/net/onrc/onos/core/datastore/RCProtos.java b/src/main/java/net/onrc/onos/core/datastore/RCProtos.java
deleted file mode 100644
index 44b6934..0000000
--- a/src/main/java/net/onrc/onos/core/datastore/RCProtos.java
+++ /dev/null
@@ -1,2391 +0,0 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: protobuf/ramcloud.proto
-
-package net.onrc.onos.core.datastore;
-
-public final class RCProtos {
-    private RCProtos() {
-    }
-
-    public static void registerAllExtensions(
-            com.google.protobuf.ExtensionRegistry registry) {
-    }
-
-    public interface SwitchPropertyOrBuilder
-            extends com.google.protobuf.MessageOrBuilder {
-
-        // required int64 dpid = 1;
-
-        /**
-         * <code>required int64 dpid = 1;</code>
-         */
-        boolean hasDpid();
-
-        /**
-         * <code>required int64 dpid = 1;</code>
-         */
-        long getDpid();
-
-        // required int32 status = 2;
-
-        /**
-         * <code>required int32 status = 2;</code>
-         */
-        boolean hasStatus();
-
-        /**
-         * <code>required int32 status = 2;</code>
-         */
-        int getStatus();
-
-        // optional bytes value = 3;
-
-        /**
-         * <code>optional bytes value = 3;</code>
-         */
-        boolean hasValue();
-
-        /**
-         * <code>optional bytes value = 3;</code>
-         */
-        com.google.protobuf.ByteString getValue();
-    }
-
-    /**
-     * Protobuf type {@code RCProtos.SwitchProperty}
-     */
-    public static final class SwitchProperty extends
-            com.google.protobuf.GeneratedMessage
-            implements SwitchPropertyOrBuilder {
-        // Use SwitchProperty.newBuilder() to construct.
-        private SwitchProperty(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
-            super(builder);
-            this.unknownFields = builder.getUnknownFields();
-        }
-
-        private SwitchProperty(boolean noInit) {
-            this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance();
-        }
-
-        private static final SwitchProperty defaultInstance;
-
-        public static SwitchProperty getDefaultInstance() {
-            return defaultInstance;
-        }
-
-        public SwitchProperty getDefaultInstanceForType() {
-            return defaultInstance;
-        }
-
-        private final com.google.protobuf.UnknownFieldSet unknownFields;
-
-        @java.lang.Override
-        public final com.google.protobuf.UnknownFieldSet
-        getUnknownFields() {
-            return this.unknownFields;
-        }
-
-        private SwitchProperty(
-                com.google.protobuf.CodedInputStream input,
-                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-                throws com.google.protobuf.InvalidProtocolBufferException {
-            initFields();
-            int mutable_bitField0_ = 0;
-            com.google.protobuf.UnknownFieldSet.Builder unknownFields =
-                    com.google.protobuf.UnknownFieldSet.newBuilder();
-            try {
-                boolean done = false;
-                while (!done) {
-                    int tag = input.readTag();
-                    switch (tag) {
-                        case 0:
-                            done = true;
-                            break;
-                        default: {
-                            if (!parseUnknownField(input, unknownFields,
-                                    extensionRegistry, tag)) {
-                                done = true;
-                            }
-                            break;
-                        }
-                        case 8: {
-                            bitField0_ |= 0x00000001;
-                            dpid_ = input.readInt64();
-                            break;
-                        }
-                        case 16: {
-                            bitField0_ |= 0x00000002;
-                            status_ = input.readInt32();
-                            break;
-                        }
-                        case 26: {
-                            bitField0_ |= 0x00000004;
-                            value_ = input.readBytes();
-                            break;
-                        }
-                    }
-                }
-            } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-                throw e.setUnfinishedMessage(this);
-            } catch (java.io.IOException e) {
-                throw new com.google.protobuf.InvalidProtocolBufferException(
-                        e.getMessage()).setUnfinishedMessage(this);
-            } finally {
-                this.unknownFields = unknownFields.build();
-                makeExtensionsImmutable();
-            }
-        }
-
-        public static final com.google.protobuf.Descriptors.Descriptor
-        getDescriptor() {
-            return net.onrc.onos.core.datastore.RCProtos.internal_static_ProtoBuffer_SwitchProperty_descriptor;
-        }
-
-        protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
-        internalGetFieldAccessorTable() {
-            return net.onrc.onos.core.datastore.RCProtos.internal_static_ProtoBuffer_SwitchProperty_fieldAccessorTable
-                    .ensureFieldAccessorsInitialized(
-                            net.onrc.onos.core.datastore.RCProtos.SwitchProperty.class, net.onrc.onos.core.datastore.RCProtos.SwitchProperty.Builder.class);
-        }
-
-        public static com.google.protobuf.Parser<SwitchProperty> PARSER =
-                new com.google.protobuf.AbstractParser<SwitchProperty>() {
-                    public SwitchProperty parsePartialFrom(
-                            com.google.protobuf.CodedInputStream input,
-                            com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-                            throws com.google.protobuf.InvalidProtocolBufferException {
-                        return new SwitchProperty(input, extensionRegistry);
-                    }
-                };
-
-        @java.lang.Override
-        public com.google.protobuf.Parser<SwitchProperty> getParserForType() {
-            return PARSER;
-        }
-
-        private int bitField0_;
-        // required int64 dpid = 1;
-        public static final int DPID_FIELD_NUMBER = 1;
-        private long dpid_;
-
-        /**
-         * <code>required int64 dpid = 1;</code>
-         */
-        public boolean hasDpid() {
-            return ((bitField0_ & 0x00000001) == 0x00000001);
-        }
-
-        /**
-         * <code>required int64 dpid = 1;</code>
-         */
-        public long getDpid() {
-            return dpid_;
-        }
-
-        // required int32 status = 2;
-        public static final int STATUS_FIELD_NUMBER = 2;
-        private int status_;
-
-        /**
-         * <code>required int32 status = 2;</code>
-         */
-        public boolean hasStatus() {
-            return ((bitField0_ & 0x00000002) == 0x00000002);
-        }
-
-        /**
-         * <code>required int32 status = 2;</code>
-         */
-        public int getStatus() {
-            return status_;
-        }
-
-        // optional bytes value = 3;
-        public static final int VALUE_FIELD_NUMBER = 3;
-        private com.google.protobuf.ByteString value_;
-
-        /**
-         * <code>optional bytes value = 3;</code>
-         */
-        public boolean hasValue() {
-            return ((bitField0_ & 0x00000004) == 0x00000004);
-        }
-
-        /**
-         * <code>optional bytes value = 3;</code>
-         */
-        public com.google.protobuf.ByteString getValue() {
-            return value_;
-        }
-
-        private void initFields() {
-            dpid_ = 0L;
-            status_ = 0;
-            value_ = com.google.protobuf.ByteString.EMPTY;
-        }
-
-        private byte memoizedIsInitialized = -1;
-
-        public final boolean isInitialized() {
-            byte isInitialized = memoizedIsInitialized;
-            if (isInitialized != -1) return isInitialized == 1;
-
-            if (!hasDpid()) {
-                memoizedIsInitialized = 0;
-                return false;
-            }
-            if (!hasStatus()) {
-                memoizedIsInitialized = 0;
-                return false;
-            }
-            memoizedIsInitialized = 1;
-            return true;
-        }
-
-        public void writeTo(com.google.protobuf.CodedOutputStream output)
-                throws java.io.IOException {
-            getSerializedSize();
-            if (((bitField0_ & 0x00000001) == 0x00000001)) {
-                output.writeInt64(1, dpid_);
-            }
-            if (((bitField0_ & 0x00000002) == 0x00000002)) {
-                output.writeInt32(2, status_);
-            }
-            if (((bitField0_ & 0x00000004) == 0x00000004)) {
-                output.writeBytes(3, value_);
-            }
-            getUnknownFields().writeTo(output);
-        }
-
-        private int memoizedSerializedSize = -1;
-
-        public int getSerializedSize() {
-            int size = memoizedSerializedSize;
-            if (size != -1) return size;
-
-            size = 0;
-            if (((bitField0_ & 0x00000001) == 0x00000001)) {
-                size += com.google.protobuf.CodedOutputStream
-                        .computeInt64Size(1, dpid_);
-            }
-            if (((bitField0_ & 0x00000002) == 0x00000002)) {
-                size += com.google.protobuf.CodedOutputStream
-                        .computeInt32Size(2, status_);
-            }
-            if (((bitField0_ & 0x00000004) == 0x00000004)) {
-                size += com.google.protobuf.CodedOutputStream
-                        .computeBytesSize(3, value_);
-            }
-            size += getUnknownFields().getSerializedSize();
-            memoizedSerializedSize = size;
-            return size;
-        }
-
-        private static final long serialVersionUID = 0L;
-
-        @java.lang.Override
-        protected java.lang.Object writeReplace()
-                throws java.io.ObjectStreamException {
-            return super.writeReplace();
-        }
-
-        public static net.onrc.onos.core.datastore.RCProtos.SwitchProperty parseFrom(
-                com.google.protobuf.ByteString data)
-                throws com.google.protobuf.InvalidProtocolBufferException {
-            return PARSER.parseFrom(data);
-        }
-
-        public static net.onrc.onos.core.datastore.RCProtos.SwitchProperty parseFrom(
-                com.google.protobuf.ByteString data,
-                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-                throws com.google.protobuf.InvalidProtocolBufferException {
-            return PARSER.parseFrom(data, extensionRegistry);
-        }
-
-        public static net.onrc.onos.core.datastore.RCProtos.SwitchProperty parseFrom(byte[] data)
-                throws com.google.protobuf.InvalidProtocolBufferException {
-            return PARSER.parseFrom(data);
-        }
-
-        public static net.onrc.onos.core.datastore.RCProtos.SwitchProperty parseFrom(
-                byte[] data,
-                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-                throws com.google.protobuf.InvalidProtocolBufferException {
-            return PARSER.parseFrom(data, extensionRegistry);
-        }
-
-        public static net.onrc.onos.core.datastore.RCProtos.SwitchProperty parseFrom(java.io.InputStream input)
-                throws java.io.IOException {
-            return PARSER.parseFrom(input);
-        }
-
-        public static net.onrc.onos.core.datastore.RCProtos.SwitchProperty parseFrom(
-                java.io.InputStream input,
-                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-                throws java.io.IOException {
-            return PARSER.parseFrom(input, extensionRegistry);
-        }
-
-        public static net.onrc.onos.core.datastore.RCProtos.SwitchProperty parseDelimitedFrom(java.io.InputStream input)
-                throws java.io.IOException {
-            return PARSER.parseDelimitedFrom(input);
-        }
-
-        public static net.onrc.onos.core.datastore.RCProtos.SwitchProperty parseDelimitedFrom(
-                java.io.InputStream input,
-                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-                throws java.io.IOException {
-            return PARSER.parseDelimitedFrom(input, extensionRegistry);
-        }
-
-        public static net.onrc.onos.core.datastore.RCProtos.SwitchProperty parseFrom(
-                com.google.protobuf.CodedInputStream input)
-                throws java.io.IOException {
-            return PARSER.parseFrom(input);
-        }
-
-        public static net.onrc.onos.core.datastore.RCProtos.SwitchProperty parseFrom(
-                com.google.protobuf.CodedInputStream input,
-                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-                throws java.io.IOException {
-            return PARSER.parseFrom(input, extensionRegistry);
-        }
-
-        public static Builder newBuilder() {
-            return Builder.create();
-        }
-
-        public Builder newBuilderForType() {
-            return newBuilder();
-        }
-
-        public static Builder newBuilder(net.onrc.onos.core.datastore.RCProtos.SwitchProperty prototype) {
-            return newBuilder().mergeFrom(prototype);
-        }
-
-        public Builder toBuilder() {
-            return newBuilder(this);
-        }
-
-        @java.lang.Override
-        protected Builder newBuilderForType(
-                com.google.protobuf.GeneratedMessage.BuilderParent parent) {
-            Builder builder = new Builder(parent);
-            return builder;
-        }
-
-        /**
-         * Protobuf type {@code RCProtos.SwitchProperty}
-         */
-        public static final class Builder extends
-                com.google.protobuf.GeneratedMessage.Builder<Builder>
-                implements net.onrc.onos.core.datastore.RCProtos.SwitchPropertyOrBuilder {
-            public static final com.google.protobuf.Descriptors.Descriptor
-            getDescriptor() {
-                return net.onrc.onos.core.datastore.RCProtos.internal_static_ProtoBuffer_SwitchProperty_descriptor;
-            }
-
-            protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
-            internalGetFieldAccessorTable() {
-                return net.onrc.onos.core.datastore.RCProtos.internal_static_ProtoBuffer_SwitchProperty_fieldAccessorTable
-                        .ensureFieldAccessorsInitialized(
-                                net.onrc.onos.core.datastore.RCProtos.SwitchProperty.class, net.onrc.onos.core.datastore.RCProtos.SwitchProperty.Builder.class);
-            }
-
-            // Construct using net.onrc.onos.core.datastore.RCProtos.SwitchProperty.newBuilder()
-            private Builder() {
-                maybeForceBuilderInitialization();
-            }
-
-            private Builder(
-                    com.google.protobuf.GeneratedMessage.BuilderParent parent) {
-                super(parent);
-                maybeForceBuilderInitialization();
-            }
-
-            private void maybeForceBuilderInitialization() {
-                if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
-                }
-            }
-
-            private static Builder create() {
-                return new Builder();
-            }
-
-            public Builder clear() {
-                super.clear();
-                dpid_ = 0L;
-                bitField0_ = (bitField0_ & ~0x00000001);
-                status_ = 0;
-                bitField0_ = (bitField0_ & ~0x00000002);
-                value_ = com.google.protobuf.ByteString.EMPTY;
-                bitField0_ = (bitField0_ & ~0x00000004);
-                return this;
-            }
-
-            public Builder clone() {
-                return create().mergeFrom(buildPartial());
-            }
-
-            public com.google.protobuf.Descriptors.Descriptor
-            getDescriptorForType() {
-                return net.onrc.onos.core.datastore.RCProtos.internal_static_ProtoBuffer_SwitchProperty_descriptor;
-            }
-
-            public net.onrc.onos.core.datastore.RCProtos.SwitchProperty getDefaultInstanceForType() {
-                return net.onrc.onos.core.datastore.RCProtos.SwitchProperty.getDefaultInstance();
-            }
-
-            public net.onrc.onos.core.datastore.RCProtos.SwitchProperty build() {
-                net.onrc.onos.core.datastore.RCProtos.SwitchProperty result = buildPartial();
-                if (!result.isInitialized()) {
-                    throw newUninitializedMessageException(result);
-                }
-                return result;
-            }
-
-            public net.onrc.onos.core.datastore.RCProtos.SwitchProperty buildPartial() {
-                net.onrc.onos.core.datastore.RCProtos.SwitchProperty result = new net.onrc.onos.core.datastore.RCProtos.SwitchProperty(this);
-                int from_bitField0_ = bitField0_;
-                int to_bitField0_ = 0;
-                if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
-                    to_bitField0_ |= 0x00000001;
-                }
-                result.dpid_ = dpid_;
-                if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
-                    to_bitField0_ |= 0x00000002;
-                }
-                result.status_ = status_;
-                if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
-                    to_bitField0_ |= 0x00000004;
-                }
-                result.value_ = value_;
-                result.bitField0_ = to_bitField0_;
-                onBuilt();
-                return result;
-            }
-
-            public Builder mergeFrom(com.google.protobuf.Message other) {
-                if (other instanceof net.onrc.onos.core.datastore.RCProtos.SwitchProperty) {
-                    return mergeFrom((net.onrc.onos.core.datastore.RCProtos.SwitchProperty) other);
-                } else {
-                    super.mergeFrom(other);
-                    return this;
-                }
-            }
-
-            public Builder mergeFrom(net.onrc.onos.core.datastore.RCProtos.SwitchProperty other) {
-                if (other == net.onrc.onos.core.datastore.RCProtos.SwitchProperty.getDefaultInstance())
-                    return this;
-                if (other.hasDpid()) {
-                    setDpid(other.getDpid());
-                }
-                if (other.hasStatus()) {
-                    setStatus(other.getStatus());
-                }
-                if (other.hasValue()) {
-                    setValue(other.getValue());
-                }
-                this.mergeUnknownFields(other.getUnknownFields());
-                return this;
-            }
-
-            public final boolean isInitialized() {
-                if (!hasDpid()) {
-
-                    return false;
-                }
-                if (!hasStatus()) {
-
-                    return false;
-                }
-                return true;
-            }
-
-            public Builder mergeFrom(
-                    com.google.protobuf.CodedInputStream input,
-                    com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-                    throws java.io.IOException {
-                net.onrc.onos.core.datastore.RCProtos.SwitchProperty parsedMessage = null;
-                try {
-                    parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
-                } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-                    parsedMessage = (net.onrc.onos.core.datastore.RCProtos.SwitchProperty) e.getUnfinishedMessage();
-                    throw e;
-                } finally {
-                    if (parsedMessage != null) {
-                        mergeFrom(parsedMessage);
-                    }
-                }
-                return this;
-            }
-
-            private int bitField0_;
-
-            // required int64 dpid = 1;
-            private long dpid_;
-
-            /**
-             * <code>required int64 dpid = 1;</code>
-             */
-            public boolean hasDpid() {
-                return ((bitField0_ & 0x00000001) == 0x00000001);
-            }
-
-            /**
-             * <code>required int64 dpid = 1;</code>
-             */
-            public long getDpid() {
-                return dpid_;
-            }
-
-            /**
-             * <code>required int64 dpid = 1;</code>
-             */
-            public Builder setDpid(long value) {
-                bitField0_ |= 0x00000001;
-                dpid_ = value;
-                onChanged();
-                return this;
-            }
-
-            /**
-             * <code>required int64 dpid = 1;</code>
-             */
-            public Builder clearDpid() {
-                bitField0_ = (bitField0_ & ~0x00000001);
-                dpid_ = 0L;
-                onChanged();
-                return this;
-            }
-
-            // required int32 status = 2;
-            private int status_;
-
-            /**
-             * <code>required int32 status = 2;</code>
-             */
-            public boolean hasStatus() {
-                return ((bitField0_ & 0x00000002) == 0x00000002);
-            }
-
-            /**
-             * <code>required int32 status = 2;</code>
-             */
-            public int getStatus() {
-                return status_;
-            }
-
-            /**
-             * <code>required int32 status = 2;</code>
-             */
-            public Builder setStatus(int value) {
-                bitField0_ |= 0x00000002;
-                status_ = value;
-                onChanged();
-                return this;
-            }
-
-            /**
-             * <code>required int32 status = 2;</code>
-             */
-            public Builder clearStatus() {
-                bitField0_ = (bitField0_ & ~0x00000002);
-                status_ = 0;
-                onChanged();
-                return this;
-            }
-
-            // optional bytes value = 3;
-            private com.google.protobuf.ByteString value_ = com.google.protobuf.ByteString.EMPTY;
-
-            /**
-             * <code>optional bytes value = 3;</code>
-             */
-            public boolean hasValue() {
-                return ((bitField0_ & 0x00000004) == 0x00000004);
-            }
-
-            /**
-             * <code>optional bytes value = 3;</code>
-             */
-            public com.google.protobuf.ByteString getValue() {
-                return value_;
-            }
-
-            /**
-             * <code>optional bytes value = 3;</code>
-             */
-            public Builder setValue(com.google.protobuf.ByteString value) {
-                if (value == null) {
-                    throw new NullPointerException();
-                }
-                bitField0_ |= 0x00000004;
-                value_ = value;
-                onChanged();
-                return this;
-            }
-
-            /**
-             * <code>optional bytes value = 3;</code>
-             */
-            public Builder clearValue() {
-                bitField0_ = (bitField0_ & ~0x00000004);
-                value_ = getDefaultInstance().getValue();
-                onChanged();
-                return this;
-            }
-
-            // @@protoc_insertion_point(builder_scope:RCProtos.SwitchProperty)
-        }
-
-        static {
-            defaultInstance = new SwitchProperty(true);
-            defaultInstance.initFields();
-        }
-
-        // @@protoc_insertion_point(class_scope:RCProtos.SwitchProperty)
-    }
-
-    public interface PortPropertyOrBuilder
-            extends com.google.protobuf.MessageOrBuilder {
-
-        // required int64 dpid = 1;
-
-        /**
-         * <code>required int64 dpid = 1;</code>
-         */
-        boolean hasDpid();
-
-        /**
-         * <code>required int64 dpid = 1;</code>
-         */
-        long getDpid();
-
-        // required int64 number = 2;
-
-        /**
-         * <code>required int64 number = 2;</code>
-         */
-        boolean hasNumber();
-
-        /**
-         * <code>required int64 number = 2;</code>
-         */
-        long getNumber();
-
-        // required int32 status = 3;
-
-        /**
-         * <code>required int32 status = 3;</code>
-         */
-        boolean hasStatus();
-
-        /**
-         * <code>required int32 status = 3;</code>
-         */
-        int getStatus();
-
-        // optional bytes value = 4;
-
-        /**
-         * <code>optional bytes value = 4;</code>
-         */
-        boolean hasValue();
-
-        /**
-         * <code>optional bytes value = 4;</code>
-         */
-        com.google.protobuf.ByteString getValue();
-    }
-
-    /**
-     * Protobuf type {@code RCProtos.PortProperty}
-     */
-    public static final class PortProperty extends
-            com.google.protobuf.GeneratedMessage
-            implements PortPropertyOrBuilder {
-        // Use PortProperty.newBuilder() to construct.
-        private PortProperty(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
-            super(builder);
-            this.unknownFields = builder.getUnknownFields();
-        }
-
-        private PortProperty(boolean noInit) {
-            this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance();
-        }
-
-        private static final PortProperty defaultInstance;
-
-        public static PortProperty getDefaultInstance() {
-            return defaultInstance;
-        }
-
-        public PortProperty getDefaultInstanceForType() {
-            return defaultInstance;
-        }
-
-        private final com.google.protobuf.UnknownFieldSet unknownFields;
-
-        @java.lang.Override
-        public final com.google.protobuf.UnknownFieldSet
-        getUnknownFields() {
-            return this.unknownFields;
-        }
-
-        private PortProperty(
-                com.google.protobuf.CodedInputStream input,
-                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-                throws com.google.protobuf.InvalidProtocolBufferException {
-            initFields();
-            int mutable_bitField0_ = 0;
-            com.google.protobuf.UnknownFieldSet.Builder unknownFields =
-                    com.google.protobuf.UnknownFieldSet.newBuilder();
-            try {
-                boolean done = false;
-                while (!done) {
-                    int tag = input.readTag();
-                    switch (tag) {
-                        case 0:
-                            done = true;
-                            break;
-                        default: {
-                            if (!parseUnknownField(input, unknownFields,
-                                    extensionRegistry, tag)) {
-                                done = true;
-                            }
-                            break;
-                        }
-                        case 8: {
-                            bitField0_ |= 0x00000001;
-                            dpid_ = input.readInt64();
-                            break;
-                        }
-                        case 16: {
-                            bitField0_ |= 0x00000002;
-                            number_ = input.readInt64();
-                            break;
-                        }
-                        case 24: {
-                            bitField0_ |= 0x00000004;
-                            status_ = input.readInt32();
-                            break;
-                        }
-                        case 34: {
-                            bitField0_ |= 0x00000008;
-                            value_ = input.readBytes();
-                            break;
-                        }
-                    }
-                }
-            } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-                throw e.setUnfinishedMessage(this);
-            } catch (java.io.IOException e) {
-                throw new com.google.protobuf.InvalidProtocolBufferException(
-                        e.getMessage()).setUnfinishedMessage(this);
-            } finally {
-                this.unknownFields = unknownFields.build();
-                makeExtensionsImmutable();
-            }
-        }
-
-        public static final com.google.protobuf.Descriptors.Descriptor
-        getDescriptor() {
-            return net.onrc.onos.core.datastore.RCProtos.internal_static_ProtoBuffer_PortProperty_descriptor;
-        }
-
-        protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
-        internalGetFieldAccessorTable() {
-            return net.onrc.onos.core.datastore.RCProtos.internal_static_ProtoBuffer_PortProperty_fieldAccessorTable
-                    .ensureFieldAccessorsInitialized(
-                            net.onrc.onos.core.datastore.RCProtos.PortProperty.class, net.onrc.onos.core.datastore.RCProtos.PortProperty.Builder.class);
-        }
-
-        public static com.google.protobuf.Parser<PortProperty> PARSER =
-                new com.google.protobuf.AbstractParser<PortProperty>() {
-                    public PortProperty parsePartialFrom(
-                            com.google.protobuf.CodedInputStream input,
-                            com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-                            throws com.google.protobuf.InvalidProtocolBufferException {
-                        return new PortProperty(input, extensionRegistry);
-                    }
-                };
-
-        @java.lang.Override
-        public com.google.protobuf.Parser<PortProperty> getParserForType() {
-            return PARSER;
-        }
-
-        private int bitField0_;
-        // required int64 dpid = 1;
-        public static final int DPID_FIELD_NUMBER = 1;
-        private long dpid_;
-
-        /**
-         * <code>required int64 dpid = 1;</code>
-         */
-        public boolean hasDpid() {
-            return ((bitField0_ & 0x00000001) == 0x00000001);
-        }
-
-        /**
-         * <code>required int64 dpid = 1;</code>
-         */
-        public long getDpid() {
-            return dpid_;
-        }
-
-        // required int64 number = 2;
-        public static final int NUMBER_FIELD_NUMBER = 2;
-        private long number_;
-
-        /**
-         * <code>required int64 number = 2;</code>
-         */
-        public boolean hasNumber() {
-            return ((bitField0_ & 0x00000002) == 0x00000002);
-        }
-
-        /**
-         * <code>required int64 number = 2;</code>
-         */
-        public long getNumber() {
-            return number_;
-        }
-
-        // required int32 status = 3;
-        public static final int STATUS_FIELD_NUMBER = 3;
-        private int status_;
-
-        /**
-         * <code>required int32 status = 3;</code>
-         */
-        public boolean hasStatus() {
-            return ((bitField0_ & 0x00000004) == 0x00000004);
-        }
-
-        /**
-         * <code>required int32 status = 3;</code>
-         */
-        public int getStatus() {
-            return status_;
-        }
-
-        // optional bytes value = 4;
-        public static final int VALUE_FIELD_NUMBER = 4;
-        private com.google.protobuf.ByteString value_;
-
-        /**
-         * <code>optional bytes value = 4;</code>
-         */
-        public boolean hasValue() {
-            return ((bitField0_ & 0x00000008) == 0x00000008);
-        }
-
-        /**
-         * <code>optional bytes value = 4;</code>
-         */
-        public com.google.protobuf.ByteString getValue() {
-            return value_;
-        }
-
-        private void initFields() {
-            dpid_ = 0L;
-            number_ = 0L;
-            status_ = 0;
-            value_ = com.google.protobuf.ByteString.EMPTY;
-        }
-
-        private byte memoizedIsInitialized = -1;
-
-        public final boolean isInitialized() {
-            byte isInitialized = memoizedIsInitialized;
-            if (isInitialized != -1) return isInitialized == 1;
-
-            if (!hasDpid()) {
-                memoizedIsInitialized = 0;
-                return false;
-            }
-            if (!hasNumber()) {
-                memoizedIsInitialized = 0;
-                return false;
-            }
-            if (!hasStatus()) {
-                memoizedIsInitialized = 0;
-                return false;
-            }
-            memoizedIsInitialized = 1;
-            return true;
-        }
-
-        public void writeTo(com.google.protobuf.CodedOutputStream output)
-                throws java.io.IOException {
-            getSerializedSize();
-            if (((bitField0_ & 0x00000001) == 0x00000001)) {
-                output.writeInt64(1, dpid_);
-            }
-            if (((bitField0_ & 0x00000002) == 0x00000002)) {
-                output.writeInt64(2, number_);
-            }
-            if (((bitField0_ & 0x00000004) == 0x00000004)) {
-                output.writeInt32(3, status_);
-            }
-            if (((bitField0_ & 0x00000008) == 0x00000008)) {
-                output.writeBytes(4, value_);
-            }
-            getUnknownFields().writeTo(output);
-        }
-
-        private int memoizedSerializedSize = -1;
-
-        public int getSerializedSize() {
-            int size = memoizedSerializedSize;
-            if (size != -1) return size;
-
-            size = 0;
-            if (((bitField0_ & 0x00000001) == 0x00000001)) {
-                size += com.google.protobuf.CodedOutputStream
-                        .computeInt64Size(1, dpid_);
-            }
-            if (((bitField0_ & 0x00000002) == 0x00000002)) {
-                size += com.google.protobuf.CodedOutputStream
-                        .computeInt64Size(2, number_);
-            }
-            if (((bitField0_ & 0x00000004) == 0x00000004)) {
-                size += com.google.protobuf.CodedOutputStream
-                        .computeInt32Size(3, status_);
-            }
-            if (((bitField0_ & 0x00000008) == 0x00000008)) {
-                size += com.google.protobuf.CodedOutputStream
-                        .computeBytesSize(4, value_);
-            }
-            size += getUnknownFields().getSerializedSize();
-            memoizedSerializedSize = size;
-            return size;
-        }
-
-        private static final long serialVersionUID = 0L;
-
-        @java.lang.Override
-        protected java.lang.Object writeReplace()
-                throws java.io.ObjectStreamException {
-            return super.writeReplace();
-        }
-
-        public static net.onrc.onos.core.datastore.RCProtos.PortProperty parseFrom(
-                com.google.protobuf.ByteString data)
-                throws com.google.protobuf.InvalidProtocolBufferException {
-            return PARSER.parseFrom(data);
-        }
-
-        public static net.onrc.onos.core.datastore.RCProtos.PortProperty parseFrom(
-                com.google.protobuf.ByteString data,
-                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-                throws com.google.protobuf.InvalidProtocolBufferException {
-            return PARSER.parseFrom(data, extensionRegistry);
-        }
-
-        public static net.onrc.onos.core.datastore.RCProtos.PortProperty parseFrom(byte[] data)
-                throws com.google.protobuf.InvalidProtocolBufferException {
-            return PARSER.parseFrom(data);
-        }
-
-        public static net.onrc.onos.core.datastore.RCProtos.PortProperty parseFrom(
-                byte[] data,
-                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-                throws com.google.protobuf.InvalidProtocolBufferException {
-            return PARSER.parseFrom(data, extensionRegistry);
-        }
-
-        public static net.onrc.onos.core.datastore.RCProtos.PortProperty parseFrom(java.io.InputStream input)
-                throws java.io.IOException {
-            return PARSER.parseFrom(input);
-        }
-
-        public static net.onrc.onos.core.datastore.RCProtos.PortProperty parseFrom(
-                java.io.InputStream input,
-                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-                throws java.io.IOException {
-            return PARSER.parseFrom(input, extensionRegistry);
-        }
-
-        public static net.onrc.onos.core.datastore.RCProtos.PortProperty parseDelimitedFrom(java.io.InputStream input)
-                throws java.io.IOException {
-            return PARSER.parseDelimitedFrom(input);
-        }
-
-        public static net.onrc.onos.core.datastore.RCProtos.PortProperty parseDelimitedFrom(
-                java.io.InputStream input,
-                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-                throws java.io.IOException {
-            return PARSER.parseDelimitedFrom(input, extensionRegistry);
-        }
-
-        public static net.onrc.onos.core.datastore.RCProtos.PortProperty parseFrom(
-                com.google.protobuf.CodedInputStream input)
-                throws java.io.IOException {
-            return PARSER.parseFrom(input);
-        }
-
-        public static net.onrc.onos.core.datastore.RCProtos.PortProperty parseFrom(
-                com.google.protobuf.CodedInputStream input,
-                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-                throws java.io.IOException {
-            return PARSER.parseFrom(input, extensionRegistry);
-        }
-
-        public static Builder newBuilder() {
-            return Builder.create();
-        }
-
-        public Builder newBuilderForType() {
-            return newBuilder();
-        }
-
-        public static Builder newBuilder(net.onrc.onos.core.datastore.RCProtos.PortProperty prototype) {
-            return newBuilder().mergeFrom(prototype);
-        }
-
-        public Builder toBuilder() {
-            return newBuilder(this);
-        }
-
-        @java.lang.Override
-        protected Builder newBuilderForType(
-                com.google.protobuf.GeneratedMessage.BuilderParent parent) {
-            Builder builder = new Builder(parent);
-            return builder;
-        }
-
-        /**
-         * Protobuf type {@code RCProtos.PortProperty}
-         */
-        public static final class Builder extends
-                com.google.protobuf.GeneratedMessage.Builder<Builder>
-                implements net.onrc.onos.core.datastore.RCProtos.PortPropertyOrBuilder {
-            public static final com.google.protobuf.Descriptors.Descriptor
-            getDescriptor() {
-                return net.onrc.onos.core.datastore.RCProtos.internal_static_ProtoBuffer_PortProperty_descriptor;
-            }
-
-            protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
-            internalGetFieldAccessorTable() {
-                return net.onrc.onos.core.datastore.RCProtos.internal_static_ProtoBuffer_PortProperty_fieldAccessorTable
-                        .ensureFieldAccessorsInitialized(
-                                net.onrc.onos.core.datastore.RCProtos.PortProperty.class, net.onrc.onos.core.datastore.RCProtos.PortProperty.Builder.class);
-            }
-
-            // Construct using net.onrc.onos.core.datastore.RCProtos.PortProperty.newBuilder()
-            private Builder() {
-                maybeForceBuilderInitialization();
-            }
-
-            private Builder(
-                    com.google.protobuf.GeneratedMessage.BuilderParent parent) {
-                super(parent);
-                maybeForceBuilderInitialization();
-            }
-
-            private void maybeForceBuilderInitialization() {
-                if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
-                }
-            }
-
-            private static Builder create() {
-                return new Builder();
-            }
-
-            public Builder clear() {
-                super.clear();
-                dpid_ = 0L;
-                bitField0_ = (bitField0_ & ~0x00000001);
-                number_ = 0L;
-                bitField0_ = (bitField0_ & ~0x00000002);
-                status_ = 0;
-                bitField0_ = (bitField0_ & ~0x00000004);
-                value_ = com.google.protobuf.ByteString.EMPTY;
-                bitField0_ = (bitField0_ & ~0x00000008);
-                return this;
-            }
-
-            public Builder clone() {
-                return create().mergeFrom(buildPartial());
-            }
-
-            public com.google.protobuf.Descriptors.Descriptor
-            getDescriptorForType() {
-                return net.onrc.onos.core.datastore.RCProtos.internal_static_ProtoBuffer_PortProperty_descriptor;
-            }
-
-            public net.onrc.onos.core.datastore.RCProtos.PortProperty getDefaultInstanceForType() {
-                return net.onrc.onos.core.datastore.RCProtos.PortProperty.getDefaultInstance();
-            }
-
-            public net.onrc.onos.core.datastore.RCProtos.PortProperty build() {
-                net.onrc.onos.core.datastore.RCProtos.PortProperty result = buildPartial();
-                if (!result.isInitialized()) {
-                    throw newUninitializedMessageException(result);
-                }
-                return result;
-            }
-
-            public net.onrc.onos.core.datastore.RCProtos.PortProperty buildPartial() {
-                net.onrc.onos.core.datastore.RCProtos.PortProperty result = new net.onrc.onos.core.datastore.RCProtos.PortProperty(this);
-                int from_bitField0_ = bitField0_;
-                int to_bitField0_ = 0;
-                if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
-                    to_bitField0_ |= 0x00000001;
-                }
-                result.dpid_ = dpid_;
-                if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
-                    to_bitField0_ |= 0x00000002;
-                }
-                result.number_ = number_;
-                if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
-                    to_bitField0_ |= 0x00000004;
-                }
-                result.status_ = status_;
-                if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
-                    to_bitField0_ |= 0x00000008;
-                }
-                result.value_ = value_;
-                result.bitField0_ = to_bitField0_;
-                onBuilt();
-                return result;
-            }
-
-            public Builder mergeFrom(com.google.protobuf.Message other) {
-                if (other instanceof net.onrc.onos.core.datastore.RCProtos.PortProperty) {
-                    return mergeFrom((net.onrc.onos.core.datastore.RCProtos.PortProperty) other);
-                } else {
-                    super.mergeFrom(other);
-                    return this;
-                }
-            }
-
-            public Builder mergeFrom(net.onrc.onos.core.datastore.RCProtos.PortProperty other) {
-                if (other == net.onrc.onos.core.datastore.RCProtos.PortProperty.getDefaultInstance())
-                    return this;
-                if (other.hasDpid()) {
-                    setDpid(other.getDpid());
-                }
-                if (other.hasNumber()) {
-                    setNumber(other.getNumber());
-                }
-                if (other.hasStatus()) {
-                    setStatus(other.getStatus());
-                }
-                if (other.hasValue()) {
-                    setValue(other.getValue());
-                }
-                this.mergeUnknownFields(other.getUnknownFields());
-                return this;
-            }
-
-            public final boolean isInitialized() {
-                if (!hasDpid()) {
-
-                    return false;
-                }
-                if (!hasNumber()) {
-
-                    return false;
-                }
-                if (!hasStatus()) {
-
-                    return false;
-                }
-                return true;
-            }
-
-            public Builder mergeFrom(
-                    com.google.protobuf.CodedInputStream input,
-                    com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-                    throws java.io.IOException {
-                net.onrc.onos.core.datastore.RCProtos.PortProperty parsedMessage = null;
-                try {
-                    parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
-                } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-                    parsedMessage = (net.onrc.onos.core.datastore.RCProtos.PortProperty) e.getUnfinishedMessage();
-                    throw e;
-                } finally {
-                    if (parsedMessage != null) {
-                        mergeFrom(parsedMessage);
-                    }
-                }
-                return this;
-            }
-
-            private int bitField0_;
-
-            // required int64 dpid = 1;
-            private long dpid_;
-
-            /**
-             * <code>required int64 dpid = 1;</code>
-             */
-            public boolean hasDpid() {
-                return ((bitField0_ & 0x00000001) == 0x00000001);
-            }
-
-            /**
-             * <code>required int64 dpid = 1;</code>
-             */
-            public long getDpid() {
-                return dpid_;
-            }
-
-            /**
-             * <code>required int64 dpid = 1;</code>
-             */
-            public Builder setDpid(long value) {
-                bitField0_ |= 0x00000001;
-                dpid_ = value;
-                onChanged();
-                return this;
-            }
-
-            /**
-             * <code>required int64 dpid = 1;</code>
-             */
-            public Builder clearDpid() {
-                bitField0_ = (bitField0_ & ~0x00000001);
-                dpid_ = 0L;
-                onChanged();
-                return this;
-            }
-
-            // required int64 number = 2;
-            private long number_;
-
-            /**
-             * <code>required int64 number = 2;</code>
-             */
-            public boolean hasNumber() {
-                return ((bitField0_ & 0x00000002) == 0x00000002);
-            }
-
-            /**
-             * <code>required int64 number = 2;</code>
-             */
-            public long getNumber() {
-                return number_;
-            }
-
-            /**
-             * <code>required int64 number = 2;</code>
-             */
-            public Builder setNumber(long value) {
-                bitField0_ |= 0x00000002;
-                number_ = value;
-                onChanged();
-                return this;
-            }
-
-            /**
-             * <code>required int64 number = 2;</code>
-             */
-            public Builder clearNumber() {
-                bitField0_ = (bitField0_ & ~0x00000002);
-                number_ = 0L;
-                onChanged();
-                return this;
-            }
-
-            // required int32 status = 3;
-            private int status_;
-
-            /**
-             * <code>required int32 status = 3;</code>
-             */
-            public boolean hasStatus() {
-                return ((bitField0_ & 0x00000004) == 0x00000004);
-            }
-
-            /**
-             * <code>required int32 status = 3;</code>
-             */
-            public int getStatus() {
-                return status_;
-            }
-
-            /**
-             * <code>required int32 status = 3;</code>
-             */
-            public Builder setStatus(int value) {
-                bitField0_ |= 0x00000004;
-                status_ = value;
-                onChanged();
-                return this;
-            }
-
-            /**
-             * <code>required int32 status = 3;</code>
-             */
-            public Builder clearStatus() {
-                bitField0_ = (bitField0_ & ~0x00000004);
-                status_ = 0;
-                onChanged();
-                return this;
-            }
-
-            // optional bytes value = 4;
-            private com.google.protobuf.ByteString value_ = com.google.protobuf.ByteString.EMPTY;
-
-            /**
-             * <code>optional bytes value = 4;</code>
-             */
-            public boolean hasValue() {
-                return ((bitField0_ & 0x00000008) == 0x00000008);
-            }
-
-            /**
-             * <code>optional bytes value = 4;</code>
-             */
-            public com.google.protobuf.ByteString getValue() {
-                return value_;
-            }
-
-            /**
-             * <code>optional bytes value = 4;</code>
-             */
-            public Builder setValue(com.google.protobuf.ByteString value) {
-                if (value == null) {
-                    throw new NullPointerException();
-                }
-                bitField0_ |= 0x00000008;
-                value_ = value;
-                onChanged();
-                return this;
-            }
-
-            /**
-             * <code>optional bytes value = 4;</code>
-             */
-            public Builder clearValue() {
-                bitField0_ = (bitField0_ & ~0x00000008);
-                value_ = getDefaultInstance().getValue();
-                onChanged();
-                return this;
-            }
-
-            // @@protoc_insertion_point(builder_scope:RCProtos.PortProperty)
-        }
-
-        static {
-            defaultInstance = new PortProperty(true);
-            defaultInstance.initFields();
-        }
-
-        // @@protoc_insertion_point(class_scope:RCProtos.PortProperty)
-    }
-
-    public interface LinkPropertyOrBuilder
-            extends com.google.protobuf.MessageOrBuilder {
-
-        // required bytes srcSwId = 1;
-
-        /**
-         * <code>required bytes srcSwId = 1;</code>
-         */
-        boolean hasSrcSwId();
-
-        /**
-         * <code>required bytes srcSwId = 1;</code>
-         */
-        com.google.protobuf.ByteString getSrcSwId();
-
-        // required bytes srcPortId = 2;
-
-        /**
-         * <code>required bytes srcPortId = 2;</code>
-         */
-        boolean hasSrcPortId();
-
-        /**
-         * <code>required bytes srcPortId = 2;</code>
-         */
-        com.google.protobuf.ByteString getSrcPortId();
-
-        // required bytes dstSwId = 3;
-
-        /**
-         * <code>required bytes dstSwId = 3;</code>
-         */
-        boolean hasDstSwId();
-
-        /**
-         * <code>required bytes dstSwId = 3;</code>
-         */
-        com.google.protobuf.ByteString getDstSwId();
-
-        // required bytes dstPortId = 4;
-
-        /**
-         * <code>required bytes dstPortId = 4;</code>
-         */
-        boolean hasDstPortId();
-
-        /**
-         * <code>required bytes dstPortId = 4;</code>
-         */
-        com.google.protobuf.ByteString getDstPortId();
-
-        // required int32 status = 5;
-
-        /**
-         * <code>required int32 status = 5;</code>
-         */
-        boolean hasStatus();
-
-        /**
-         * <code>required int32 status = 5;</code>
-         */
-        int getStatus();
-
-        // optional bytes value = 6;
-
-        /**
-         * <code>optional bytes value = 6;</code>
-         */
-        boolean hasValue();
-
-        /**
-         * <code>optional bytes value = 6;</code>
-         */
-        com.google.protobuf.ByteString getValue();
-    }
-
-    /**
-     * Protobuf type {@code RCProtos.LinkProperty}
-     */
-    public static final class LinkProperty extends
-            com.google.protobuf.GeneratedMessage
-            implements LinkPropertyOrBuilder {
-        // Use LinkProperty.newBuilder() to construct.
-        private LinkProperty(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
-            super(builder);
-            this.unknownFields = builder.getUnknownFields();
-        }
-
-        private LinkProperty(boolean noInit) {
-            this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance();
-        }
-
-        private static final LinkProperty defaultInstance;
-
-        public static LinkProperty getDefaultInstance() {
-            return defaultInstance;
-        }
-
-        public LinkProperty getDefaultInstanceForType() {
-            return defaultInstance;
-        }
-
-        private final com.google.protobuf.UnknownFieldSet unknownFields;
-
-        @java.lang.Override
-        public final com.google.protobuf.UnknownFieldSet
-        getUnknownFields() {
-            return this.unknownFields;
-        }
-
-        private LinkProperty(
-                com.google.protobuf.CodedInputStream input,
-                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-                throws com.google.protobuf.InvalidProtocolBufferException {
-            initFields();
-            int mutable_bitField0_ = 0;
-            com.google.protobuf.UnknownFieldSet.Builder unknownFields =
-                    com.google.protobuf.UnknownFieldSet.newBuilder();
-            try {
-                boolean done = false;
-                while (!done) {
-                    int tag = input.readTag();
-                    switch (tag) {
-                        case 0:
-                            done = true;
-                            break;
-                        default: {
-                            if (!parseUnknownField(input, unknownFields,
-                                    extensionRegistry, tag)) {
-                                done = true;
-                            }
-                            break;
-                        }
-                        case 10: {
-                            bitField0_ |= 0x00000001;
-                            srcSwId_ = input.readBytes();
-                            break;
-                        }
-                        case 18: {
-                            bitField0_ |= 0x00000002;
-                            srcPortId_ = input.readBytes();
-                            break;
-                        }
-                        case 26: {
-                            bitField0_ |= 0x00000004;
-                            dstSwId_ = input.readBytes();
-                            break;
-                        }
-                        case 34: {
-                            bitField0_ |= 0x00000008;
-                            dstPortId_ = input.readBytes();
-                            break;
-                        }
-                        case 40: {
-                            bitField0_ |= 0x00000010;
-                            status_ = input.readInt32();
-                            break;
-                        }
-                        case 50: {
-                            bitField0_ |= 0x00000020;
-                            value_ = input.readBytes();
-                            break;
-                        }
-                    }
-                }
-            } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-                throw e.setUnfinishedMessage(this);
-            } catch (java.io.IOException e) {
-                throw new com.google.protobuf.InvalidProtocolBufferException(
-                        e.getMessage()).setUnfinishedMessage(this);
-            } finally {
-                this.unknownFields = unknownFields.build();
-                makeExtensionsImmutable();
-            }
-        }
-
-        public static final com.google.protobuf.Descriptors.Descriptor
-        getDescriptor() {
-            return net.onrc.onos.core.datastore.RCProtos.internal_static_ProtoBuffer_LinkProperty_descriptor;
-        }
-
-        protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
-        internalGetFieldAccessorTable() {
-            return net.onrc.onos.core.datastore.RCProtos.internal_static_ProtoBuffer_LinkProperty_fieldAccessorTable
-                    .ensureFieldAccessorsInitialized(
-                            net.onrc.onos.core.datastore.RCProtos.LinkProperty.class, net.onrc.onos.core.datastore.RCProtos.LinkProperty.Builder.class);
-        }
-
-        public static com.google.protobuf.Parser<LinkProperty> PARSER =
-                new com.google.protobuf.AbstractParser<LinkProperty>() {
-                    public LinkProperty parsePartialFrom(
-                            com.google.protobuf.CodedInputStream input,
-                            com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-                            throws com.google.protobuf.InvalidProtocolBufferException {
-                        return new LinkProperty(input, extensionRegistry);
-                    }
-                };
-
-        @java.lang.Override
-        public com.google.protobuf.Parser<LinkProperty> getParserForType() {
-            return PARSER;
-        }
-
-        private int bitField0_;
-        // required bytes srcSwId = 1;
-        public static final int SRCSWID_FIELD_NUMBER = 1;
-        private com.google.protobuf.ByteString srcSwId_;
-
-        /**
-         * <code>required bytes srcSwId = 1;</code>
-         */
-        public boolean hasSrcSwId() {
-            return ((bitField0_ & 0x00000001) == 0x00000001);
-        }
-
-        /**
-         * <code>required bytes srcSwId = 1;</code>
-         */
-        public com.google.protobuf.ByteString getSrcSwId() {
-            return srcSwId_;
-        }
-
-        // required bytes srcPortId = 2;
-        public static final int SRCPORTID_FIELD_NUMBER = 2;
-        private com.google.protobuf.ByteString srcPortId_;
-
-        /**
-         * <code>required bytes srcPortId = 2;</code>
-         */
-        public boolean hasSrcPortId() {
-            return ((bitField0_ & 0x00000002) == 0x00000002);
-        }
-
-        /**
-         * <code>required bytes srcPortId = 2;</code>
-         */
-        public com.google.protobuf.ByteString getSrcPortId() {
-            return srcPortId_;
-        }
-
-        // required bytes dstSwId = 3;
-        public static final int DSTSWID_FIELD_NUMBER = 3;
-        private com.google.protobuf.ByteString dstSwId_;
-
-        /**
-         * <code>required bytes dstSwId = 3;</code>
-         */
-        public boolean hasDstSwId() {
-            return ((bitField0_ & 0x00000004) == 0x00000004);
-        }
-
-        /**
-         * <code>required bytes dstSwId = 3;</code>
-         */
-        public com.google.protobuf.ByteString getDstSwId() {
-            return dstSwId_;
-        }
-
-        // required bytes dstPortId = 4;
-        public static final int DSTPORTID_FIELD_NUMBER = 4;
-        private com.google.protobuf.ByteString dstPortId_;
-
-        /**
-         * <code>required bytes dstPortId = 4;</code>
-         */
-        public boolean hasDstPortId() {
-            return ((bitField0_ & 0x00000008) == 0x00000008);
-        }
-
-        /**
-         * <code>required bytes dstPortId = 4;</code>
-         */
-        public com.google.protobuf.ByteString getDstPortId() {
-            return dstPortId_;
-        }
-
-        // required int32 status = 5;
-        public static final int STATUS_FIELD_NUMBER = 5;
-        private int status_;
-
-        /**
-         * <code>required int32 status = 5;</code>
-         */
-        public boolean hasStatus() {
-            return ((bitField0_ & 0x00000010) == 0x00000010);
-        }
-
-        /**
-         * <code>required int32 status = 5;</code>
-         */
-        public int getStatus() {
-            return status_;
-        }
-
-        // optional bytes value = 6;
-        public static final int VALUE_FIELD_NUMBER = 6;
-        private com.google.protobuf.ByteString value_;
-
-        /**
-         * <code>optional bytes value = 6;</code>
-         */
-        public boolean hasValue() {
-            return ((bitField0_ & 0x00000020) == 0x00000020);
-        }
-
-        /**
-         * <code>optional bytes value = 6;</code>
-         */
-        public com.google.protobuf.ByteString getValue() {
-            return value_;
-        }
-
-        private void initFields() {
-            srcSwId_ = com.google.protobuf.ByteString.EMPTY;
-            srcPortId_ = com.google.protobuf.ByteString.EMPTY;
-            dstSwId_ = com.google.protobuf.ByteString.EMPTY;
-            dstPortId_ = com.google.protobuf.ByteString.EMPTY;
-            status_ = 0;
-            value_ = com.google.protobuf.ByteString.EMPTY;
-        }
-
-        private byte memoizedIsInitialized = -1;
-
-        public final boolean isInitialized() {
-            byte isInitialized = memoizedIsInitialized;
-            if (isInitialized != -1) return isInitialized == 1;
-
-            if (!hasSrcSwId()) {
-                memoizedIsInitialized = 0;
-                return false;
-            }
-            if (!hasSrcPortId()) {
-                memoizedIsInitialized = 0;
-                return false;
-            }
-            if (!hasDstSwId()) {
-                memoizedIsInitialized = 0;
-                return false;
-            }
-            if (!hasDstPortId()) {
-                memoizedIsInitialized = 0;
-                return false;
-            }
-            if (!hasStatus()) {
-                memoizedIsInitialized = 0;
-                return false;
-            }
-            memoizedIsInitialized = 1;
-            return true;
-        }
-
-        public void writeTo(com.google.protobuf.CodedOutputStream output)
-                throws java.io.IOException {
-            getSerializedSize();
-            if (((bitField0_ & 0x00000001) == 0x00000001)) {
-                output.writeBytes(1, srcSwId_);
-            }
-            if (((bitField0_ & 0x00000002) == 0x00000002)) {
-                output.writeBytes(2, srcPortId_);
-            }
-            if (((bitField0_ & 0x00000004) == 0x00000004)) {
-                output.writeBytes(3, dstSwId_);
-            }
-            if (((bitField0_ & 0x00000008) == 0x00000008)) {
-                output.writeBytes(4, dstPortId_);
-            }
-            if (((bitField0_ & 0x00000010) == 0x00000010)) {
-                output.writeInt32(5, status_);
-            }
-            if (((bitField0_ & 0x00000020) == 0x00000020)) {
-                output.writeBytes(6, value_);
-            }
-            getUnknownFields().writeTo(output);
-        }
-
-        private int memoizedSerializedSize = -1;
-
-        public int getSerializedSize() {
-            int size = memoizedSerializedSize;
-            if (size != -1) return size;
-
-            size = 0;
-            if (((bitField0_ & 0x00000001) == 0x00000001)) {
-                size += com.google.protobuf.CodedOutputStream
-                        .computeBytesSize(1, srcSwId_);
-            }
-            if (((bitField0_ & 0x00000002) == 0x00000002)) {
-                size += com.google.protobuf.CodedOutputStream
-                        .computeBytesSize(2, srcPortId_);
-            }
-            if (((bitField0_ & 0x00000004) == 0x00000004)) {
-                size += com.google.protobuf.CodedOutputStream
-                        .computeBytesSize(3, dstSwId_);
-            }
-            if (((bitField0_ & 0x00000008) == 0x00000008)) {
-                size += com.google.protobuf.CodedOutputStream
-                        .computeBytesSize(4, dstPortId_);
-            }
-            if (((bitField0_ & 0x00000010) == 0x00000010)) {
-                size += com.google.protobuf.CodedOutputStream
-                        .computeInt32Size(5, status_);
-            }
-            if (((bitField0_ & 0x00000020) == 0x00000020)) {
-                size += com.google.protobuf.CodedOutputStream
-                        .computeBytesSize(6, value_);
-            }
-            size += getUnknownFields().getSerializedSize();
-            memoizedSerializedSize = size;
-            return size;
-        }
-
-        private static final long serialVersionUID = 0L;
-
-        @java.lang.Override
-        protected java.lang.Object writeReplace()
-                throws java.io.ObjectStreamException {
-            return super.writeReplace();
-        }
-
-        public static net.onrc.onos.core.datastore.RCProtos.LinkProperty parseFrom(
-                com.google.protobuf.ByteString data)
-                throws com.google.protobuf.InvalidProtocolBufferException {
-            return PARSER.parseFrom(data);
-        }
-
-        public static net.onrc.onos.core.datastore.RCProtos.LinkProperty parseFrom(
-                com.google.protobuf.ByteString data,
-                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-                throws com.google.protobuf.InvalidProtocolBufferException {
-            return PARSER.parseFrom(data, extensionRegistry);
-        }
-
-        public static net.onrc.onos.core.datastore.RCProtos.LinkProperty parseFrom(byte[] data)
-                throws com.google.protobuf.InvalidProtocolBufferException {
-            return PARSER.parseFrom(data);
-        }
-
-        public static net.onrc.onos.core.datastore.RCProtos.LinkProperty parseFrom(
-                byte[] data,
-                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-                throws com.google.protobuf.InvalidProtocolBufferException {
-            return PARSER.parseFrom(data, extensionRegistry);
-        }
-
-        public static net.onrc.onos.core.datastore.RCProtos.LinkProperty parseFrom(java.io.InputStream input)
-                throws java.io.IOException {
-            return PARSER.parseFrom(input);
-        }
-
-        public static net.onrc.onos.core.datastore.RCProtos.LinkProperty parseFrom(
-                java.io.InputStream input,
-                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-                throws java.io.IOException {
-            return PARSER.parseFrom(input, extensionRegistry);
-        }
-
-        public static net.onrc.onos.core.datastore.RCProtos.LinkProperty parseDelimitedFrom(java.io.InputStream input)
-                throws java.io.IOException {
-            return PARSER.parseDelimitedFrom(input);
-        }
-
-        public static net.onrc.onos.core.datastore.RCProtos.LinkProperty parseDelimitedFrom(
-                java.io.InputStream input,
-                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-                throws java.io.IOException {
-            return PARSER.parseDelimitedFrom(input, extensionRegistry);
-        }
-
-        public static net.onrc.onos.core.datastore.RCProtos.LinkProperty parseFrom(
-                com.google.protobuf.CodedInputStream input)
-                throws java.io.IOException {
-            return PARSER.parseFrom(input);
-        }
-
-        public static net.onrc.onos.core.datastore.RCProtos.LinkProperty parseFrom(
-                com.google.protobuf.CodedInputStream input,
-                com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-                throws java.io.IOException {
-            return PARSER.parseFrom(input, extensionRegistry);
-        }
-
-        public static Builder newBuilder() {
-            return Builder.create();
-        }
-
-        public Builder newBuilderForType() {
-            return newBuilder();
-        }
-
-        public static Builder newBuilder(net.onrc.onos.core.datastore.RCProtos.LinkProperty prototype) {
-            return newBuilder().mergeFrom(prototype);
-        }
-
-        public Builder toBuilder() {
-            return newBuilder(this);
-        }
-
-        @java.lang.Override
-        protected Builder newBuilderForType(
-                com.google.protobuf.GeneratedMessage.BuilderParent parent) {
-            Builder builder = new Builder(parent);
-            return builder;
-        }
-
-        /**
-         * Protobuf type {@code RCProtos.LinkProperty}
-         */
-        public static final class Builder extends
-                com.google.protobuf.GeneratedMessage.Builder<Builder>
-                implements net.onrc.onos.core.datastore.RCProtos.LinkPropertyOrBuilder {
-            public static final com.google.protobuf.Descriptors.Descriptor
-            getDescriptor() {
-                return net.onrc.onos.core.datastore.RCProtos.internal_static_ProtoBuffer_LinkProperty_descriptor;
-            }
-
-            protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
-            internalGetFieldAccessorTable() {
-                return net.onrc.onos.core.datastore.RCProtos.internal_static_ProtoBuffer_LinkProperty_fieldAccessorTable
-                        .ensureFieldAccessorsInitialized(
-                                net.onrc.onos.core.datastore.RCProtos.LinkProperty.class, net.onrc.onos.core.datastore.RCProtos.LinkProperty.Builder.class);
-            }
-
-            // Construct using net.onrc.onos.core.datastore.RCProtos.LinkProperty.newBuilder()
-            private Builder() {
-                maybeForceBuilderInitialization();
-            }
-
-            private Builder(
-                    com.google.protobuf.GeneratedMessage.BuilderParent parent) {
-                super(parent);
-                maybeForceBuilderInitialization();
-            }
-
-            private void maybeForceBuilderInitialization() {
-                if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
-                }
-            }
-
-            private static Builder create() {
-                return new Builder();
-            }
-
-            public Builder clear() {
-                super.clear();
-                srcSwId_ = com.google.protobuf.ByteString.EMPTY;
-                bitField0_ = (bitField0_ & ~0x00000001);
-                srcPortId_ = com.google.protobuf.ByteString.EMPTY;
-                bitField0_ = (bitField0_ & ~0x00000002);
-                dstSwId_ = com.google.protobuf.ByteString.EMPTY;
-                bitField0_ = (bitField0_ & ~0x00000004);
-                dstPortId_ = com.google.protobuf.ByteString.EMPTY;
-                bitField0_ = (bitField0_ & ~0x00000008);
-                status_ = 0;
-                bitField0_ = (bitField0_ & ~0x00000010);
-                value_ = com.google.protobuf.ByteString.EMPTY;
-                bitField0_ = (bitField0_ & ~0x00000020);
-                return this;
-            }
-
-            public Builder clone() {
-                return create().mergeFrom(buildPartial());
-            }
-
-            public com.google.protobuf.Descriptors.Descriptor
-            getDescriptorForType() {
-                return net.onrc.onos.core.datastore.RCProtos.internal_static_ProtoBuffer_LinkProperty_descriptor;
-            }
-
-            public net.onrc.onos.core.datastore.RCProtos.LinkProperty getDefaultInstanceForType() {
-                return net.onrc.onos.core.datastore.RCProtos.LinkProperty.getDefaultInstance();
-            }
-
-            public net.onrc.onos.core.datastore.RCProtos.LinkProperty build() {
-                net.onrc.onos.core.datastore.RCProtos.LinkProperty result = buildPartial();
-                if (!result.isInitialized()) {
-                    throw newUninitializedMessageException(result);
-                }
-                return result;
-            }
-
-            public net.onrc.onos.core.datastore.RCProtos.LinkProperty buildPartial() {
-                net.onrc.onos.core.datastore.RCProtos.LinkProperty result = new net.onrc.onos.core.datastore.RCProtos.LinkProperty(this);
-                int from_bitField0_ = bitField0_;
-                int to_bitField0_ = 0;
-                if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
-                    to_bitField0_ |= 0x00000001;
-                }
-                result.srcSwId_ = srcSwId_;
-                if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
-                    to_bitField0_ |= 0x00000002;
-                }
-                result.srcPortId_ = srcPortId_;
-                if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
-                    to_bitField0_ |= 0x00000004;
-                }
-                result.dstSwId_ = dstSwId_;
-                if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
-                    to_bitField0_ |= 0x00000008;
-                }
-                result.dstPortId_ = dstPortId_;
-                if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
-                    to_bitField0_ |= 0x00000010;
-                }
-                result.status_ = status_;
-                if (((from_bitField0_ & 0x00000020) == 0x00000020)) {
-                    to_bitField0_ |= 0x00000020;
-                }
-                result.value_ = value_;
-                result.bitField0_ = to_bitField0_;
-                onBuilt();
-                return result;
-            }
-
-            public Builder mergeFrom(com.google.protobuf.Message other) {
-                if (other instanceof net.onrc.onos.core.datastore.RCProtos.LinkProperty) {
-                    return mergeFrom((net.onrc.onos.core.datastore.RCProtos.LinkProperty) other);
-                } else {
-                    super.mergeFrom(other);
-                    return this;
-                }
-            }
-
-            public Builder mergeFrom(net.onrc.onos.core.datastore.RCProtos.LinkProperty other) {
-                if (other == net.onrc.onos.core.datastore.RCProtos.LinkProperty.getDefaultInstance())
-                    return this;
-                if (other.hasSrcSwId()) {
-                    setSrcSwId(other.getSrcSwId());
-                }
-                if (other.hasSrcPortId()) {
-                    setSrcPortId(other.getSrcPortId());
-                }
-                if (other.hasDstSwId()) {
-                    setDstSwId(other.getDstSwId());
-                }
-                if (other.hasDstPortId()) {
-                    setDstPortId(other.getDstPortId());
-                }
-                if (other.hasStatus()) {
-                    setStatus(other.getStatus());
-                }
-                if (other.hasValue()) {
-                    setValue(other.getValue());
-                }
-                this.mergeUnknownFields(other.getUnknownFields());
-                return this;
-            }
-
-            public final boolean isInitialized() {
-                if (!hasSrcSwId()) {
-
-                    return false;
-                }
-                if (!hasSrcPortId()) {
-
-                    return false;
-                }
-                if (!hasDstSwId()) {
-
-                    return false;
-                }
-                if (!hasDstPortId()) {
-
-                    return false;
-                }
-                if (!hasStatus()) {
-
-                    return false;
-                }
-                return true;
-            }
-
-            public Builder mergeFrom(
-                    com.google.protobuf.CodedInputStream input,
-                    com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-                    throws java.io.IOException {
-                net.onrc.onos.core.datastore.RCProtos.LinkProperty parsedMessage = null;
-                try {
-                    parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
-                } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-                    parsedMessage = (net.onrc.onos.core.datastore.RCProtos.LinkProperty) e.getUnfinishedMessage();
-                    throw e;
-                } finally {
-                    if (parsedMessage != null) {
-                        mergeFrom(parsedMessage);
-                    }
-                }
-                return this;
-            }
-
-            private int bitField0_;
-
-            // required bytes srcSwId = 1;
-            private com.google.protobuf.ByteString srcSwId_ = com.google.protobuf.ByteString.EMPTY;
-
-            /**
-             * <code>required bytes srcSwId = 1;</code>
-             */
-            public boolean hasSrcSwId() {
-                return ((bitField0_ & 0x00000001) == 0x00000001);
-            }
-
-            /**
-             * <code>required bytes srcSwId = 1;</code>
-             */
-            public com.google.protobuf.ByteString getSrcSwId() {
-                return srcSwId_;
-            }
-
-            /**
-             * <code>required bytes srcSwId = 1;</code>
-             */
-            public Builder setSrcSwId(com.google.protobuf.ByteString value) {
-                if (value == null) {
-                    throw new NullPointerException();
-                }
-                bitField0_ |= 0x00000001;
-                srcSwId_ = value;
-                onChanged();
-                return this;
-            }
-
-            /**
-             * <code>required bytes srcSwId = 1;</code>
-             */
-            public Builder clearSrcSwId() {
-                bitField0_ = (bitField0_ & ~0x00000001);
-                srcSwId_ = getDefaultInstance().getSrcSwId();
-                onChanged();
-                return this;
-            }
-
-            // required bytes srcPortId = 2;
-            private com.google.protobuf.ByteString srcPortId_ = com.google.protobuf.ByteString.EMPTY;
-
-            /**
-             * <code>required bytes srcPortId = 2;</code>
-             */
-            public boolean hasSrcPortId() {
-                return ((bitField0_ & 0x00000002) == 0x00000002);
-            }
-
-            /**
-             * <code>required bytes srcPortId = 2;</code>
-             */
-            public com.google.protobuf.ByteString getSrcPortId() {
-                return srcPortId_;
-            }
-
-            /**
-             * <code>required bytes srcPortId = 2;</code>
-             */
-            public Builder setSrcPortId(com.google.protobuf.ByteString value) {
-                if (value == null) {
-                    throw new NullPointerException();
-                }
-                bitField0_ |= 0x00000002;
-                srcPortId_ = value;
-                onChanged();
-                return this;
-            }
-
-            /**
-             * <code>required bytes srcPortId = 2;</code>
-             */
-            public Builder clearSrcPortId() {
-                bitField0_ = (bitField0_ & ~0x00000002);
-                srcPortId_ = getDefaultInstance().getSrcPortId();
-                onChanged();
-                return this;
-            }
-
-            // required bytes dstSwId = 3;
-            private com.google.protobuf.ByteString dstSwId_ = com.google.protobuf.ByteString.EMPTY;
-
-            /**
-             * <code>required bytes dstSwId = 3;</code>
-             */
-            public boolean hasDstSwId() {
-                return ((bitField0_ & 0x00000004) == 0x00000004);
-            }
-
-            /**
-             * <code>required bytes dstSwId = 3;</code>
-             */
-            public com.google.protobuf.ByteString getDstSwId() {
-                return dstSwId_;
-            }
-
-            /**
-             * <code>required bytes dstSwId = 3;</code>
-             */
-            public Builder setDstSwId(com.google.protobuf.ByteString value) {
-                if (value == null) {
-                    throw new NullPointerException();
-                }
-                bitField0_ |= 0x00000004;
-                dstSwId_ = value;
-                onChanged();
-                return this;
-            }
-
-            /**
-             * <code>required bytes dstSwId = 3;</code>
-             */
-            public Builder clearDstSwId() {
-                bitField0_ = (bitField0_ & ~0x00000004);
-                dstSwId_ = getDefaultInstance().getDstSwId();
-                onChanged();
-                return this;
-            }
-
-            // required bytes dstPortId = 4;
-            private com.google.protobuf.ByteString dstPortId_ = com.google.protobuf.ByteString.EMPTY;
-
-            /**
-             * <code>required bytes dstPortId = 4;</code>
-             */
-            public boolean hasDstPortId() {
-                return ((bitField0_ & 0x00000008) == 0x00000008);
-            }
-
-            /**
-             * <code>required bytes dstPortId = 4;</code>
-             */
-            public com.google.protobuf.ByteString getDstPortId() {
-                return dstPortId_;
-            }
-
-            /**
-             * <code>required bytes dstPortId = 4;</code>
-             */
-            public Builder setDstPortId(com.google.protobuf.ByteString value) {
-                if (value == null) {
-                    throw new NullPointerException();
-                }
-                bitField0_ |= 0x00000008;
-                dstPortId_ = value;
-                onChanged();
-                return this;
-            }
-
-            /**
-             * <code>required bytes dstPortId = 4;</code>
-             */
-            public Builder clearDstPortId() {
-                bitField0_ = (bitField0_ & ~0x00000008);
-                dstPortId_ = getDefaultInstance().getDstPortId();
-                onChanged();
-                return this;
-            }
-
-            // required int32 status = 5;
-            private int status_;
-
-            /**
-             * <code>required int32 status = 5;</code>
-             */
-            public boolean hasStatus() {
-                return ((bitField0_ & 0x00000010) == 0x00000010);
-            }
-
-            /**
-             * <code>required int32 status = 5;</code>
-             */
-            public int getStatus() {
-                return status_;
-            }
-
-            /**
-             * <code>required int32 status = 5;</code>
-             */
-            public Builder setStatus(int value) {
-                bitField0_ |= 0x00000010;
-                status_ = value;
-                onChanged();
-                return this;
-            }
-
-            /**
-             * <code>required int32 status = 5;</code>
-             */
-            public Builder clearStatus() {
-                bitField0_ = (bitField0_ & ~0x00000010);
-                status_ = 0;
-                onChanged();
-                return this;
-            }
-
-            // optional bytes value = 6;
-            private com.google.protobuf.ByteString value_ = com.google.protobuf.ByteString.EMPTY;
-
-            /**
-             * <code>optional bytes value = 6;</code>
-             */
-            public boolean hasValue() {
-                return ((bitField0_ & 0x00000020) == 0x00000020);
-            }
-
-            /**
-             * <code>optional bytes value = 6;</code>
-             */
-            public com.google.protobuf.ByteString getValue() {
-                return value_;
-            }
-
-            /**
-             * <code>optional bytes value = 6;</code>
-             */
-            public Builder setValue(com.google.protobuf.ByteString value) {
-                if (value == null) {
-                    throw new NullPointerException();
-                }
-                bitField0_ |= 0x00000020;
-                value_ = value;
-                onChanged();
-                return this;
-            }
-
-            /**
-             * <code>optional bytes value = 6;</code>
-             */
-            public Builder clearValue() {
-                bitField0_ = (bitField0_ & ~0x00000020);
-                value_ = getDefaultInstance().getValue();
-                onChanged();
-                return this;
-            }
-
-            // @@protoc_insertion_point(builder_scope:RCProtos.LinkProperty)
-        }
-
-        static {
-            defaultInstance = new LinkProperty(true);
-            defaultInstance.initFields();
-        }
-
-        // @@protoc_insertion_point(class_scope:RCProtos.LinkProperty)
-    }
-
-    private static com.google.protobuf.Descriptors.Descriptor
-            internal_static_ProtoBuffer_SwitchProperty_descriptor;
-    private static
-    com.google.protobuf.GeneratedMessage.FieldAccessorTable
-            internal_static_ProtoBuffer_SwitchProperty_fieldAccessorTable;
-    private static com.google.protobuf.Descriptors.Descriptor
-            internal_static_ProtoBuffer_PortProperty_descriptor;
-    private static
-    com.google.protobuf.GeneratedMessage.FieldAccessorTable
-            internal_static_ProtoBuffer_PortProperty_fieldAccessorTable;
-    private static com.google.protobuf.Descriptors.Descriptor
-            internal_static_ProtoBuffer_LinkProperty_descriptor;
-    private static
-    com.google.protobuf.GeneratedMessage.FieldAccessorTable
-            internal_static_ProtoBuffer_LinkProperty_fieldAccessorTable;
-
-    public static com.google.protobuf.Descriptors.FileDescriptor
-    getDescriptor() {
-        return descriptor;
-    }
-
-    private static com.google.protobuf.Descriptors.FileDescriptor
-            descriptor;
-
-    static {
-        java.lang.String[] descriptorData = {
-                "\n\027protobuf/ramcloud.proto\022\013ProtoBuffer\"=" +
-                        "\n\016SwitchProperty\022\014\n\004dpid\030\001 \002(\003\022\016\n\006status" +
-                        "\030\002 \002(\005\022\r\n\005value\030\003 \001(\014\"K\n\014PortProperty\022\014\n" +
-                        "\004dpid\030\001 \002(\003\022\016\n\006number\030\002 \002(\003\022\016\n\006status\030\003 " +
-                        "\002(\005\022\r\n\005value\030\004 \001(\014\"u\n\014LinkProperty\022\017\n\007sr" +
-                        "cSwId\030\001 \002(\014\022\021\n\tsrcPortId\030\002 \002(\014\022\017\n\007dstSwI" +
-                        "d\030\003 \002(\014\022\021\n\tdstPortId\030\004 \002(\014\022\016\n\006status\030\005 \002" +
-                        "(\005\022\r\n\005value\030\006 \001(\014B&\n\027net.onrc.onos.datas" +
-                        "toreB\013ProtoBuffer"
-        };
-        com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
-                new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
-                    public com.google.protobuf.ExtensionRegistry assignDescriptors(
-                            com.google.protobuf.Descriptors.FileDescriptor root) {
-                        descriptor = root;
-                        internal_static_ProtoBuffer_SwitchProperty_descriptor =
-                                getDescriptor().getMessageTypes().get(0);
-                        internal_static_ProtoBuffer_SwitchProperty_fieldAccessorTable = new
-                                com.google.protobuf.GeneratedMessage.FieldAccessorTable(
-                                internal_static_ProtoBuffer_SwitchProperty_descriptor,
-                                new java.lang.String[]{"Dpid", "Status", "Value",});
-                        internal_static_ProtoBuffer_PortProperty_descriptor =
-                                getDescriptor().getMessageTypes().get(1);
-                        internal_static_ProtoBuffer_PortProperty_fieldAccessorTable = new
-                                com.google.protobuf.GeneratedMessage.FieldAccessorTable(
-                                internal_static_ProtoBuffer_PortProperty_descriptor,
-                                new java.lang.String[]{"Dpid", "Number", "Status", "Value",});
-                        internal_static_ProtoBuffer_LinkProperty_descriptor =
-                                getDescriptor().getMessageTypes().get(2);
-                        internal_static_ProtoBuffer_LinkProperty_fieldAccessorTable = new
-                                com.google.protobuf.GeneratedMessage.FieldAccessorTable(
-                                internal_static_ProtoBuffer_LinkProperty_descriptor,
-                                new java.lang.String[]{"SrcSwId", "SrcPortId", "DstSwId", "DstPortId", "Status", "Value",});
-                        return null;
-                    }
-                };
-        com.google.protobuf.Descriptors.FileDescriptor
-                .internalBuildGeneratedFileFrom(descriptorData,
-                        new com.google.protobuf.Descriptors.FileDescriptor[]{
-                        }, assigner);
-    }
-
-    // @@protoc_insertion_point(outer_class_scope)
-}
diff --git a/src/main/java/net/onrc/onos/core/datastore/serializers/Topology.java b/src/main/java/net/onrc/onos/core/datastore/serializers/Topology.java
new file mode 100644
index 0000000..06154f3
--- /dev/null
+++ b/src/main/java/net/onrc/onos/core/datastore/serializers/Topology.java
@@ -0,0 +1,2177 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: topology.proto
+
+package net.onrc.onos.core.datastore.serializers;
+
+public final class Topology {
+  private Topology() {}
+  public static void registerAllExtensions(
+      com.google.protobuf.ExtensionRegistry registry) {
+  }
+  public interface SwitchPropertyOrBuilder
+      extends com.google.protobuf.MessageOrBuilder {
+
+    // required int64 dpid = 1;
+    /**
+     * <code>required int64 dpid = 1;</code>
+     */
+    boolean hasDpid();
+    /**
+     * <code>required int64 dpid = 1;</code>
+     */
+    long getDpid();
+
+    // required int32 status = 2;
+    /**
+     * <code>required int32 status = 2;</code>
+     */
+    boolean hasStatus();
+    /**
+     * <code>required int32 status = 2;</code>
+     */
+    int getStatus();
+
+    // optional bytes value = 3;
+    /**
+     * <code>optional bytes value = 3;</code>
+     */
+    boolean hasValue();
+    /**
+     * <code>optional bytes value = 3;</code>
+     */
+    com.google.protobuf.ByteString getValue();
+  }
+  /**
+   * Protobuf type {@code topology.SwitchProperty}
+   */
+  public static final class SwitchProperty extends
+      com.google.protobuf.GeneratedMessage
+      implements SwitchPropertyOrBuilder {
+    // Use SwitchProperty.newBuilder() to construct.
+    private SwitchProperty(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private SwitchProperty(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final SwitchProperty defaultInstance;
+    public static SwitchProperty getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public SwitchProperty getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private SwitchProperty(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      int mutable_bitField0_ = 0;
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+            case 8: {
+              bitField0_ |= 0x00000001;
+              dpid_ = input.readInt64();
+              break;
+            }
+            case 16: {
+              bitField0_ |= 0x00000002;
+              status_ = input.readInt32();
+              break;
+            }
+            case 26: {
+              bitField0_ |= 0x00000004;
+              value_ = input.readBytes();
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return net.onrc.onos.core.datastore.serializers.Topology.internal_static_topology_SwitchProperty_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return net.onrc.onos.core.datastore.serializers.Topology.internal_static_topology_SwitchProperty_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              net.onrc.onos.core.datastore.serializers.Topology.SwitchProperty.class, net.onrc.onos.core.datastore.serializers.Topology.SwitchProperty.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<SwitchProperty> PARSER =
+        new com.google.protobuf.AbstractParser<SwitchProperty>() {
+      public SwitchProperty parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new SwitchProperty(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<SwitchProperty> getParserForType() {
+      return PARSER;
+    }
+
+    private int bitField0_;
+    // required int64 dpid = 1;
+    public static final int DPID_FIELD_NUMBER = 1;
+    private long dpid_;
+    /**
+     * <code>required int64 dpid = 1;</code>
+     */
+    public boolean hasDpid() {
+      return ((bitField0_ & 0x00000001) == 0x00000001);
+    }
+    /**
+     * <code>required int64 dpid = 1;</code>
+     */
+    public long getDpid() {
+      return dpid_;
+    }
+
+    // required int32 status = 2;
+    public static final int STATUS_FIELD_NUMBER = 2;
+    private int status_;
+    /**
+     * <code>required int32 status = 2;</code>
+     */
+    public boolean hasStatus() {
+      return ((bitField0_ & 0x00000002) == 0x00000002);
+    }
+    /**
+     * <code>required int32 status = 2;</code>
+     */
+    public int getStatus() {
+      return status_;
+    }
+
+    // optional bytes value = 3;
+    public static final int VALUE_FIELD_NUMBER = 3;
+    private com.google.protobuf.ByteString value_;
+    /**
+     * <code>optional bytes value = 3;</code>
+     */
+    public boolean hasValue() {
+      return ((bitField0_ & 0x00000004) == 0x00000004);
+    }
+    /**
+     * <code>optional bytes value = 3;</code>
+     */
+    public com.google.protobuf.ByteString getValue() {
+      return value_;
+    }
+
+    private void initFields() {
+      dpid_ = 0L;
+      status_ = 0;
+      value_ = com.google.protobuf.ByteString.EMPTY;
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized != -1) return isInitialized == 1;
+
+      if (!hasDpid()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      if (!hasStatus()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        output.writeInt64(1, dpid_);
+      }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        output.writeInt32(2, status_);
+      }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        output.writeBytes(3, value_);
+      }
+      getUnknownFields().writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt64Size(1, dpid_);
+      }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt32Size(2, status_);
+      }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(3, value_);
+      }
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
+    }
+
+    public static net.onrc.onos.core.datastore.serializers.Topology.SwitchProperty parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static net.onrc.onos.core.datastore.serializers.Topology.SwitchProperty parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static net.onrc.onos.core.datastore.serializers.Topology.SwitchProperty parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static net.onrc.onos.core.datastore.serializers.Topology.SwitchProperty parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static net.onrc.onos.core.datastore.serializers.Topology.SwitchProperty parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static net.onrc.onos.core.datastore.serializers.Topology.SwitchProperty parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static net.onrc.onos.core.datastore.serializers.Topology.SwitchProperty parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static net.onrc.onos.core.datastore.serializers.Topology.SwitchProperty parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static net.onrc.onos.core.datastore.serializers.Topology.SwitchProperty parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static net.onrc.onos.core.datastore.serializers.Topology.SwitchProperty parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(net.onrc.onos.core.datastore.serializers.Topology.SwitchProperty prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code topology.SwitchProperty}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder>
+       implements net.onrc.onos.core.datastore.serializers.Topology.SwitchPropertyOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return net.onrc.onos.core.datastore.serializers.Topology.internal_static_topology_SwitchProperty_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return net.onrc.onos.core.datastore.serializers.Topology.internal_static_topology_SwitchProperty_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                net.onrc.onos.core.datastore.serializers.Topology.SwitchProperty.class, net.onrc.onos.core.datastore.serializers.Topology.SwitchProperty.Builder.class);
+      }
+
+      // Construct using net.onrc.onos.core.datastore.serializers.Topology.SwitchProperty.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+
+      public Builder clear() {
+        super.clear();
+        dpid_ = 0L;
+        bitField0_ = (bitField0_ & ~0x00000001);
+        status_ = 0;
+        bitField0_ = (bitField0_ & ~0x00000002);
+        value_ = com.google.protobuf.ByteString.EMPTY;
+        bitField0_ = (bitField0_ & ~0x00000004);
+        return this;
+      }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return net.onrc.onos.core.datastore.serializers.Topology.internal_static_topology_SwitchProperty_descriptor;
+      }
+
+      public net.onrc.onos.core.datastore.serializers.Topology.SwitchProperty getDefaultInstanceForType() {
+        return net.onrc.onos.core.datastore.serializers.Topology.SwitchProperty.getDefaultInstance();
+      }
+
+      public net.onrc.onos.core.datastore.serializers.Topology.SwitchProperty build() {
+        net.onrc.onos.core.datastore.serializers.Topology.SwitchProperty result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public net.onrc.onos.core.datastore.serializers.Topology.SwitchProperty buildPartial() {
+        net.onrc.onos.core.datastore.serializers.Topology.SwitchProperty result = new net.onrc.onos.core.datastore.serializers.Topology.SwitchProperty(this);
+        int from_bitField0_ = bitField0_;
+        int to_bitField0_ = 0;
+        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+          to_bitField0_ |= 0x00000001;
+        }
+        result.dpid_ = dpid_;
+        if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+          to_bitField0_ |= 0x00000002;
+        }
+        result.status_ = status_;
+        if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+          to_bitField0_ |= 0x00000004;
+        }
+        result.value_ = value_;
+        result.bitField0_ = to_bitField0_;
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof net.onrc.onos.core.datastore.serializers.Topology.SwitchProperty) {
+          return mergeFrom((net.onrc.onos.core.datastore.serializers.Topology.SwitchProperty)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(net.onrc.onos.core.datastore.serializers.Topology.SwitchProperty other) {
+        if (other == net.onrc.onos.core.datastore.serializers.Topology.SwitchProperty.getDefaultInstance()) return this;
+        if (other.hasDpid()) {
+          setDpid(other.getDpid());
+        }
+        if (other.hasStatus()) {
+          setStatus(other.getStatus());
+        }
+        if (other.hasValue()) {
+          setValue(other.getValue());
+        }
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        if (!hasDpid()) {
+          
+          return false;
+        }
+        if (!hasStatus()) {
+          
+          return false;
+        }
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        net.onrc.onos.core.datastore.serializers.Topology.SwitchProperty parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (net.onrc.onos.core.datastore.serializers.Topology.SwitchProperty) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+      private int bitField0_;
+
+      // required int64 dpid = 1;
+      private long dpid_ ;
+      /**
+       * <code>required int64 dpid = 1;</code>
+       */
+      public boolean hasDpid() {
+        return ((bitField0_ & 0x00000001) == 0x00000001);
+      }
+      /**
+       * <code>required int64 dpid = 1;</code>
+       */
+      public long getDpid() {
+        return dpid_;
+      }
+      /**
+       * <code>required int64 dpid = 1;</code>
+       */
+      public Builder setDpid(long value) {
+        bitField0_ |= 0x00000001;
+        dpid_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required int64 dpid = 1;</code>
+       */
+      public Builder clearDpid() {
+        bitField0_ = (bitField0_ & ~0x00000001);
+        dpid_ = 0L;
+        onChanged();
+        return this;
+      }
+
+      // required int32 status = 2;
+      private int status_ ;
+      /**
+       * <code>required int32 status = 2;</code>
+       */
+      public boolean hasStatus() {
+        return ((bitField0_ & 0x00000002) == 0x00000002);
+      }
+      /**
+       * <code>required int32 status = 2;</code>
+       */
+      public int getStatus() {
+        return status_;
+      }
+      /**
+       * <code>required int32 status = 2;</code>
+       */
+      public Builder setStatus(int value) {
+        bitField0_ |= 0x00000002;
+        status_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required int32 status = 2;</code>
+       */
+      public Builder clearStatus() {
+        bitField0_ = (bitField0_ & ~0x00000002);
+        status_ = 0;
+        onChanged();
+        return this;
+      }
+
+      // optional bytes value = 3;
+      private com.google.protobuf.ByteString value_ = com.google.protobuf.ByteString.EMPTY;
+      /**
+       * <code>optional bytes value = 3;</code>
+       */
+      public boolean hasValue() {
+        return ((bitField0_ & 0x00000004) == 0x00000004);
+      }
+      /**
+       * <code>optional bytes value = 3;</code>
+       */
+      public com.google.protobuf.ByteString getValue() {
+        return value_;
+      }
+      /**
+       * <code>optional bytes value = 3;</code>
+       */
+      public Builder setValue(com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000004;
+        value_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional bytes value = 3;</code>
+       */
+      public Builder clearValue() {
+        bitField0_ = (bitField0_ & ~0x00000004);
+        value_ = getDefaultInstance().getValue();
+        onChanged();
+        return this;
+      }
+
+      // @@protoc_insertion_point(builder_scope:topology.SwitchProperty)
+    }
+
+    static {
+      defaultInstance = new SwitchProperty(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:topology.SwitchProperty)
+  }
+
+  public interface PortPropertyOrBuilder
+      extends com.google.protobuf.MessageOrBuilder {
+
+    // required int64 dpid = 1;
+    /**
+     * <code>required int64 dpid = 1;</code>
+     */
+    boolean hasDpid();
+    /**
+     * <code>required int64 dpid = 1;</code>
+     */
+    long getDpid();
+
+    // required int64 number = 2;
+    /**
+     * <code>required int64 number = 2;</code>
+     */
+    boolean hasNumber();
+    /**
+     * <code>required int64 number = 2;</code>
+     */
+    long getNumber();
+
+    // required int32 status = 3;
+    /**
+     * <code>required int32 status = 3;</code>
+     */
+    boolean hasStatus();
+    /**
+     * <code>required int32 status = 3;</code>
+     */
+    int getStatus();
+
+    // optional bytes value = 4;
+    /**
+     * <code>optional bytes value = 4;</code>
+     */
+    boolean hasValue();
+    /**
+     * <code>optional bytes value = 4;</code>
+     */
+    com.google.protobuf.ByteString getValue();
+  }
+  /**
+   * Protobuf type {@code topology.PortProperty}
+   */
+  public static final class PortProperty extends
+      com.google.protobuf.GeneratedMessage
+      implements PortPropertyOrBuilder {
+    // Use PortProperty.newBuilder() to construct.
+    private PortProperty(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private PortProperty(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final PortProperty defaultInstance;
+    public static PortProperty getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public PortProperty getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private PortProperty(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      int mutable_bitField0_ = 0;
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+            case 8: {
+              bitField0_ |= 0x00000001;
+              dpid_ = input.readInt64();
+              break;
+            }
+            case 16: {
+              bitField0_ |= 0x00000002;
+              number_ = input.readInt64();
+              break;
+            }
+            case 24: {
+              bitField0_ |= 0x00000004;
+              status_ = input.readInt32();
+              break;
+            }
+            case 34: {
+              bitField0_ |= 0x00000008;
+              value_ = input.readBytes();
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return net.onrc.onos.core.datastore.serializers.Topology.internal_static_topology_PortProperty_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return net.onrc.onos.core.datastore.serializers.Topology.internal_static_topology_PortProperty_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              net.onrc.onos.core.datastore.serializers.Topology.PortProperty.class, net.onrc.onos.core.datastore.serializers.Topology.PortProperty.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<PortProperty> PARSER =
+        new com.google.protobuf.AbstractParser<PortProperty>() {
+      public PortProperty parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new PortProperty(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<PortProperty> getParserForType() {
+      return PARSER;
+    }
+
+    private int bitField0_;
+    // required int64 dpid = 1;
+    public static final int DPID_FIELD_NUMBER = 1;
+    private long dpid_;
+    /**
+     * <code>required int64 dpid = 1;</code>
+     */
+    public boolean hasDpid() {
+      return ((bitField0_ & 0x00000001) == 0x00000001);
+    }
+    /**
+     * <code>required int64 dpid = 1;</code>
+     */
+    public long getDpid() {
+      return dpid_;
+    }
+
+    // required int64 number = 2;
+    public static final int NUMBER_FIELD_NUMBER = 2;
+    private long number_;
+    /**
+     * <code>required int64 number = 2;</code>
+     */
+    public boolean hasNumber() {
+      return ((bitField0_ & 0x00000002) == 0x00000002);
+    }
+    /**
+     * <code>required int64 number = 2;</code>
+     */
+    public long getNumber() {
+      return number_;
+    }
+
+    // required int32 status = 3;
+    public static final int STATUS_FIELD_NUMBER = 3;
+    private int status_;
+    /**
+     * <code>required int32 status = 3;</code>
+     */
+    public boolean hasStatus() {
+      return ((bitField0_ & 0x00000004) == 0x00000004);
+    }
+    /**
+     * <code>required int32 status = 3;</code>
+     */
+    public int getStatus() {
+      return status_;
+    }
+
+    // optional bytes value = 4;
+    public static final int VALUE_FIELD_NUMBER = 4;
+    private com.google.protobuf.ByteString value_;
+    /**
+     * <code>optional bytes value = 4;</code>
+     */
+    public boolean hasValue() {
+      return ((bitField0_ & 0x00000008) == 0x00000008);
+    }
+    /**
+     * <code>optional bytes value = 4;</code>
+     */
+    public com.google.protobuf.ByteString getValue() {
+      return value_;
+    }
+
+    private void initFields() {
+      dpid_ = 0L;
+      number_ = 0L;
+      status_ = 0;
+      value_ = com.google.protobuf.ByteString.EMPTY;
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized != -1) return isInitialized == 1;
+
+      if (!hasDpid()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      if (!hasNumber()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      if (!hasStatus()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        output.writeInt64(1, dpid_);
+      }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        output.writeInt64(2, number_);
+      }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        output.writeInt32(3, status_);
+      }
+      if (((bitField0_ & 0x00000008) == 0x00000008)) {
+        output.writeBytes(4, value_);
+      }
+      getUnknownFields().writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt64Size(1, dpid_);
+      }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt64Size(2, number_);
+      }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt32Size(3, status_);
+      }
+      if (((bitField0_ & 0x00000008) == 0x00000008)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(4, value_);
+      }
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
+    }
+
+    public static net.onrc.onos.core.datastore.serializers.Topology.PortProperty parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static net.onrc.onos.core.datastore.serializers.Topology.PortProperty parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static net.onrc.onos.core.datastore.serializers.Topology.PortProperty parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static net.onrc.onos.core.datastore.serializers.Topology.PortProperty parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static net.onrc.onos.core.datastore.serializers.Topology.PortProperty parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static net.onrc.onos.core.datastore.serializers.Topology.PortProperty parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static net.onrc.onos.core.datastore.serializers.Topology.PortProperty parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static net.onrc.onos.core.datastore.serializers.Topology.PortProperty parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static net.onrc.onos.core.datastore.serializers.Topology.PortProperty parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static net.onrc.onos.core.datastore.serializers.Topology.PortProperty parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(net.onrc.onos.core.datastore.serializers.Topology.PortProperty prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code topology.PortProperty}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder>
+       implements net.onrc.onos.core.datastore.serializers.Topology.PortPropertyOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return net.onrc.onos.core.datastore.serializers.Topology.internal_static_topology_PortProperty_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return net.onrc.onos.core.datastore.serializers.Topology.internal_static_topology_PortProperty_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                net.onrc.onos.core.datastore.serializers.Topology.PortProperty.class, net.onrc.onos.core.datastore.serializers.Topology.PortProperty.Builder.class);
+      }
+
+      // Construct using net.onrc.onos.core.datastore.serializers.Topology.PortProperty.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+
+      public Builder clear() {
+        super.clear();
+        dpid_ = 0L;
+        bitField0_ = (bitField0_ & ~0x00000001);
+        number_ = 0L;
+        bitField0_ = (bitField0_ & ~0x00000002);
+        status_ = 0;
+        bitField0_ = (bitField0_ & ~0x00000004);
+        value_ = com.google.protobuf.ByteString.EMPTY;
+        bitField0_ = (bitField0_ & ~0x00000008);
+        return this;
+      }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return net.onrc.onos.core.datastore.serializers.Topology.internal_static_topology_PortProperty_descriptor;
+      }
+
+      public net.onrc.onos.core.datastore.serializers.Topology.PortProperty getDefaultInstanceForType() {
+        return net.onrc.onos.core.datastore.serializers.Topology.PortProperty.getDefaultInstance();
+      }
+
+      public net.onrc.onos.core.datastore.serializers.Topology.PortProperty build() {
+        net.onrc.onos.core.datastore.serializers.Topology.PortProperty result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public net.onrc.onos.core.datastore.serializers.Topology.PortProperty buildPartial() {
+        net.onrc.onos.core.datastore.serializers.Topology.PortProperty result = new net.onrc.onos.core.datastore.serializers.Topology.PortProperty(this);
+        int from_bitField0_ = bitField0_;
+        int to_bitField0_ = 0;
+        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+          to_bitField0_ |= 0x00000001;
+        }
+        result.dpid_ = dpid_;
+        if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+          to_bitField0_ |= 0x00000002;
+        }
+        result.number_ = number_;
+        if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+          to_bitField0_ |= 0x00000004;
+        }
+        result.status_ = status_;
+        if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
+          to_bitField0_ |= 0x00000008;
+        }
+        result.value_ = value_;
+        result.bitField0_ = to_bitField0_;
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof net.onrc.onos.core.datastore.serializers.Topology.PortProperty) {
+          return mergeFrom((net.onrc.onos.core.datastore.serializers.Topology.PortProperty)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(net.onrc.onos.core.datastore.serializers.Topology.PortProperty other) {
+        if (other == net.onrc.onos.core.datastore.serializers.Topology.PortProperty.getDefaultInstance()) return this;
+        if (other.hasDpid()) {
+          setDpid(other.getDpid());
+        }
+        if (other.hasNumber()) {
+          setNumber(other.getNumber());
+        }
+        if (other.hasStatus()) {
+          setStatus(other.getStatus());
+        }
+        if (other.hasValue()) {
+          setValue(other.getValue());
+        }
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        if (!hasDpid()) {
+          
+          return false;
+        }
+        if (!hasNumber()) {
+          
+          return false;
+        }
+        if (!hasStatus()) {
+          
+          return false;
+        }
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        net.onrc.onos.core.datastore.serializers.Topology.PortProperty parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (net.onrc.onos.core.datastore.serializers.Topology.PortProperty) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+      private int bitField0_;
+
+      // required int64 dpid = 1;
+      private long dpid_ ;
+      /**
+       * <code>required int64 dpid = 1;</code>
+       */
+      public boolean hasDpid() {
+        return ((bitField0_ & 0x00000001) == 0x00000001);
+      }
+      /**
+       * <code>required int64 dpid = 1;</code>
+       */
+      public long getDpid() {
+        return dpid_;
+      }
+      /**
+       * <code>required int64 dpid = 1;</code>
+       */
+      public Builder setDpid(long value) {
+        bitField0_ |= 0x00000001;
+        dpid_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required int64 dpid = 1;</code>
+       */
+      public Builder clearDpid() {
+        bitField0_ = (bitField0_ & ~0x00000001);
+        dpid_ = 0L;
+        onChanged();
+        return this;
+      }
+
+      // required int64 number = 2;
+      private long number_ ;
+      /**
+       * <code>required int64 number = 2;</code>
+       */
+      public boolean hasNumber() {
+        return ((bitField0_ & 0x00000002) == 0x00000002);
+      }
+      /**
+       * <code>required int64 number = 2;</code>
+       */
+      public long getNumber() {
+        return number_;
+      }
+      /**
+       * <code>required int64 number = 2;</code>
+       */
+      public Builder setNumber(long value) {
+        bitField0_ |= 0x00000002;
+        number_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required int64 number = 2;</code>
+       */
+      public Builder clearNumber() {
+        bitField0_ = (bitField0_ & ~0x00000002);
+        number_ = 0L;
+        onChanged();
+        return this;
+      }
+
+      // required int32 status = 3;
+      private int status_ ;
+      /**
+       * <code>required int32 status = 3;</code>
+       */
+      public boolean hasStatus() {
+        return ((bitField0_ & 0x00000004) == 0x00000004);
+      }
+      /**
+       * <code>required int32 status = 3;</code>
+       */
+      public int getStatus() {
+        return status_;
+      }
+      /**
+       * <code>required int32 status = 3;</code>
+       */
+      public Builder setStatus(int value) {
+        bitField0_ |= 0x00000004;
+        status_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required int32 status = 3;</code>
+       */
+      public Builder clearStatus() {
+        bitField0_ = (bitField0_ & ~0x00000004);
+        status_ = 0;
+        onChanged();
+        return this;
+      }
+
+      // optional bytes value = 4;
+      private com.google.protobuf.ByteString value_ = com.google.protobuf.ByteString.EMPTY;
+      /**
+       * <code>optional bytes value = 4;</code>
+       */
+      public boolean hasValue() {
+        return ((bitField0_ & 0x00000008) == 0x00000008);
+      }
+      /**
+       * <code>optional bytes value = 4;</code>
+       */
+      public com.google.protobuf.ByteString getValue() {
+        return value_;
+      }
+      /**
+       * <code>optional bytes value = 4;</code>
+       */
+      public Builder setValue(com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000008;
+        value_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional bytes value = 4;</code>
+       */
+      public Builder clearValue() {
+        bitField0_ = (bitField0_ & ~0x00000008);
+        value_ = getDefaultInstance().getValue();
+        onChanged();
+        return this;
+      }
+
+      // @@protoc_insertion_point(builder_scope:topology.PortProperty)
+    }
+
+    static {
+      defaultInstance = new PortProperty(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:topology.PortProperty)
+  }
+
+  public interface LinkPropertyOrBuilder
+      extends com.google.protobuf.MessageOrBuilder {
+
+    // required bytes srcSwId = 1;
+    /**
+     * <code>required bytes srcSwId = 1;</code>
+     */
+    boolean hasSrcSwId();
+    /**
+     * <code>required bytes srcSwId = 1;</code>
+     */
+    com.google.protobuf.ByteString getSrcSwId();
+
+    // required bytes srcPortId = 2;
+    /**
+     * <code>required bytes srcPortId = 2;</code>
+     */
+    boolean hasSrcPortId();
+    /**
+     * <code>required bytes srcPortId = 2;</code>
+     */
+    com.google.protobuf.ByteString getSrcPortId();
+
+    // required bytes dstSwId = 3;
+    /**
+     * <code>required bytes dstSwId = 3;</code>
+     */
+    boolean hasDstSwId();
+    /**
+     * <code>required bytes dstSwId = 3;</code>
+     */
+    com.google.protobuf.ByteString getDstSwId();
+
+    // required bytes dstPortId = 4;
+    /**
+     * <code>required bytes dstPortId = 4;</code>
+     */
+    boolean hasDstPortId();
+    /**
+     * <code>required bytes dstPortId = 4;</code>
+     */
+    com.google.protobuf.ByteString getDstPortId();
+
+    // required int32 status = 5;
+    /**
+     * <code>required int32 status = 5;</code>
+     */
+    boolean hasStatus();
+    /**
+     * <code>required int32 status = 5;</code>
+     */
+    int getStatus();
+
+    // optional bytes value = 6;
+    /**
+     * <code>optional bytes value = 6;</code>
+     */
+    boolean hasValue();
+    /**
+     * <code>optional bytes value = 6;</code>
+     */
+    com.google.protobuf.ByteString getValue();
+  }
+  /**
+   * Protobuf type {@code topology.LinkProperty}
+   */
+  public static final class LinkProperty extends
+      com.google.protobuf.GeneratedMessage
+      implements LinkPropertyOrBuilder {
+    // Use LinkProperty.newBuilder() to construct.
+    private LinkProperty(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private LinkProperty(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final LinkProperty defaultInstance;
+    public static LinkProperty getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public LinkProperty getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private LinkProperty(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      int mutable_bitField0_ = 0;
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+            case 10: {
+              bitField0_ |= 0x00000001;
+              srcSwId_ = input.readBytes();
+              break;
+            }
+            case 18: {
+              bitField0_ |= 0x00000002;
+              srcPortId_ = input.readBytes();
+              break;
+            }
+            case 26: {
+              bitField0_ |= 0x00000004;
+              dstSwId_ = input.readBytes();
+              break;
+            }
+            case 34: {
+              bitField0_ |= 0x00000008;
+              dstPortId_ = input.readBytes();
+              break;
+            }
+            case 40: {
+              bitField0_ |= 0x00000010;
+              status_ = input.readInt32();
+              break;
+            }
+            case 50: {
+              bitField0_ |= 0x00000020;
+              value_ = input.readBytes();
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return net.onrc.onos.core.datastore.serializers.Topology.internal_static_topology_LinkProperty_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return net.onrc.onos.core.datastore.serializers.Topology.internal_static_topology_LinkProperty_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              net.onrc.onos.core.datastore.serializers.Topology.LinkProperty.class, net.onrc.onos.core.datastore.serializers.Topology.LinkProperty.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<LinkProperty> PARSER =
+        new com.google.protobuf.AbstractParser<LinkProperty>() {
+      public LinkProperty parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new LinkProperty(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<LinkProperty> getParserForType() {
+      return PARSER;
+    }
+
+    private int bitField0_;
+    // required bytes srcSwId = 1;
+    public static final int SRCSWID_FIELD_NUMBER = 1;
+    private com.google.protobuf.ByteString srcSwId_;
+    /**
+     * <code>required bytes srcSwId = 1;</code>
+     */
+    public boolean hasSrcSwId() {
+      return ((bitField0_ & 0x00000001) == 0x00000001);
+    }
+    /**
+     * <code>required bytes srcSwId = 1;</code>
+     */
+    public com.google.protobuf.ByteString getSrcSwId() {
+      return srcSwId_;
+    }
+
+    // required bytes srcPortId = 2;
+    public static final int SRCPORTID_FIELD_NUMBER = 2;
+    private com.google.protobuf.ByteString srcPortId_;
+    /**
+     * <code>required bytes srcPortId = 2;</code>
+     */
+    public boolean hasSrcPortId() {
+      return ((bitField0_ & 0x00000002) == 0x00000002);
+    }
+    /**
+     * <code>required bytes srcPortId = 2;</code>
+     */
+    public com.google.protobuf.ByteString getSrcPortId() {
+      return srcPortId_;
+    }
+
+    // required bytes dstSwId = 3;
+    public static final int DSTSWID_FIELD_NUMBER = 3;
+    private com.google.protobuf.ByteString dstSwId_;
+    /**
+     * <code>required bytes dstSwId = 3;</code>
+     */
+    public boolean hasDstSwId() {
+      return ((bitField0_ & 0x00000004) == 0x00000004);
+    }
+    /**
+     * <code>required bytes dstSwId = 3;</code>
+     */
+    public com.google.protobuf.ByteString getDstSwId() {
+      return dstSwId_;
+    }
+
+    // required bytes dstPortId = 4;
+    public static final int DSTPORTID_FIELD_NUMBER = 4;
+    private com.google.protobuf.ByteString dstPortId_;
+    /**
+     * <code>required bytes dstPortId = 4;</code>
+     */
+    public boolean hasDstPortId() {
+      return ((bitField0_ & 0x00000008) == 0x00000008);
+    }
+    /**
+     * <code>required bytes dstPortId = 4;</code>
+     */
+    public com.google.protobuf.ByteString getDstPortId() {
+      return dstPortId_;
+    }
+
+    // required int32 status = 5;
+    public static final int STATUS_FIELD_NUMBER = 5;
+    private int status_;
+    /**
+     * <code>required int32 status = 5;</code>
+     */
+    public boolean hasStatus() {
+      return ((bitField0_ & 0x00000010) == 0x00000010);
+    }
+    /**
+     * <code>required int32 status = 5;</code>
+     */
+    public int getStatus() {
+      return status_;
+    }
+
+    // optional bytes value = 6;
+    public static final int VALUE_FIELD_NUMBER = 6;
+    private com.google.protobuf.ByteString value_;
+    /**
+     * <code>optional bytes value = 6;</code>
+     */
+    public boolean hasValue() {
+      return ((bitField0_ & 0x00000020) == 0x00000020);
+    }
+    /**
+     * <code>optional bytes value = 6;</code>
+     */
+    public com.google.protobuf.ByteString getValue() {
+      return value_;
+    }
+
+    private void initFields() {
+      srcSwId_ = com.google.protobuf.ByteString.EMPTY;
+      srcPortId_ = com.google.protobuf.ByteString.EMPTY;
+      dstSwId_ = com.google.protobuf.ByteString.EMPTY;
+      dstPortId_ = com.google.protobuf.ByteString.EMPTY;
+      status_ = 0;
+      value_ = com.google.protobuf.ByteString.EMPTY;
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized != -1) return isInitialized == 1;
+
+      if (!hasSrcSwId()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      if (!hasSrcPortId()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      if (!hasDstSwId()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      if (!hasDstPortId()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      if (!hasStatus()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        output.writeBytes(1, srcSwId_);
+      }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        output.writeBytes(2, srcPortId_);
+      }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        output.writeBytes(3, dstSwId_);
+      }
+      if (((bitField0_ & 0x00000008) == 0x00000008)) {
+        output.writeBytes(4, dstPortId_);
+      }
+      if (((bitField0_ & 0x00000010) == 0x00000010)) {
+        output.writeInt32(5, status_);
+      }
+      if (((bitField0_ & 0x00000020) == 0x00000020)) {
+        output.writeBytes(6, value_);
+      }
+      getUnknownFields().writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(1, srcSwId_);
+      }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(2, srcPortId_);
+      }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(3, dstSwId_);
+      }
+      if (((bitField0_ & 0x00000008) == 0x00000008)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(4, dstPortId_);
+      }
+      if (((bitField0_ & 0x00000010) == 0x00000010)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt32Size(5, status_);
+      }
+      if (((bitField0_ & 0x00000020) == 0x00000020)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(6, value_);
+      }
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
+    }
+
+    public static net.onrc.onos.core.datastore.serializers.Topology.LinkProperty parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static net.onrc.onos.core.datastore.serializers.Topology.LinkProperty parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static net.onrc.onos.core.datastore.serializers.Topology.LinkProperty parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static net.onrc.onos.core.datastore.serializers.Topology.LinkProperty parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static net.onrc.onos.core.datastore.serializers.Topology.LinkProperty parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static net.onrc.onos.core.datastore.serializers.Topology.LinkProperty parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static net.onrc.onos.core.datastore.serializers.Topology.LinkProperty parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static net.onrc.onos.core.datastore.serializers.Topology.LinkProperty parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static net.onrc.onos.core.datastore.serializers.Topology.LinkProperty parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static net.onrc.onos.core.datastore.serializers.Topology.LinkProperty parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(net.onrc.onos.core.datastore.serializers.Topology.LinkProperty prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code topology.LinkProperty}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder>
+       implements net.onrc.onos.core.datastore.serializers.Topology.LinkPropertyOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return net.onrc.onos.core.datastore.serializers.Topology.internal_static_topology_LinkProperty_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return net.onrc.onos.core.datastore.serializers.Topology.internal_static_topology_LinkProperty_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                net.onrc.onos.core.datastore.serializers.Topology.LinkProperty.class, net.onrc.onos.core.datastore.serializers.Topology.LinkProperty.Builder.class);
+      }
+
+      // Construct using net.onrc.onos.core.datastore.serializers.Topology.LinkProperty.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+
+      public Builder clear() {
+        super.clear();
+        srcSwId_ = com.google.protobuf.ByteString.EMPTY;
+        bitField0_ = (bitField0_ & ~0x00000001);
+        srcPortId_ = com.google.protobuf.ByteString.EMPTY;
+        bitField0_ = (bitField0_ & ~0x00000002);
+        dstSwId_ = com.google.protobuf.ByteString.EMPTY;
+        bitField0_ = (bitField0_ & ~0x00000004);
+        dstPortId_ = com.google.protobuf.ByteString.EMPTY;
+        bitField0_ = (bitField0_ & ~0x00000008);
+        status_ = 0;
+        bitField0_ = (bitField0_ & ~0x00000010);
+        value_ = com.google.protobuf.ByteString.EMPTY;
+        bitField0_ = (bitField0_ & ~0x00000020);
+        return this;
+      }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return net.onrc.onos.core.datastore.serializers.Topology.internal_static_topology_LinkProperty_descriptor;
+      }
+
+      public net.onrc.onos.core.datastore.serializers.Topology.LinkProperty getDefaultInstanceForType() {
+        return net.onrc.onos.core.datastore.serializers.Topology.LinkProperty.getDefaultInstance();
+      }
+
+      public net.onrc.onos.core.datastore.serializers.Topology.LinkProperty build() {
+        net.onrc.onos.core.datastore.serializers.Topology.LinkProperty result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public net.onrc.onos.core.datastore.serializers.Topology.LinkProperty buildPartial() {
+        net.onrc.onos.core.datastore.serializers.Topology.LinkProperty result = new net.onrc.onos.core.datastore.serializers.Topology.LinkProperty(this);
+        int from_bitField0_ = bitField0_;
+        int to_bitField0_ = 0;
+        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+          to_bitField0_ |= 0x00000001;
+        }
+        result.srcSwId_ = srcSwId_;
+        if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+          to_bitField0_ |= 0x00000002;
+        }
+        result.srcPortId_ = srcPortId_;
+        if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+          to_bitField0_ |= 0x00000004;
+        }
+        result.dstSwId_ = dstSwId_;
+        if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
+          to_bitField0_ |= 0x00000008;
+        }
+        result.dstPortId_ = dstPortId_;
+        if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
+          to_bitField0_ |= 0x00000010;
+        }
+        result.status_ = status_;
+        if (((from_bitField0_ & 0x00000020) == 0x00000020)) {
+          to_bitField0_ |= 0x00000020;
+        }
+        result.value_ = value_;
+        result.bitField0_ = to_bitField0_;
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof net.onrc.onos.core.datastore.serializers.Topology.LinkProperty) {
+          return mergeFrom((net.onrc.onos.core.datastore.serializers.Topology.LinkProperty)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(net.onrc.onos.core.datastore.serializers.Topology.LinkProperty other) {
+        if (other == net.onrc.onos.core.datastore.serializers.Topology.LinkProperty.getDefaultInstance()) return this;
+        if (other.hasSrcSwId()) {
+          setSrcSwId(other.getSrcSwId());
+        }
+        if (other.hasSrcPortId()) {
+          setSrcPortId(other.getSrcPortId());
+        }
+        if (other.hasDstSwId()) {
+          setDstSwId(other.getDstSwId());
+        }
+        if (other.hasDstPortId()) {
+          setDstPortId(other.getDstPortId());
+        }
+        if (other.hasStatus()) {
+          setStatus(other.getStatus());
+        }
+        if (other.hasValue()) {
+          setValue(other.getValue());
+        }
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        if (!hasSrcSwId()) {
+          
+          return false;
+        }
+        if (!hasSrcPortId()) {
+          
+          return false;
+        }
+        if (!hasDstSwId()) {
+          
+          return false;
+        }
+        if (!hasDstPortId()) {
+          
+          return false;
+        }
+        if (!hasStatus()) {
+          
+          return false;
+        }
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        net.onrc.onos.core.datastore.serializers.Topology.LinkProperty parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (net.onrc.onos.core.datastore.serializers.Topology.LinkProperty) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+      private int bitField0_;
+
+      // required bytes srcSwId = 1;
+      private com.google.protobuf.ByteString srcSwId_ = com.google.protobuf.ByteString.EMPTY;
+      /**
+       * <code>required bytes srcSwId = 1;</code>
+       */
+      public boolean hasSrcSwId() {
+        return ((bitField0_ & 0x00000001) == 0x00000001);
+      }
+      /**
+       * <code>required bytes srcSwId = 1;</code>
+       */
+      public com.google.protobuf.ByteString getSrcSwId() {
+        return srcSwId_;
+      }
+      /**
+       * <code>required bytes srcSwId = 1;</code>
+       */
+      public Builder setSrcSwId(com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000001;
+        srcSwId_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required bytes srcSwId = 1;</code>
+       */
+      public Builder clearSrcSwId() {
+        bitField0_ = (bitField0_ & ~0x00000001);
+        srcSwId_ = getDefaultInstance().getSrcSwId();
+        onChanged();
+        return this;
+      }
+
+      // required bytes srcPortId = 2;
+      private com.google.protobuf.ByteString srcPortId_ = com.google.protobuf.ByteString.EMPTY;
+      /**
+       * <code>required bytes srcPortId = 2;</code>
+       */
+      public boolean hasSrcPortId() {
+        return ((bitField0_ & 0x00000002) == 0x00000002);
+      }
+      /**
+       * <code>required bytes srcPortId = 2;</code>
+       */
+      public com.google.protobuf.ByteString getSrcPortId() {
+        return srcPortId_;
+      }
+      /**
+       * <code>required bytes srcPortId = 2;</code>
+       */
+      public Builder setSrcPortId(com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000002;
+        srcPortId_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required bytes srcPortId = 2;</code>
+       */
+      public Builder clearSrcPortId() {
+        bitField0_ = (bitField0_ & ~0x00000002);
+        srcPortId_ = getDefaultInstance().getSrcPortId();
+        onChanged();
+        return this;
+      }
+
+      // required bytes dstSwId = 3;
+      private com.google.protobuf.ByteString dstSwId_ = com.google.protobuf.ByteString.EMPTY;
+      /**
+       * <code>required bytes dstSwId = 3;</code>
+       */
+      public boolean hasDstSwId() {
+        return ((bitField0_ & 0x00000004) == 0x00000004);
+      }
+      /**
+       * <code>required bytes dstSwId = 3;</code>
+       */
+      public com.google.protobuf.ByteString getDstSwId() {
+        return dstSwId_;
+      }
+      /**
+       * <code>required bytes dstSwId = 3;</code>
+       */
+      public Builder setDstSwId(com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000004;
+        dstSwId_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required bytes dstSwId = 3;</code>
+       */
+      public Builder clearDstSwId() {
+        bitField0_ = (bitField0_ & ~0x00000004);
+        dstSwId_ = getDefaultInstance().getDstSwId();
+        onChanged();
+        return this;
+      }
+
+      // required bytes dstPortId = 4;
+      private com.google.protobuf.ByteString dstPortId_ = com.google.protobuf.ByteString.EMPTY;
+      /**
+       * <code>required bytes dstPortId = 4;</code>
+       */
+      public boolean hasDstPortId() {
+        return ((bitField0_ & 0x00000008) == 0x00000008);
+      }
+      /**
+       * <code>required bytes dstPortId = 4;</code>
+       */
+      public com.google.protobuf.ByteString getDstPortId() {
+        return dstPortId_;
+      }
+      /**
+       * <code>required bytes dstPortId = 4;</code>
+       */
+      public Builder setDstPortId(com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000008;
+        dstPortId_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required bytes dstPortId = 4;</code>
+       */
+      public Builder clearDstPortId() {
+        bitField0_ = (bitField0_ & ~0x00000008);
+        dstPortId_ = getDefaultInstance().getDstPortId();
+        onChanged();
+        return this;
+      }
+
+      // required int32 status = 5;
+      private int status_ ;
+      /**
+       * <code>required int32 status = 5;</code>
+       */
+      public boolean hasStatus() {
+        return ((bitField0_ & 0x00000010) == 0x00000010);
+      }
+      /**
+       * <code>required int32 status = 5;</code>
+       */
+      public int getStatus() {
+        return status_;
+      }
+      /**
+       * <code>required int32 status = 5;</code>
+       */
+      public Builder setStatus(int value) {
+        bitField0_ |= 0x00000010;
+        status_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required int32 status = 5;</code>
+       */
+      public Builder clearStatus() {
+        bitField0_ = (bitField0_ & ~0x00000010);
+        status_ = 0;
+        onChanged();
+        return this;
+      }
+
+      // optional bytes value = 6;
+      private com.google.protobuf.ByteString value_ = com.google.protobuf.ByteString.EMPTY;
+      /**
+       * <code>optional bytes value = 6;</code>
+       */
+      public boolean hasValue() {
+        return ((bitField0_ & 0x00000020) == 0x00000020);
+      }
+      /**
+       * <code>optional bytes value = 6;</code>
+       */
+      public com.google.protobuf.ByteString getValue() {
+        return value_;
+      }
+      /**
+       * <code>optional bytes value = 6;</code>
+       */
+      public Builder setValue(com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000020;
+        value_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional bytes value = 6;</code>
+       */
+      public Builder clearValue() {
+        bitField0_ = (bitField0_ & ~0x00000020);
+        value_ = getDefaultInstance().getValue();
+        onChanged();
+        return this;
+      }
+
+      // @@protoc_insertion_point(builder_scope:topology.LinkProperty)
+    }
+
+    static {
+      defaultInstance = new LinkProperty(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:topology.LinkProperty)
+  }
+
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_topology_SwitchProperty_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_topology_SwitchProperty_fieldAccessorTable;
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_topology_PortProperty_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_topology_PortProperty_fieldAccessorTable;
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_topology_LinkProperty_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_topology_LinkProperty_fieldAccessorTable;
+
+  public static com.google.protobuf.Descriptors.FileDescriptor
+      getDescriptor() {
+    return descriptor;
+  }
+  private static com.google.protobuf.Descriptors.FileDescriptor
+      descriptor;
+  static {
+    java.lang.String[] descriptorData = {
+      "\n\016topology.proto\022\010topology\"=\n\016SwitchProp" +
+      "erty\022\014\n\004dpid\030\001 \002(\003\022\016\n\006status\030\002 \002(\005\022\r\n\005va" +
+      "lue\030\003 \001(\014\"K\n\014PortProperty\022\014\n\004dpid\030\001 \002(\003\022" +
+      "\016\n\006number\030\002 \002(\003\022\016\n\006status\030\003 \002(\005\022\r\n\005value" +
+      "\030\004 \001(\014\"u\n\014LinkProperty\022\017\n\007srcSwId\030\001 \002(\014\022" +
+      "\021\n\tsrcPortId\030\002 \002(\014\022\017\n\007dstSwId\030\003 \002(\014\022\021\n\td" +
+      "stPortId\030\004 \002(\014\022\016\n\006status\030\005 \002(\005\022\r\n\005value\030" +
+      "\006 \001(\014B4\n(net.onrc.onos.core.datastore.se" +
+      "rializersB\010Topology"
+    };
+    com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
+      new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
+        public com.google.protobuf.ExtensionRegistry assignDescriptors(
+            com.google.protobuf.Descriptors.FileDescriptor root) {
+          descriptor = root;
+          internal_static_topology_SwitchProperty_descriptor =
+            getDescriptor().getMessageTypes().get(0);
+          internal_static_topology_SwitchProperty_fieldAccessorTable = new
+            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+              internal_static_topology_SwitchProperty_descriptor,
+              new java.lang.String[] { "Dpid", "Status", "Value", });
+          internal_static_topology_PortProperty_descriptor =
+            getDescriptor().getMessageTypes().get(1);
+          internal_static_topology_PortProperty_fieldAccessorTable = new
+            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+              internal_static_topology_PortProperty_descriptor,
+              new java.lang.String[] { "Dpid", "Number", "Status", "Value", });
+          internal_static_topology_LinkProperty_descriptor =
+            getDescriptor().getMessageTypes().get(2);
+          internal_static_topology_LinkProperty_fieldAccessorTable = new
+            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+              internal_static_topology_LinkProperty_descriptor,
+              new java.lang.String[] { "SrcSwId", "SrcPortId", "DstSwId", "DstPortId", "Status", "Value", });
+          return null;
+        }
+      };
+    com.google.protobuf.Descriptors.FileDescriptor
+      .internalBuildGeneratedFileFrom(descriptorData,
+        new com.google.protobuf.Descriptors.FileDescriptor[] {
+        }, assigner);
+  }
+
+  // @@protoc_insertion_point(outer_class_scope)
+}
diff --git a/src/main/java/net/onrc/onos/core/datastore/topology/KVLink.java b/src/main/java/net/onrc/onos/core/datastore/topology/KVLink.java
index 64eabc1..a7501e1 100644
--- a/src/main/java/net/onrc/onos/core/datastore/topology/KVLink.java
+++ b/src/main/java/net/onrc/onos/core/datastore/topology/KVLink.java
@@ -7,7 +7,7 @@
 
 import net.onrc.onos.core.datastore.DataStoreClient;
 import net.onrc.onos.core.datastore.IKVTable.IKVEntry;
-import net.onrc.onos.core.datastore.RCProtos.LinkProperty;
+import net.onrc.onos.core.datastore.serializers.Topology.LinkProperty;
 import net.onrc.onos.core.datastore.utils.KVObject;
 import net.onrc.onos.core.topology.LinkEvent;
 import net.onrc.onos.core.topology.PortEvent;
diff --git a/src/main/java/net/onrc/onos/core/datastore/topology/KVPort.java b/src/main/java/net/onrc/onos/core/datastore/topology/KVPort.java
index db4e1ff..254e026 100644
--- a/src/main/java/net/onrc/onos/core/datastore/topology/KVPort.java
+++ b/src/main/java/net/onrc/onos/core/datastore/topology/KVPort.java
@@ -7,7 +7,7 @@
 
 import net.onrc.onos.core.datastore.DataStoreClient;
 import net.onrc.onos.core.datastore.IKVTable.IKVEntry;
-import net.onrc.onos.core.datastore.RCProtos.PortProperty;
+import net.onrc.onos.core.datastore.serializers.Topology.PortProperty;
 import net.onrc.onos.core.datastore.utils.ByteArrayUtil;
 import net.onrc.onos.core.datastore.utils.KVObject;
 import net.onrc.onos.core.topology.PortEvent;
diff --git a/src/main/java/net/onrc/onos/core/datastore/topology/KVSwitch.java b/src/main/java/net/onrc/onos/core/datastore/topology/KVSwitch.java
index 9f865e0..a9cc367 100644
--- a/src/main/java/net/onrc/onos/core/datastore/topology/KVSwitch.java
+++ b/src/main/java/net/onrc/onos/core/datastore/topology/KVSwitch.java
@@ -7,7 +7,7 @@
 
 import net.onrc.onos.core.datastore.DataStoreClient;
 import net.onrc.onos.core.datastore.IKVTable.IKVEntry;
-import net.onrc.onos.core.datastore.RCProtos.SwitchProperty;
+import net.onrc.onos.core.datastore.serializers.Topology.SwitchProperty;
 import net.onrc.onos.core.datastore.utils.KVObject;
 import net.onrc.onos.core.topology.SwitchEvent;
 
diff --git a/src/main/protobuf/README.md b/src/main/protobuf/README.md
new file mode 100644
index 0000000..fd78944
--- /dev/null
+++ b/src/main/protobuf/README.md
@@ -0,0 +1,20 @@
+
+Generating Java source code after modifing protobuf definition
+--------------------------------------------------------------
+
+1. Check to see you have the correct protoc version
+
+    	$ protoc --version
+
+	Confirm that the result version is compatible with the version
+    specified in pom.xml.
+
+2. Generate Java source code.
+
+    	$ protoc topology.proto  --java_out=${ONOS_HOME}/src/main/java/
+
+	Replace `--java_out` path to root Java source directory.  
+    e.g., If you're in the same directory as this file:
+
+    	$ protoc topology.proto  --java_out=../java/
+
diff --git a/src/main/protobuf/ramcloud.proto b/src/main/protobuf/topology.proto
similarity index 78%
rename from src/main/protobuf/ramcloud.proto
rename to src/main/protobuf/topology.proto
index 35c63d8..191488d 100644
--- a/src/main/protobuf/ramcloud.proto
+++ b/src/main/protobuf/topology.proto
@@ -1,7 +1,7 @@
-package RCProtos;
+package topology;
 
-option java_package = "net.onrc.onos.core.datastore";
-option java_outer_classname = "RCProtos";
+option java_package = "net.onrc.onos.core.datastore.serializers";
+option java_outer_classname = "Topology";
 
 message SwitchProperty {
   required int64 dpid = 1;
