Make vRouter components into separate apps.
This allows us to leverage the ONOS app subsystem for selecting which
components to load.
CORD-710
Change-Id: Ibd7c4c1afd2caa137b44c085e7b6b5b4a1082521
diff --git a/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/protocol/FpmHeader.java b/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/protocol/FpmHeader.java
new file mode 100644
index 0000000..5bba9fb
--- /dev/null
+++ b/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/protocol/FpmHeader.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.routing.fpm.protocol;
+
+import com.google.common.base.MoreObjects;
+import org.onlab.packet.DeserializationException;
+
+import java.nio.ByteBuffer;
+
+import static org.onlab.packet.PacketUtils.checkInput;
+
+/**
+ * FPM header.
+ */
+public final class FpmHeader {
+ public static final int FPM_HEADER_LENGTH = 4;
+
+ public static final short FPM_VERSION_1 = 1;
+ public static final short FPM_TYPE_NETLINK = 1;
+
+ private static final String VERSION_NOT_SUPPORTED = "FPM version not supported: ";
+ private static final String TYPE_NOT_SUPPORTED = "FPM type not supported: ";
+
+ private final short version;
+ private final short type;
+ private final int length;
+
+ private final Netlink netlink;
+
+ /**
+ * Class constructor.
+ *
+ * @param version version
+ * @param type type
+ * @param length length
+ * @param netlink netlink header
+ */
+ private FpmHeader(short version, short type, int length, Netlink netlink) {
+ this.version = version;
+ this.type = type;
+ this.length = length;
+ this.netlink = netlink;
+ }
+
+ /**
+ * Returns the protocol version.
+ *
+ * @return protocol version
+ */
+ public short version() {
+ return version;
+ }
+
+ /**
+ * Returns the type.
+ *
+ * @return type
+ */
+ public short type() {
+ return type;
+ }
+
+ /**
+ * Returns the message length.
+ *
+ * @return message length
+ */
+ public int length() {
+ return length;
+ }
+
+ /**
+ * Returns the netlink header.
+ *
+ * @return netlink header
+ */
+ public Netlink netlink() {
+ return netlink;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("version", version)
+ .add("type", type)
+ .add("length", length)
+ .add("netlink", netlink)
+ .toString();
+ }
+
+ /**
+ * Decodes an FPM header from an input buffer.
+ *
+ * @param buffer input buffer
+ * @param start starting position the FPM header
+ * @param length length of the message
+ * @return FPM header
+ * @throws DeserializationException if an FPM header could not be decoded
+ * from the input buffer
+ */
+ public static FpmHeader decode(byte[] buffer, int start, int length) throws
+ DeserializationException {
+ checkInput(buffer, start, length, FPM_HEADER_LENGTH);
+
+ ByteBuffer bb = ByteBuffer.wrap(buffer, start, length);
+
+ short version = bb.get();
+ if (version != FPM_VERSION_1) {
+ throw new DeserializationException(VERSION_NOT_SUPPORTED + version);
+ }
+
+ short type = bb.get();
+ if (type != FPM_TYPE_NETLINK) {
+ throw new DeserializationException(TYPE_NOT_SUPPORTED + type);
+ }
+
+ int messageLength = bb.getShort();
+
+ Netlink netlink = Netlink.decode(buffer, bb.position(), bb.limit() - bb.position());
+
+ return new FpmHeader(version, type, messageLength, netlink);
+ }
+}
diff --git a/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/protocol/Netlink.java b/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/protocol/Netlink.java
new file mode 100644
index 0000000..79c23ab
--- /dev/null
+++ b/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/protocol/Netlink.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.routing.fpm.protocol;
+
+import com.google.common.base.MoreObjects;
+import org.onlab.packet.DeserializationException;
+
+import java.nio.ByteBuffer;
+
+import static org.onlab.packet.PacketUtils.checkInput;
+
+/**
+ * Netlink header.
+ * <p>
+ * Taken from struct nlmsghdr in linux/netlink.h
+ * </p>
+ */
+public final class Netlink {
+
+ public static final int NETLINK_HEADER_LENGTH = 16;
+
+ private final long length;
+ private final NetlinkMessageType type;
+ private final int flags;
+ private final long sequence;
+ private final long processPortId;
+
+ private final RtNetlink rtNetlink;
+
+ /**
+ * Class constructor.
+ *
+ * @param length message length
+ * @param type type
+ * @param flags flags
+ * @param sequence sequence number
+ * @param processPortId port ID
+ * @param rtNetlink netlink routing message
+ */
+ private Netlink(long length, NetlinkMessageType type, int flags, long sequence,
+ long processPortId, RtNetlink rtNetlink) {
+ this.length = length;
+ this.type = type;
+ this.flags = flags;
+ this.sequence = sequence;
+ this.processPortId = processPortId;
+ this.rtNetlink = rtNetlink;
+ }
+
+ /**
+ * Returns the message length.
+ *
+ * @return length
+ */
+ public long length() {
+ return length;
+ }
+
+ /**
+ * Returns the message type.
+ *
+ * @return message type
+ */
+ public NetlinkMessageType type() {
+ return type;
+ }
+
+ /**
+ * Returns the flags.
+ *
+ * @return flags
+ */
+ public int flags() {
+ return flags;
+ }
+
+ /**
+ * Returns the sequence number.
+ *
+ * @return sequence number
+ */
+ public long sequence() {
+ return sequence;
+ }
+
+ /**
+ * Returns the port ID.
+ *
+ * @return port ID
+ */
+ public long processPortId() {
+ return processPortId;
+ }
+
+ /**
+ * Returns the netlink routing message.
+ *
+ * @return netlink routing message
+ */
+ public RtNetlink rtNetlink() {
+ return rtNetlink;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("length", length)
+ .add("type", type)
+ .add("flags", flags)
+ .add("sequence", sequence)
+ .add("processPortId", processPortId)
+ .add("rtNetlink", rtNetlink)
+ .toString();
+ }
+
+ /**
+ * Decodes a netlink header from an input buffer.
+ *
+ * @param buffer input buffer
+ * @param start starting position the netlink header
+ * @param length length of the message
+ * @return netlink header
+ * @throws DeserializationException if a netlink header could not be
+ * decoded from the input buffer
+ */
+ public static Netlink decode(byte[] buffer, int start, int length) throws
+ DeserializationException {
+ checkInput(buffer, start, length, NETLINK_HEADER_LENGTH);
+
+ ByteBuffer bb = ByteBuffer.wrap(buffer, start, length);
+
+ long messageLength = Integer.reverseBytes(bb.getInt());
+ int type = Short.reverseBytes(bb.getShort());
+ int flags = Short.reverseBytes(bb.getShort());
+ long sequence = Integer.reverseBytes(bb.getInt());
+ long processPortId = Integer.reverseBytes(bb.getInt());
+
+ NetlinkMessageType messageType = NetlinkMessageType.get(type);
+ if (messageType == null) {
+ throw new DeserializationException(
+ "Unsupported Netlink message type: " + type);
+ }
+
+ // Netlink messages from Quagga's FPM protocol are always in the
+ // netlink route family (family 0).
+ RtNetlink rtNetlink = RtNetlink.decode(buffer, bb.position(),
+ bb.limit() - bb.position());
+
+ return new Netlink(messageLength,
+ messageType,
+ flags,
+ sequence,
+ processPortId,
+ rtNetlink);
+ }
+
+}
diff --git a/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/protocol/NetlinkMessageType.java b/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/protocol/NetlinkMessageType.java
new file mode 100644
index 0000000..0abb0bd
--- /dev/null
+++ b/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/protocol/NetlinkMessageType.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.routing.fpm.protocol;
+
+/**
+ * Netlink message types.
+ * <p>
+ * This is a subset of the types used for routing messages (rtnelink).
+ * Taken from linux/rtnetlink.h
+ * </p>
+ */
+public enum NetlinkMessageType {
+ RTM_NEWROUTE(24),
+ RTM_DELROUTE(25),
+ RTM_GETROUTE(26);
+
+ private final int type;
+
+ /**
+ * Enum constructor.
+ *
+ * @param type integer type value
+ */
+ NetlinkMessageType(int type) {
+ this.type = type;
+ }
+
+ /**
+ * Returns the integer type value for this message type.
+ *
+ * @return type value
+ */
+ public int type() {
+ return type;
+ }
+
+ /**
+ * Gets the NetlinkMessageType for the given integer type value.
+ *
+ * @param type type value
+ * @return Netlink message type, or null if unsupported type value
+ */
+ public static NetlinkMessageType get(int type) {
+ for (NetlinkMessageType m : NetlinkMessageType.values()) {
+ if (m.type() == type) {
+ return m;
+ }
+ }
+ return null;
+ }
+}
diff --git a/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/protocol/RouteAttribute.java b/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/protocol/RouteAttribute.java
new file mode 100644
index 0000000..cffb422
--- /dev/null
+++ b/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/protocol/RouteAttribute.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.routing.fpm.protocol;
+
+import com.google.common.collect.ImmutableMap;
+import org.onlab.packet.DeserializationException;
+
+import java.nio.ByteBuffer;
+import java.util.Map;
+
+import static org.onlab.packet.PacketUtils.checkInput;
+
+/**
+ * Route attribute header.
+ */
+public abstract class RouteAttribute {
+
+ public static final int ROUTE_ATTRIBUTE_HEADER_LENGTH = 4;
+
+ public static final int RTA_DST = 1;
+ public static final int RTA_OIF = 4;
+ public static final int RTA_GATEWAY = 5;
+ public static final int RTA_PRIORITY = 6;
+
+ private final int length;
+ private final int type;
+
+ private static final Map<Integer, RouteAttributeDecoder<?>> TYPE_DECODER_MAP
+ = ImmutableMap.<Integer, RouteAttributeDecoder<?>>builder()
+ .put(RTA_DST, RouteAttributeDst.decoder())
+ .put(RTA_OIF, RouteAttributeOif.decoder())
+ .put(RTA_GATEWAY, RouteAttributeGateway.decoder())
+ .put(RTA_PRIORITY, RouteAttributePriority.decoder())
+ .build();
+
+ /**
+ * Class constructor.
+ *
+ * @param length attribute length
+ * @param type attribute type
+ */
+ protected RouteAttribute(int length, int type) {
+ this.length = length;
+ this.type = type;
+ }
+
+ /**
+ * Returns the attribute length.
+ *
+ * @return length
+ */
+ public int length() {
+ return length;
+ }
+
+ /**
+ * Returns the attribute type.
+ *
+ * @return type
+ */
+ public int type() {
+ return type;
+ }
+
+ @Override
+ public abstract String toString();
+
+ /**
+ * Decodes a route attribute from an input buffer.
+ *
+ * @param buffer input buffer
+ * @param start starting position the route attribute message
+ * @param length length of the message
+ * @return route attribute message
+ * @throws DeserializationException if a route attribute could not be
+ * decoded from the input buffer
+ */
+ public static RouteAttribute decode(byte[] buffer, int start, int length)
+ throws DeserializationException {
+ checkInput(buffer, start, length, ROUTE_ATTRIBUTE_HEADER_LENGTH);
+
+ ByteBuffer bb = ByteBuffer.wrap(buffer, start, length);
+
+ int tlvLength = Short.reverseBytes(bb.getShort());
+ int type = Short.reverseBytes(bb.getShort());
+
+ if (bb.remaining() < tlvLength - ROUTE_ATTRIBUTE_HEADER_LENGTH) {
+ throw new DeserializationException(
+ "Incorrect buffer size when decoding route attribute");
+ }
+
+ byte[] value = new byte[tlvLength - ROUTE_ATTRIBUTE_HEADER_LENGTH];
+ bb.get(value);
+
+ RouteAttributeDecoder<?> decoder = TYPE_DECODER_MAP.get(type);
+ if (decoder == null) {
+ throw new DeserializationException(
+ "No decoder found for route attribute type " + type);
+ }
+
+ return decoder.decodeAttribute(tlvLength, type, value);
+ }
+}
diff --git a/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/protocol/RouteAttributeDecoder.java b/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/protocol/RouteAttributeDecoder.java
new file mode 100644
index 0000000..f702c40
--- /dev/null
+++ b/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/protocol/RouteAttributeDecoder.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.routing.fpm.protocol;
+
+import org.onlab.packet.DeserializationException;
+
+/**
+ * Decoder for a route attribute.
+ */
+@FunctionalInterface
+public interface RouteAttributeDecoder<A extends RouteAttribute> {
+
+ /**
+ * Decodes the a route attribute from the input buffer.
+ *
+ * @param length length of the attribute
+ * @param type type of the attribute
+ * @param value input buffer
+ * @return route attribute
+ * @throws DeserializationException if a route attribute could not be
+ * decoded from the input buffer
+ */
+ A decodeAttribute(int length, int type, byte[] value)
+ throws DeserializationException;
+}
diff --git a/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/protocol/RouteAttributeDst.java b/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/protocol/RouteAttributeDst.java
new file mode 100644
index 0000000..d12f14c
--- /dev/null
+++ b/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/protocol/RouteAttributeDst.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.routing.fpm.protocol;
+
+import com.google.common.base.MoreObjects;
+import org.onlab.packet.DeserializationException;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.Ip6Address;
+import org.onlab.packet.IpAddress;
+
+/**
+ * Destination address route attribute.
+ */
+public final class RouteAttributeDst extends RouteAttribute {
+
+ private final IpAddress dstAddress;
+
+ /**
+ * Class constructor.
+ *
+ * @param length length
+ * @param type type
+ * @param dstAddress destination address
+ */
+ private RouteAttributeDst(int length, int type, IpAddress dstAddress) {
+ super(length, type);
+
+ this.dstAddress = dstAddress;
+ }
+
+ /**
+ * Returns the destination IP address.
+ *
+ * @return destination IP address
+ */
+ public IpAddress dstAddress() {
+ return dstAddress;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("type", type())
+ .add("length", length())
+ .add("dstAddress", dstAddress)
+ .toString();
+ }
+
+ /**
+ * Returns a decoder for a destination address route attribute.
+ *
+ * @return destination address route attribute decoder
+ */
+ public static RouteAttributeDecoder<RouteAttributeDst> decoder() {
+ return (int length, int type, byte[] value) -> {
+
+ IpAddress dstAddress;
+ if (value.length == Ip4Address.BYTE_LENGTH) {
+ dstAddress = IpAddress.valueOf(IpAddress.Version.INET, value);
+ } else if (value.length == Ip6Address.BYTE_LENGTH) {
+ dstAddress = IpAddress.valueOf(IpAddress.Version.INET6, value);
+ } else {
+ throw new DeserializationException("Invalid address length");
+ }
+
+ return new RouteAttributeDst(length, type, dstAddress);
+ };
+ }
+}
diff --git a/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/protocol/RouteAttributeGateway.java b/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/protocol/RouteAttributeGateway.java
new file mode 100644
index 0000000..0f5d158
--- /dev/null
+++ b/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/protocol/RouteAttributeGateway.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.routing.fpm.protocol;
+
+import com.google.common.base.MoreObjects;
+import org.onlab.packet.DeserializationException;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.Ip6Address;
+import org.onlab.packet.IpAddress;
+
+/**
+ * Gateway route attribute.
+ */
+public final class RouteAttributeGateway extends RouteAttribute {
+
+ public static final int VALUE_LENGTH = 4;
+
+ private final IpAddress gateway;
+
+ /**
+ * Class constructor.
+ *
+ * @param length length
+ * @param type type
+ * @param gateway gateway address
+ */
+ private RouteAttributeGateway(int length, int type, IpAddress gateway) {
+ super(length, type);
+
+ this.gateway = gateway;
+ }
+
+ /**
+ * Returns the gateway address.
+ *
+ * @return gateway address
+ */
+ public IpAddress gateway() {
+ return gateway;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("type", type())
+ .add("length", length())
+ .add("gateway", gateway)
+ .toString();
+ }
+
+ /**
+ * Returns a decoder for a gateway route attribute.
+ *
+ * @return gateway route attribute decoder
+ */
+ public static RouteAttributeDecoder<RouteAttributeGateway> decoder() {
+ return (int length, int type, byte[] value) -> {
+
+ IpAddress gateway;
+ if (value.length == Ip4Address.BYTE_LENGTH) {
+ gateway = IpAddress.valueOf(IpAddress.Version.INET, value);
+ } else if (value.length == Ip6Address.BYTE_LENGTH) {
+ gateway = IpAddress.valueOf(IpAddress.Version.INET6, value);
+ } else {
+ throw new DeserializationException("Invalid address length");
+ }
+
+ return new RouteAttributeGateway(length, type, gateway);
+ };
+ }
+
+}
diff --git a/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/protocol/RouteAttributeOif.java b/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/protocol/RouteAttributeOif.java
new file mode 100644
index 0000000..28c4b32
--- /dev/null
+++ b/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/protocol/RouteAttributeOif.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.routing.fpm.protocol;
+
+import com.google.common.base.MoreObjects;
+import org.onlab.packet.DeserializationException;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Output interface route attribute.
+ */
+public final class RouteAttributeOif extends RouteAttribute {
+
+ private static final int VALUE_LENGTH = 4;
+
+ private final long outputInterface;
+
+ /**
+ * Class constructor.
+ *
+ * @param length length
+ * @param type type
+ * @param outputInterface output interface
+ */
+ private RouteAttributeOif(int length, int type, long outputInterface) {
+ super(length, type);
+
+ this.outputInterface = outputInterface;
+ }
+
+ /**
+ * Returns the output interface.
+ *
+ * @return output interface
+ */
+ public long outputInterface() {
+ return outputInterface;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("type", type())
+ .add("length", length())
+ .add("outputInterface", outputInterface)
+ .toString();
+ }
+
+ /**
+ * Returns a decoder for a output interface route attribute.
+ *
+ * @return output interface route attribute decoder
+ */
+ public static RouteAttributeDecoder<RouteAttributeOif> decoder() {
+ return (int length, int type, byte[] value) -> {
+ if (value.length != VALUE_LENGTH) {
+ throw new DeserializationException("Wrong value length");
+ }
+
+ long outputInterface = Integer.reverseBytes(ByteBuffer.wrap(value).getInt());
+
+ return new RouteAttributeOif(length, type, outputInterface);
+ };
+ }
+}
diff --git a/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/protocol/RouteAttributePriority.java b/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/protocol/RouteAttributePriority.java
new file mode 100644
index 0000000..8f324f9
--- /dev/null
+++ b/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/protocol/RouteAttributePriority.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.routing.fpm.protocol;
+
+import com.google.common.base.MoreObjects;
+import org.onlab.packet.DeserializationException;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Priority route attribute.
+ */
+public final class RouteAttributePriority extends RouteAttribute {
+
+ private static final int VALUE_LENGTH = 4;
+
+ private final long priority;
+
+ /**
+ * Class constructor.
+ *
+ * @param length length
+ * @param type type
+ * @param priority priority
+ */
+ private RouteAttributePriority(int length, int type, long priority) {
+ super(length, type);
+
+ this.priority = priority;
+ }
+
+ /**
+ * Returns the priority.
+ *
+ * @return priority
+ */
+ public long priority() {
+ return priority;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("type", type())
+ .add("length", length())
+ .add("priority", priority)
+ .toString();
+ }
+
+ /**
+ * Returns a decoder for a priority route attribute.
+ *
+ * @return priority route attribute decoder
+ */
+ public static RouteAttributeDecoder<RouteAttributePriority> decoder() {
+ return (int length, int type, byte[] value) -> {
+ if (value.length != VALUE_LENGTH) {
+ throw new DeserializationException("Wrong value length");
+ }
+
+ long priority = Integer.reverseBytes(ByteBuffer.wrap(value).getInt());
+
+ return new RouteAttributePriority(length, type, priority);
+ };
+ }
+
+}
diff --git a/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/protocol/RtNetlink.java b/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/protocol/RtNetlink.java
new file mode 100644
index 0000000..f914f0c
--- /dev/null
+++ b/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/protocol/RtNetlink.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.routing.fpm.protocol;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableList;
+import org.onlab.packet.DeserializationException;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.onlab.packet.PacketUtils.checkInput;
+
+/**
+ * Netlink routing message (rtnetlink).
+ * <p>
+ * Taken from struct rtmsg in linux/rtnetlink.h
+ * </p>
+ */
+public final class RtNetlink {
+
+ private static final int RT_NETLINK_LENGTH = 12;
+
+ private static final int MASK = 0xff;
+
+ private final short addressFamily;
+ private final int dstLength;
+ private final int srcLength;
+ private final short tos;
+ private final short table;
+ private final RtProtocol protocol;
+ private final short scope;
+ private final short type;
+ private final long flags;
+
+ private final List<RouteAttribute> attributes;
+
+ /**
+ * Class constructor.
+ *
+ * @param addressFamily address family
+ * @param dstLength destination address length
+ * @param srcLength source address length
+ * @param tos type of service
+ * @param table routing table
+ * @param protocol protocol
+ * @param scope scope
+ * @param type type
+ * @param flags flags
+ * @param attributes list of attributes
+ */
+ private RtNetlink(short addressFamily,
+ int dstLength,
+ int srcLength,
+ short tos,
+ short table,
+ RtProtocol protocol,
+ short scope,
+ short type,
+ long flags,
+ List<RouteAttribute> attributes) {
+
+ this.addressFamily = addressFamily;
+ this.dstLength = dstLength;
+ this.srcLength = srcLength;
+ this.tos = tos;
+ this.table = table;
+ this.protocol = protocol;
+ this.scope = scope;
+ this.type = type;
+ this.flags = flags;
+
+ this.attributes = ImmutableList.copyOf(attributes);
+
+ }
+
+ /**
+ * Returns the address family of the route.
+ *
+ * @return address family
+ */
+ public short addressFamily() {
+ return addressFamily;
+ }
+
+ /**
+ * Returns the destination address length.
+ *
+ * @return destination address length
+ */
+ public int dstLength() {
+ return dstLength;
+ }
+
+ /**
+ * Returns the source address length.
+ *
+ * @return source address length
+ */
+ public int srcLength() {
+ return srcLength;
+ }
+
+ /**
+ * Returns the type of service.
+ *
+ * @return type of service
+ */
+ public short tos() {
+ return tos;
+ }
+
+ /**
+ * Returns the routing table.
+ *
+ * @return routing table
+ */
+ public short table() {
+ return table;
+ }
+
+ /**
+ * Returns the protocol.
+ *
+ * @return protocol
+ */
+ public RtProtocol protocol() {
+ return protocol;
+ }
+
+ /**
+ * Returns the route scope.
+ *
+ * @return scope
+ */
+ public short scope() {
+ return scope;
+ }
+
+ /**
+ * Returns the route type.
+ *
+ * @return route type
+ */
+ public short type() {
+ return type;
+ }
+
+ /**
+ * Returns the route flags.
+ *
+ * @return route flags
+ */
+ public long flags() {
+ return flags;
+ }
+
+ /**
+ * Returns the list of route attributes.
+ *
+ * @return route attributes
+ */
+ public List<RouteAttribute> attributes() {
+ return attributes;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("addressFamily", addressFamily)
+ .add("dstLength", dstLength)
+ .add("srcLength", srcLength)
+ .add("tos", tos)
+ .add("table", table)
+ .add("protocol", protocol)
+ .add("scope", scope)
+ .add("type", type)
+ .add("flags", flags)
+ .add("attributes", attributes)
+ .toString();
+ }
+
+ /**
+ * Decodes an rtnetlink message from an input buffer.
+ *
+ * @param buffer input buffer
+ * @param start starting position the rtnetlink message
+ * @param length length of the message
+ * @return rtnetlink message
+ * @throws DeserializationException if an rtnetlink message could not be
+ * decoded from the input buffer
+ */
+ public static RtNetlink decode(byte[] buffer, int start, int length)
+ throws DeserializationException {
+ checkInput(buffer, start, length, RT_NETLINK_LENGTH);
+
+ ByteBuffer bb = ByteBuffer.wrap(buffer, start, length);
+
+ short addressFamily = (short) (bb.get() & MASK);
+ int dstLength = bb.get() & MASK;
+ int srcLength = bb.get() & MASK;
+ short tos = (short) (bb.get() & MASK);
+ short table = (short) (bb.get() & MASK);
+ short protocol = (short) (bb.get() & MASK);
+ short scope = (short) (bb.get() & MASK);
+ short type = (short) (bb.get() & MASK);
+ long flags = Integer.reverseBytes(bb.getInt());
+ List<RouteAttribute> attributes = new ArrayList<>();
+
+ RtProtocol rtProtocol = RtProtocol.get(protocol);
+
+ while (bb.hasRemaining()) {
+ RouteAttribute attribute = RouteAttribute.decode(buffer, bb.position(),
+ bb.limit() - bb.position());
+ attributes.add(attribute);
+ bb.position(bb.position() + attribute.length());
+ }
+
+ return new RtNetlink(
+ addressFamily,
+ dstLength,
+ srcLength,
+ tos,
+ table,
+ rtProtocol,
+ scope,
+ type,
+ flags,
+ attributes);
+ }
+
+}
diff --git a/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/protocol/RtProtocol.java b/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/protocol/RtProtocol.java
new file mode 100644
index 0000000..de86394
--- /dev/null
+++ b/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/protocol/RtProtocol.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.routing.fpm.protocol;
+
+/**
+ * RtNetlink protocol value.
+ * <p>
+ * This is a subset of the protocol values used in rtnetlink.
+ * Taken from linux/rtnetlink.h
+ * </p>
+ */
+public enum RtProtocol {
+ /**
+ * Unspecified.
+ */
+ UNSPEC((short) 0),
+
+ /**
+ * Route installed by ICMP redirects.
+ */
+ REDIRECT((short) 1),
+
+ /**
+ * Route installed by kernel.
+ */
+ KERNEL((short) 2),
+
+ /**
+ * Route installed during boot.
+ */
+ BOOT((short) 3),
+
+ /**
+ * Route installed by administrator.
+ */
+ STATIC((short) 4),
+
+ /**
+ * GateD.
+ */
+ GATED((short) 8),
+
+ /**
+ * RDISC/ND router advertisements.
+ */
+ RA((short) 9),
+
+ /**
+ * Merit MRT.
+ */
+ MRT((short) 10),
+
+ /**
+ * Zebra.
+ */
+ ZEBRA((short) 11),
+
+ /**
+ * BIRD.
+ */
+ BIRD((short) 12),
+
+ /**
+ * DECnet routing daemon.
+ */
+ DNROUTED((short) 13),
+
+ /**
+ * XORP.
+ */
+ XORP((short) 14),
+
+ /**
+ * Netsukuku.
+ */
+ NTK((short) 15),
+
+ /**
+ * DHCP client.
+ */
+ DHCP((short) 16),
+
+ /**
+ * Multicast daemon.
+ */
+ MROUTED((short) 17),
+
+ /**
+ * Unknown.
+ */
+ UNKNOWN((short) 0);
+
+ private final short value;
+
+ /**
+ * Constructor.
+ *
+ * @param value value
+ */
+ RtProtocol(short value) {
+ this.value = value;
+ }
+
+ /**
+ * Returns the value.
+ *
+ * @return value
+ */
+ public short value() {
+ return value;
+ }
+
+ /**
+ * Gets the RtProtocol for the given integer value.
+ *
+ * @param value value
+ * @return RtProtocol, or null if unsupported type value
+ */
+ public static RtProtocol get(short value) {
+ for (RtProtocol p : RtProtocol.values()) {
+ if (p.value() == value) {
+ return p;
+ }
+ }
+ return UNKNOWN;
+ }
+}
diff --git a/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/protocol/package-info.java b/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/protocol/package-info.java
new file mode 100644
index 0000000..fed7b1e
--- /dev/null
+++ b/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/protocol/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * FPM protocol implementation.
+ */
+package org.onosproject.routing.fpm.protocol;