bgpd: allow using rtt in route-map's set metric
Useful when the BGP neighbors are over tunnels that have large
differences in geographic distances and RTTs. Especially useful
for DMVPN setups to allow preferring closes hub.
The parameter is added as new alias command as otherwise it seems
the command parser is not able to match it properly (it seems
merging is done for the various 'set metric' route-map objects in
different routing engines). For same reason also they are listed
as three separate options: optional +/- seems not possibly easily.
Related research papers:
http://www.pps.univ-paris-diderot.fr/~jch/research/delay-based.pdf
http://arxiv.org/pdf/1309.0632.pdf
Paper on similar extension to Babel:
http://www.pps.univ-paris-diderot.fr/~jch/research/rapport-jonglez-2013.pdf
Signed-off-by: Timo Teräs <timo.teras@iki.fi>
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index 18114ad..7d27972 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -28,6 +28,7 @@
#include "log.h"
#include "memory.h"
#include "sockunion.h" /* for inet_ntop () */
+#include "sockopt.h"
#include "linklist.h"
#include "plist.h"
@@ -2592,6 +2593,7 @@
{
case BGP_MSG_OPEN:
peer->open_in++;
+ peer->rtt = sockopt_tcp_rtt(peer->fd);
bgp_open_receive (peer, size); /* XXX return value ignored! */
break;
case BGP_MSG_UPDATE:
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index 4a0dac7..5467cfd 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -110,22 +110,33 @@
struct rmap_value
{
u_int8_t action;
+ u_int8_t variable;
u_int32_t value;
};
static int
route_value_match (struct rmap_value *rv, u_int32_t value)
{
- if (value == rv->value)
+ if (rv->variable == 0 && value == rv->value)
return RMAP_MATCH;
return RMAP_NOMATCH;
}
static u_int32_t
-route_value_adjust (struct rmap_value *rv, u_int32_t current)
+route_value_adjust (struct rmap_value *rv, u_int32_t current, struct peer *peer)
{
- u_int32_t value = rv->value;
+ u_int32_t value;
+
+ switch (rv->variable)
+ {
+ case 1:
+ value = peer->rtt;
+ break;
+ default:
+ value = rv->value;
+ break;
+ }
switch (rv->action)
{
@@ -145,8 +156,8 @@
static void *
route_value_compile (const char *arg)
{
- u_int8_t action = RMAP_VALUE_SET;
- unsigned long larg;
+ u_int8_t action = RMAP_VALUE_SET, var = 0;
+ unsigned long larg = 0;
char *endptr = NULL;
struct rmap_value *rv;
@@ -161,16 +172,27 @@
arg++;
}
- errno = 0;
- larg = strtoul (arg, &endptr, 10);
- if (*arg == 0 || *endptr != 0 || errno || larg > UINT32_MAX)
- return NULL;
+ if (all_digit(arg))
+ {
+ errno = 0;
+ larg = strtoul (arg, &endptr, 10);
+ if (*arg == 0 || *endptr != 0 || errno || larg > UINT32_MAX)
+ return NULL;
+ }
+ else
+ {
+ if (strcmp(arg, "rtt") == 0)
+ var = 1;
+ else
+ return NULL;
+ }
rv = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_value));
if (!rv)
return NULL;
rv->action = action;
+ rv->variable = var;
rv->value = larg;
return rv;
}
@@ -1050,7 +1072,7 @@
locpref = bgp_info->attr->local_pref;
bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF);
- bgp_info->attr->local_pref = route_value_adjust(rv, locpref);
+ bgp_info->attr->local_pref = route_value_adjust(rv, locpref, bgp_info->peer);
}
return RMAP_OKAY;
@@ -1083,7 +1105,7 @@
bgp_info = object;
/* Set weight value. */
- weight = route_value_adjust(rv, 0);
+ weight = route_value_adjust(rv, 0, bgp_info->peer);
if (weight)
(bgp_attr_extra_get (bgp_info->attr))->weight = weight;
else if (bgp_info->attr->extra)
@@ -1122,7 +1144,7 @@
if (bgp_info->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
med = bgp_info->attr->med;
- bgp_info->attr->med = route_value_adjust(rv, med);
+ bgp_info->attr->med = route_value_adjust(rv, med, bgp_info->peer);
bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
}
return RMAP_OKAY;
@@ -2974,6 +2996,15 @@
"Metric value for destination routing protocol\n"
"Add or subtract metric\n")
+ALIAS (set_metric,
+ set_metric_rtt_cmd,
+ "set metric (rtt|+rtt|-rtt)",
+ SET_STR
+ "Metric value for destination routing protocol\n"
+ "Assign round trip time\n"
+ "Add round trip time\n"
+ "Subtract round trip time\n")
+
DEFUN (no_set_metric,
no_set_metric_cmd,
"no set metric",
@@ -3937,6 +3968,7 @@
install_element (RMAP_NODE, &no_set_weight_val_cmd);
install_element (RMAP_NODE, &set_metric_cmd);
install_element (RMAP_NODE, &set_metric_addsub_cmd);
+ install_element (RMAP_NODE, &set_metric_rtt_cmd);
install_element (RMAP_NODE, &no_set_metric_cmd);
install_element (RMAP_NODE, &no_set_metric_val_cmd);
install_element (RMAP_NODE, &set_aspath_prepend_cmd);
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 00d766d..6233163 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -7906,6 +7906,11 @@
#endif /* HAVE_IPV6 */
}
+ /* TCP metrics. */
+ if (p->status == Established && p->rtt)
+ vty_out (vty, "Estimated round trip time: %d ms%s",
+ p->rtt, VTY_NEWLINE);
+
/* Timer information. */
if (p->t_start)
vty_out (vty, "Next start timer due in %ld seconds%s",
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 40c381c..58d1eca 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -331,6 +331,7 @@
/* Peer information */
int fd; /* File descriptor */
int ttl; /* TTL of TCP connection to the peer. */
+ int rtt; /* Estimated round-trip-time from TCP_INFO */
int gtsm_hops; /* minimum hopcount to peer */
char *desc; /* Description of the peer. */
unsigned short port; /* Destination port for peer */