Hello,

I submit two patched.

   0001-PATCH-FLX-Add-command-line-option-for-specifying-the.patch

The first one is to add the -P <pidfile> argument on the command line.
On some distributions, the pidfile is managed into the start script and
not into the configuration file.

   0003-FEAT-Add-protocol-volatile.patch

The second patch is new protocol. I named it "protocol volatile". This
permit to add routes into bird via the control socket. These route are
volatile: when bird restart, they are lost.

This is useful for servers using transparent redirect and transparent
binding like "squid" or "haproxy". This two softs can receive trafic for
an ip not present on the system. This new feature "protocol volatile"
permit to do high avalaibility infrastructure with announcing these
routes only if the service is avalaible. This permit also to do
load-balacing: if many computers annouce the same route, the router can
be use ecmp algorithm for the repartion.

Thierry FOURNIER
>From d41ceea7dd017f731dff85c815f18db32f987a0a Mon Sep 17 00:00:00 2001
From: Exceliance (author: D. Ducolombier) <cont...@exceliance.fr>
Date: Wed, 28 Aug 2013 14:57:14 +0200
Subject: [PATCH 1/3] PATCH FLX: Add command line option for specifying the pid
 file

---
 sysdep/unix/main.c | 31 +++++++++++++++++++++++++++++--
 1 file changed, 29 insertions(+), 2 deletions(-)

diff --git a/sysdep/unix/main.c b/sysdep/unix/main.c
index bd80ba2..c0b2b22 100644
--- a/sysdep/unix/main.c
+++ b/sysdep/unix/main.c
@@ -548,16 +548,17 @@ signal_init(void)
  *	Parsing of command-line arguments
  */
 
-static char *opt_list = "c:dD:ps:u:g:";
+static char *opt_list = "c:dD:ps:u:g:P:";
 static int parse_and_exit;
 char *bird_name;
 static char *use_user;
 static char *use_group;
+static char *pid_file;
 
 static void
 usage(void)
 {
-  fprintf(stderr, "Usage: %s [-c <config-file>] [-d] [-D <debug-file>] [-p] [-s <control-socket>] [-u <user>] [-g <group>]\n", bird_name);
+  fprintf(stderr, "Usage: %s [-c <config-file>] [-d] [-D <debug-file>] [-p] [-s <control-socket>] [-u <user>] [-g <group>] [-P <pid-file>]\n", bird_name);
   exit(1);
 }
 
@@ -621,6 +622,28 @@ get_gid(const char *s)
   return gr->gr_gid;
 }
 
+static inline void
+set_pid(const char *s)
+{
+  int fd;
+  char pid[6];
+
+  if (!s)
+    return;
+
+  memset(pid, 0, sizeof(pid));
+
+  if((fd=open(s, O_WRONLY|O_CREAT, 0664)) == -1)
+    die("Cannot open pid file '%s'", s);
+
+  snprintf(pid, sizeof(pid), "%u", getpid());
+
+  if(write(fd, pid, sizeof(pid)) == -1)
+    die("Cannot write pid file '%s'", s);
+
+  return;
+}
+
 static void
 parse_args(int argc, char **argv)
 {
@@ -662,6 +685,9 @@ parse_args(int argc, char **argv)
       case 'g':
 	use_group = optarg;
 	break;
+      case 'P':
+	pid_file = optarg;
+	break;
       default:
 	usage();
       }
@@ -733,6 +759,7 @@ main(int argc, char **argv)
       dup2(0, 2);
     }
 
+  set_pid(pid_file);
   signal_init();
 
 #ifdef LOCAL_DEBUG
-- 
1.8.1.1

>From f87206e7550ae2afd91917cff94eb310e58e33d2 Mon Sep 17 00:00:00 2001
From: Thierry FOURNIER <tfourn...@exceliance.fr>
Date: Fri, 23 Aug 2013 15:15:33 +0200
Subject: [PATCH 3/3] FEAT: Add protocol volatile

---
 configure                 |   4 +-
 configure.in              |   4 +-
 nest/proto.c              |   3 +
 nest/protocol.h           |   2 +-
 proto/Doc                 |   1 +
 proto/volatile/Doc        |   1 +
 proto/volatile/Makefile   |   6 ++
 proto/volatile/config.Y   |  75 ++++++++++++++++++
 proto/volatile/volatile.c | 195 ++++++++++++++++++++++++++++++++++++++++++++++
 proto/volatile/volatile.h |  46 +++++++++++
 10 files changed, 332 insertions(+), 5 deletions(-)
 create mode 100644 proto/volatile/Doc
 create mode 100644 proto/volatile/Makefile
 create mode 100644 proto/volatile/config.Y
 create mode 100644 proto/volatile/volatile.c
 create mode 100644 proto/volatile/volatile.h

