fpm: Add protobuf support for FPM.

Code that allows a client to convey routes to a Forwarding Plane
Manager component using protobuf instead of netlink..

  * fpm/fpm.proto

    Protobuf definitions pertaining to the Forwarding Plane Manager.
    In particular, this file defines the AddRoute and DeleteRoute
    messages.

  * fpm/fpm.h

    Tweak FPM message header definition to also allow messages to be
    encoded in protobuf format.

  * fpm/{fpm_pb.h,.gitignore,.Makefile.am}

    Add the fpm_pb library, which contains code for interfacing with
    the FPM using protobuf.

  * configure.ac

    Generate fpm/Makefile.

  * Makefile.am

    Add fpm subdirectory to build.

  * common.am

    Add flags to be used by clients of the fpm_pb library.

Signed-off-by: Avneesh Sachdev <avneesh@sproute.com>
diff --git a/Makefile.am b/Makefile.am
index 87ba3d0..0cd75be 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,10 +1,10 @@
 ## Process this file with automake to produce Makefile.in.
 
-SUBDIRS = lib qpb @ZEBRA@ @BGPD@ @RIPD@ @RIPNGD@ @OSPFD@ @OSPF6D@ \
+SUBDIRS = lib qpb fpm @ZEBRA@ @BGPD@ @RIPD@ @RIPNGD@ @OSPFD@ @OSPF6D@ \
          @ISISD@ @PIMD@ @WATCHQUAGGA@ @VTYSH@ @OSPFCLIENT@ @DOC@ m4 @pkgsrcdir@ \
          redhat @SOLARIS@ tests
 
-DIST_SUBDIRS = lib qpb zebra bgpd ripd ripngd ospfd ospf6d \
+DIST_SUBDIRS = lib qpb fpm zebra bgpd ripd ripngd ospfd ospf6d \
 	  isisd watchquagga vtysh ospfclient doc m4 pkgsrc redhat tests \
 	  solaris pimd
 
@@ -12,8 +12,7 @@
 	update-autotools \
 	vtysh/Makefile.in vtysh/Makefile.am \
 	tools/rrcheck.pl tools/rrlookup.pl tools/zc.pl \
-	tools/zebra.el tools/multiple-bgpd.sh \
-	fpm/fpm.h
+	tools/zebra.el tools/multiple-bgpd.sh
 
 if HAVE_LATEX
 
diff --git a/configure.ac b/configure.ac
index 8d92a3d..3818990 100755
--- a/configure.ac
+++ b/configure.ac
@@ -1585,6 +1585,7 @@
 	  tests/libzebra.tests/Makefile
 	  redhat/Makefile
 	  pkgsrc/Makefile
+	  fpm/Makefile
 	  redhat/quagga.spec 
 	  lib/version.h
 	  doc/defines.texi
diff --git a/fpm/.gitignore b/fpm/.gitignore
new file mode 100644
index 0000000..b133c52
--- /dev/null
+++ b/fpm/.gitignore
@@ -0,0 +1,15 @@
+Makefile
+Makefile.in
+*.o
+tags
+TAGS
+.deps
+.nfs*
+*.lo
+*.la
+*.a
+*.libs
+.arch-inventory
+.arch-ids
+*~
+*.loT
diff --git a/fpm/Makefile.am b/fpm/Makefile.am
new file mode 100644
index 0000000..83ab31c
--- /dev/null
+++ b/fpm/Makefile.am
@@ -0,0 +1,29 @@
+include ../common.am
+
+AM_CPPFLAGS = -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib $(Q_PROTOBUF_C_CLIENT_INCLUDES)
+
+PROTOBUF_INCLUDES=-I$(top_srcdir)
+PROTOBUF_PACKAGE = fpm
+
+lib_LTLIBRARIES = libfpm_pb.la
+libfpm_pb_la_LDFLAGS = -version-info 0:0:0
+
+if HAVE_PROTOBUF
+protobuf_srcs =
+
+protobuf_srcs_nodist =				\
+	fpm.pb-c.c
+endif
+
+libfpm_pb_la_SOURCES =				\
+	fpm.h					\
+	fpm_pb.h				\
+	fpm_pb.c				\
+	$(protobuf_srcs)
+
+nodist_libfpm_pb_la_SOURCES = $(protobuf_srcs_nodist)
+
+CLEANFILES = $(Q_CLEANFILES)
+
+BUILT_SOURCES = $(Q_PROTOBUF_SRCS)
+EXTRA_DIST = fpm.proto
diff --git a/fpm/fpm.h b/fpm/fpm.h
index 9a1dbf2..8528599 100644
--- a/fpm/fpm.h
+++ b/fpm/fpm.h
@@ -102,6 +102,10 @@
  */
 #define FPM_MAX_MSG_LEN 4096
 
