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