diff --git a/configure b/configure
index 2f4cfd4..8ea9f37 100755
--- a/configure
+++ b/configure
@@ -2355,11 +2355,11 @@ esac
 if test "$enable_ipv6" = yes ; then
 	ip=ipv6
 	SUFFIX=6
-	all_protocols=bgp,ospf,pipe,radv,rip,static
+	all_protocols=bgp,ospf,pipe,radv,rip,static,volatile
 else
 	ip=ipv4
 	SUFFIX=""
-	all_protocols=bgp,ospf,pipe,rip,static
+	all_protocols=bgp,ospf,pipe,rip,static,volatile
 fi
 
 if test "$given_suffix" = yes ; then
diff --git a/configure.in b/configure.in
index 96f2a50..227c241 100644
--- a/configure.in
+++ b/configure.in
@@ -47,11 +47,11 @@ AC_SUBST(runtimedir)
 if test "$enable_ipv6" = yes ; then
 	ip=ipv6
 	SUFFIX=6
-	all_protocols=bgp,ospf,pipe,radv,rip,static
+	all_protocols=bgp,ospf,pipe,radv,rip,static,volatile
 else
 	ip=ipv4
 	SUFFIX=""
-	all_protocols=bgp,ospf,pipe,rip,static
+	all_protocols=bgp,ospf,pipe,rip,static,volatile
 fi
 
 if test "$given_suffix" = yes ; then
diff --git a/nest/proto.c b/nest/proto.c
index 60495aa..61b3882 100644
--- a/nest/proto.c
+++ b/nest/proto.c
@@ -718,6 +718,9 @@ protos_build(void)
 #ifdef CONFIG_BGP
   proto_build(&proto_bgp);
 #endif
+#ifdef CONFIG_VOLATILE
+  proto_build(&proto_volatile);
+#endif
   proto_pool = rp_new(&root_pool, "Protocols");
   proto_flush_event = ev_new(proto_pool);
   proto_flush_event->hook = proto_flush_loop;
diff --git a/nest/protocol.h b/nest/protocol.h
index 033a0ed..6f54ae4 100644
--- a/nest/protocol.h
+++ b/nest/protocol.h
@@ -75,7 +75,7 @@ void protos_dump_all(void);
 
 extern struct protocol
   proto_device, proto_radv, proto_rip, proto_static,