+#ifdef __SUNPRO_C
+#pragma pack(1)
+#endif
+
 /*
  * Header that precedes each fpm message to/from the FPM.
  */
@@ -120,13 +124,13 @@
   /*
    * Length of entire message, including the header, in network byte
    * order.
-   *
-   * Note that msg_len is rounded up to make sure that message is at
-   * the desired alignment. This means that some payloads may need
-   * padding at the end.
    */
   uint16_t msg_len;
-} fpm_msg_hdr_t;
+} __attribute__ ((packed)) fpm_msg_hdr_t;
+
+#ifdef __SUNPRO_C
+#pragma pack()
+#endif
 
 /*
  * The current version of the FPM protocol is 1.
@@ -139,8 +143,14 @@
   /*
    * Indicates that the payload is a completely formed netlink
    * message.
+   *
+   * XXX Netlink cares about the alignment of messages. When any
+   * FPM_MSG_TYPE_NETLINK messages are sent over a channel, then all
+   * messages should be sized such that netlink alignment is
+   * maintained.
    */
   FPM_MSG_TYPE_NETLINK = 1,
+  FPM_MSG_TYPE_PROTOBUF = 2,
 } fpm_msg_type_e;
 
 /*
@@ -154,6 +164,8 @@
  * fpm_msg_align
  *
  * Round up the given length to the desired alignment.
+ *
+ * **NB**: Alignment is required only when netlink messages are used.
  */
 static inline size_t
 fpm_msg_align (size_t len)
@@ -165,7 +177,13 @@
  * The (rounded up) size of the FPM message header. This ensures that
  * the message payload always starts at an aligned address.
  */
-#define FPM_MSG_HDR_LEN (fpm_msg_align (sizeof (fpm_msg_hdr_t)))
+#define FPM_MSG_HDR_LEN (sizeof (fpm_msg_hdr_t))
+
+#ifndef COMPILE_ASSERT
+#define COMPILE_ASSERT(x) extern int __dummy[2 * !!(x) - 1]
+#endif
+
+COMPILE_ASSERT(FPM_MSG_ALIGNTO == FPM_MSG_HDR_LEN);
 
 /*
  * fpm_data_len_to_msg_len
@@ -176,7 +194,7 @@
 static inline size_t
 fpm_data_len_to_msg_len (size_t data_len)
 {
-  return fpm_msg_align (data_len) + FPM_MSG_HDR_LEN;
+  return data_len + FPM_MSG_HDR_LEN;
 }
 
 /*
@@ -250,7 +268,11 @@
   if (msg_len < FPM_MSG_HDR_LEN || msg_len > FPM_MAX_MSG_LEN)
     return 0;
 
-  if (fpm_msg_align (msg_len) != msg_len)
+  /*
+   * Netlink messages must be aligned properly.
+   */
+  if (hdr->msg_type == FPM_MSG_TYPE_NETLINK &&
+      fpm_msg_align (msg_len) != msg_len)
     return 0;
 
   return 1;
