[PATCH 3/3] FEAT: Add protocol volatile

Thierry FOURNIER tfournier at exceliance.fr
Fri Aug 23 15:15:33 CEST 2013


---
 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 <tfournier at 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 <tfournier at 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 <tfournier at 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


--Multipart=_Tue__24_Sep_2013_16_35_48_+0200_AMU0Imo+Flc+Ayzu--



More information about the Bird-users mailing list