-  proto_ospf, proto_pipe, proto_bgp;
+  proto_ospf, proto_pipe, proto_bgp, proto_volatile;
 
 /*
  *	Routing Protocol Instance
diff --git a/proto/Doc b/proto/Doc
index 16b084f..cb16a43 100644
--- a/proto/Doc
+++ b/proto/Doc
@@ -5,4 +5,5 @@ C pipe
 C rip
 C radv
 C static
+C volatile
 S ../nest/rt-dev.c
diff --git a/proto/volatile/Doc b/proto/volatile/Doc
new file mode 100644
index 0000000..2d34a68
--- /dev/null
+++ b/proto/volatile/Doc
@@ -0,0 +1 @@
+S volatile.c
diff --git a/proto/volatile/Makefile b/proto/volatile/Makefile
new file mode 100644
index 0000000..8388e27
--- /dev/null
+++ b/proto/volatile/Makefile
@@ -0,0 +1,6 @@
+source=volatile.c
+root-rel=../../
+dir-name=proto/volatile
+
+include ../../Rules
+
diff --git a/proto/volatile/config.Y b/proto/volatile/config.Y
new file mode 100644
index 0000000..ce9f795
--- /dev/null
+++ b/proto/volatile/config.Y
@@ -0,0 +1,75 @@
+/*
+ *	BIRD -- Static Protocol Configuration
+ *
+ *      (c) 2013--2013 Thierry FOURNIER <tfourn...@exceliance.fr>
+ *
+ *	Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+CF_HDR
+
+#include "proto/volatile/volatile.h"
+
+CF_DEFINES
+
+#define VOLATILE_CFG ((struct volatile_config *) this_proto)
+
+CF_DECLS
+
+%type <px> prefix_autocorrect
+
+CF_KEYWORDS(VOLATILE, SET, DEL, CLEAR, GATEWAY)
+CF_KEYWORDS(MULTIPATH, WEIGHT)
+
+CF_GRAMMAR
+
+CF_ADDTO(proto, volatile_proto '}')
+
+volatile_proto_start: proto_start VOLATILE {
+     this_proto = proto_config_new(&proto_volatile, sizeof(struct volatile_config), $1);
+  }
+ ;
+
+volatile_proto:
+   volatile_proto_start proto_name '{'
+ | volatile_proto GATEWAY ipa ';' {
+     VOLATILE_CFG->gateway = $3; 
+     VOLATILE_CFG->use_gateway = 1; 
+  }
+ ;
+
+prefix_autocorrect:
+   ipa pxlen {
+     $$.addr = $1;
+     $$.len = $2;
+     ip_addr mask = ipa_mkmask($2);
+     $$.addr = ipa_and($$.addr, mask);
+  }
+ ;
+
+
+CF_CLI_HELP(CONFIGURE VOLATILE, {set|del|clear}, [[Configure volatile routes]])
+
+CF_CLI(CONFIGURE VOLATILE SET, optsym prefix_autocorrect,
+       <name> <network>/<netmask>,
+       [[Add or set volatile routes]])
+{ volatile_configure_set(proto_get_named($4, &proto_volatile), $5); } ;
+
+CF_CLI(CONFIGURE VOLATILE DEL, optsym prefix_autocorrect,
+       <name> <natwork>/<netmask>,
+       [[Delete volatile routes]])
+{ volatile_configure_del(proto_get_named($4, &proto_volatile), $5); } ;
+
+CF_CLI(CONFIGURE VOLATILE CLEAR, optsym,
+       <name>,
+       [[Clear volatile routes]])
+{ volatile_configure_clear(proto_get_named($4, &proto_volatile)); } ;
+
+CF_CLI(SHOW VOLATILE, optsym,
+       <name>,
+       [[Show volatile routes]])
+{ volatile_show(proto_get_named($3, &proto_volatile)); } ;
+
+CF_CODE
+
+CF_END
diff --git a/proto/volatile/volatile.c b/proto/volatile/volatile.c
new file mode 100644
index 0000000..80518b9
--- /dev/null
+++ b/proto/volatile/volatile.c
@@ -0,0 +1,195 @@
+/*
+ *	BIRD -- Volatile Route Generator
+ *
+ *      (c) 2013--2013 Thierry FOURNIER <tfourn...@exceliance.fr>
+ *
+ *	Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+/**
+ * DOC: Volatile
+ *
+ * The volatile protocol take routes from the cli. These routes are annouced
+ * to the peers. These routes cannot be exists on the host or cannot correspond
+ * to any ip address on any interface.
+ *
+ * This type of announce is useful for services using transparent binding.
+ * The transparent binding is used tipically with proxy for proxifying HTTP
+ * connections. The user add route announcement and the destination is rerouted
+ * to the transparent proxy.
+ */
+
+#include "nest/bird.h"
+#include "nest/iface.h"
+#include "nest/protocol.h"
+#include "nest/route.h"
+#include "nest/cli.h"
+#include "conf/conf.h"
+#include "lib/string.h"
+#include "lib/alloca.h"
+
+#include "volatile.h"
+
+struct iface any = {
+	.name = "auto"
+};
+
+static void
+volatile_install(struct volatile_proto *p, ip_addr net, unsigned int masklen)
+{
+	struct network *network;
+	struct rta route_attr_lookup;
+	struct rta *route_attr;
+	struct rte *route;
+	struct neighbor *neigh;
+	struct iface *iface;
+
+	/* find neighbor for the gateway */
+	if (p->cf->use_gateway) {
+		neigh = neigh_find(&p->p, &p->cf->gateway, NEF_STICKY);
+		if (!neigh || !neigh->iface) {
+			log(L_INFO "Cannot find neighbor for the gateway %I", p->cf->gateway);
+			return;
+		}
+		iface = neigh->iface;
+	}
+
+	else 
+		iface = &any;
+
+	/* prepare route attrinutes lookup */
+	bzero(&route_attr_lookup, sizeof(struct rta));
+	route_attr_lookup.proto  = &p->p;
+	route_attr_lookup.scope  = SCOPE_UNIVERSE;
+	route_attr_lookup.cast   = RTC_UNICAST;
+	route_attr_lookup.iface  = iface;
+	if (p->cf->use_gateway) {
+		route_attr_lookup.gw     = p->cf->gateway;
+		route_attr_lookup.source = RTS_STATIC;
+		route_attr_lookup.dest   = RTD_ROUTER;
+	}
+	else {
+		route_attr_lookup.source = RTS_DEVICE;
+		route_attr_lookup.dest   = RTD_DEVICE;
+	}
+
+	/* lookup or add route attribute entry. This call never fail */
+	route_attr = rta_lookup(&route_attr_lookup);
+
+	/* get network entry into the table. This function never fail */
+	network = net_get(p->p.table, net, masklen);
+
+	/* get temporary route, and set attributes */
+	route = rte_get_temp(route_attr);
+	route->net = network;
+	route->pflags = 0;
+
+	/* update the route */
+	rte_update(p->p.table, network, &p->p, &p->p, route);
+}
+
+static void
+volatile_remove(struct volatile_proto *p, ip_addr net, unsigned int masklen)
+{
+	struct network *network;
+
+	/* lookup for network entry. if found remove it */
+	network = net_find(p->p.table, net, masklen);
+	if (network)
+		rte_update(p->p.table, network, &p->p, &p->p, NULL);
+}
+
+/* this function initialize configuration structs */
+static struct proto *
+volatile_init(struct proto_config *C)
+{
+	struct volatile_config *c = (struct volatile_config *) C;
+	struct proto *P = proto_new(C, sizeof(struct volatile_proto));
+	struct volatile_proto *p = (struct volatile_proto *) P;
+
+	p->cf = c;
+	return P;
+}
+
+struct protocol proto_volatile = {
+	name:     "Volatile",
+	template: "volatile%d",
+	init:     volatile_init,
+};
+
+/* this fucntion install new route */
+void
+volatile_configure_set(struct proto *P, struct prefix net)
+{
+	struct volatile_proto *p = (struct volatile_proto *) P;
+
+	volatile_install(p, net.addr, net.len);
+	cli_msg(0, "");
+}
+
+/* this fucntion delete known route */
+void
+volatile_configure_del(struct proto *P, struct prefix net)
+{
+	struct volatile_proto *p = (struct volatile_proto *) P;
+	
+	volatile_remove(p, net.addr, net.len);
+	cli_msg(0, "");
+}
+
+/* this cli function delete all route with restarting protocol */
+void
+volatile_configure_clear(struct proto *P)
+{
+	proto_cmd_restart(P, 0, 0);
+	cli_msg(0, "");
+}
+
+void
+volatile_show(struct proto *P)
+{
+	struct volatile_proto *p = (struct volatile_proto *) P;
+	struct rte *route;
+	struct rta *attrs;
+	struct network *network;
+
+	FIB_WALK(&p->p.table->fib, fn) {
+		network = (struct network *)fn;
+		for (route = network->routes;
+		     route;
+		     route = route->next) {
+
+			if (route->attrs->proto != P)
+				continue;
+
+			network = route->net;
+			attrs = route->attrs;
+
+			if (!network) {
+				cli_msg(-1009, "???");
+				continue;
+			}
+
+			switch (attrs->dest) {
+
+			case RTD_ROUTER:
+				cli_msg(-1009, "%I/%2d via %I dev %s",
+				        network->n.prefix, network->n.pxlen, attrs->gw,
+				        attrs->iface ? attrs->iface->name : "???");
+				break;
+
+			case RTD_DEVICE:
+				cli_msg(-1009, "%I/%2d dev auto",
+				        network->n.prefix, network->n.pxlen);
+				break;
+
+			default:
+				cli_msg(-1009, "%I/%2d ???",
+				        network->n.prefix, network->n.pxlen);
+				break;
+			}
+		}
+	} FIB_WALK_END;
+
+	cli_msg(0, "");
+}
diff --git a/proto/volatile/volatile.h b/proto/volatile/volatile.h
new file mode 100644
index 0000000..fd43873
--- /dev/null
+++ b/proto/volatile/volatile.h
@@ -0,0 +1,46 @@
+/*
+ *	BIRD -- Volatile Route Generator
+ *
+ *      (c) 2013--2013 Thierry FOURNIER <tfourn...@exceliance.fr>
+ *
+ *	Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+#ifndef _BIRD_VOLATILE_H_
+#define _BIRD_VOLATILE_H_
+
+struct volatile_config {
+	struct proto_config c;
+	int use_gateway;
+	ip_addr gateway;
+};
+
+struct volatile_proto {
+	struct proto p;
+	struct volatile_config *cf;      /* Shortcut to volatile configuration */
+};
+
+void volatile_init_config(struct volatile_config *);
+
+struct volatile_route {
+	node n;
+	struct volatile_route *chain;    /* Next for the same neighbor */
+	ip_addr net;                     /* Network we route */
+	int masklen;                     /* Mask length */
+	int dest;                        /* Destination type (RTD_*) */
+	ip_addr via;                     /* Destination router */
+	struct neighbor *neigh;
+	byte *if_name;                   /* Name for RTD_DEVICE routes */
+	struct volatile_route *mp_next;  /* Nexthops for RTD_MULTIPATH routes */
+	int installed;                   /* Installed in master table */
+};
+
+/* Dummy nodes (parts of multipath route) abuses masklen field for weight
+   and if_name field for a ptr to the master (RTD_MULTIPATH) node. */
+
+void volatile_configure_set(struct proto *P, struct prefix net);
+void volatile_configure_del(struct proto *P, struct prefix net);
+void volatile_configure_clear(struct proto *P);
+void volatile_show(struct proto *P);
+
+#endif
-- 
1.8.1.1

Reply via email to