diff --git a/fpm/fpm.proto b/fpm/fpm.proto
new file mode 100644
index 0000000..26d6346
--- /dev/null
+++ b/fpm/fpm.proto
@@ -0,0 +1,119 @@
+//
+// fpm.proto
+//
+// @copyright Copyright (C) 2016 Sproute Networks, Inc.
+//
+// @author Avneesh Sachdev <avneesh@sproute.com>
+//
+// Permission is granted to use, copy, modify and/or distribute this
+// software under either one of the licenses below.
+//
+// Note that if you use other files from the Quagga tree directly or
+// indirectly, then the licenses in those files still apply.
+//
+// Please retain both licenses below when modifying this code in the
+// Quagga tree.
+//
+
+//
+// License Option 1: GPL
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//
+
+//
+// License Option 2: ISC License
+//
+// Permission to use, copy, modify, and/or distribute this software
+// for any purpose with or without fee is hereby granted, provided
+// that the above copyright notice and this permission notice appear
+// in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
+// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+// OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+// NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+
+//
+// Protobuf definitions pertaining to the Forwarding Plane Manager component.
+//
+
+package fpm;
+
+import "qpb/qpb.proto";
+
+//
+// A Nexthop for a route. It indicates how packets to a given prefix
+// should be forwarded (for instance, send them out of a specified
+// interface to a specified address).
+//
+message Nexthop {
+  optional qpb.IfIdentifier if_id = 2;
+  optional qpb.L3Address address = 3;
+}
+
+message RouteKey {
+  optional qpb.L3Prefix prefix = 1;
+}
+
+message DeleteRoute {
+  required uint32 vrf_id = 1;
+  required qpb.AddressFamily address_family = 2;
+  required qpb.SubAddressFamily sub_address_family = 3;
+  required RouteKey key = 4;
+}
+
+enum RouteType {
+  UNKNOWN = 0;
+  NORMAL = 1;
+  UNREACHABLE = 2;
+  BLACKHOLE = 3;
+}
+
+message AddRoute {
+  required uint32 vrf_id = 1;
+  required qpb.AddressFamily address_family = 2;
+  required qpb.SubAddressFamily sub_address_family = 3;
+  required RouteKey key = 4;
+
+  optional RouteType route_type = 5;
+
+  required qpb.Protocol protocol = 6;
+
+  required int32 metric = 8;
+
+  repeated Nexthop nexthops = 9;
+}
+
+//
+// Any message from the FPM.
+//
+message Message {
+  enum Type {
+    UNKNOWN_MSG = 0;
+    ADD_ROUTE = 1;
+    DELETE_ROUTE = 2;
+  };
+
+  optional Type type = 1;
+
+  optional AddRoute add_route = 2;
+  optional DeleteRoute delete_route = 3;
+}
diff --git a/fpm/fpm_pb.c b/fpm/fpm_pb.c
new file mode 100644
index 0000000..ba18627
--- /dev/null
+++ b/fpm/fpm_pb.c
@@ -0,0 +1,28 @@
+/*
+ * fpm_pb.c
+ *
+ * @copyright Copyright (C) 2016 Sproute Networks, Inc.
+ *
+ * @author Avneesh Sachdev <avneesh@sproute.com>
+ *
+ * This file is part of Quagga.
+ *
+ * Quagga is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * Quagga is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Quagga; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+/*
+ * Main file for the fpm_pb library.
+ */
diff --git a/fpm/fpm_pb.h b/fpm/fpm_pb.h
new file mode 100644
index 0000000..8f74ac0
--- /dev/null
+++ b/fpm/fpm_pb.h
@@ -0,0 +1,63 @@
+/*
+ * fpm_pb.h
+ *
+ * @copyright Copyright (C) 2016 Sproute Networks, Inc.
+ *
+ * @author Avneesh Sachdev <avneesh@sproute.com>
+ *
+ * This file is part of Quagga.
+ *
+ * Quagga is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * Quagga is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Quagga; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+/*
+ * Public header file for fpm protobuf definitions.
+ */
+
+#ifndef _FPM_PB_H
+#define _FPM_PB_H
+
+#include "route_types.h"
+#include "qpb/qpb.h"
+
+#include "fpm/fpm.pb-c.h"
+
+/*
+ * fpm__route_key__create
+ */
+#define fpm_route_key_create fpm__route_key__create
+static inline Fpm__RouteKey *
+fpm__route_key__create (qpb_allocator_t *allocator, struct prefix *prefix)
+{
+  Fpm__RouteKey *key;
+
+  key = QPB_ALLOC (allocator, typeof (*key));
+  if (!key)
+    {
+      return NULL;
+    }
+  fpm__route_key__init (key);
+
+  key->prefix = qpb__l3_prefix__create (allocator, prefix);
+  if (!key->prefix)
+    {
+      return NULL;
+    }
+
+  return key;
+}
+
+#endif