From: Timo Teräs Date: Wed, 29 Apr 2015 06:43:04 +0000 (+0300) Subject: bgpd: allow using rtt in route-map's set metric X-Git-Tag: frr-2.0-rc1~621 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=baa376fc1;p=mirror%2Ffrr.git 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 Signed-off-by: David Lamparter (cherry picked from commit ef757700d0fd51dc0b46df9d3631208919f9b779) --- diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index 6c1e9e2f96..bf8ba199e4 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -28,6 +28,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "log.h" #include "memory.h" #include "sockunion.h" /* for inet_ntop () */ +#include "sockopt.h" #include "linklist.h" #include "plist.h" #include "queue.h" @@ -2345,6 +2346,7 @@ bgp_read (struct thread *thread) { 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 7a7814d414..d32c79d204 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -117,22 +117,33 @@ o Local extensions 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) { @@ -152,8 +163,8 @@ route_value_adjust (struct rmap_value *rv, u_int32_t current) 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; @@ -168,16 +179,27 @@ route_value_compile (const char *arg) 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; } @@ -1244,7 +1266,7 @@ route_set_local_pref (void *rule, struct prefix *prefix, 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; @@ -1277,7 +1299,7 @@ route_set_weight (void *rule, struct prefix *prefix, route_map_object_t type, 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) @@ -1316,7 +1338,7 @@ route_set_metric (void *rule, struct prefix *prefix, 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; @@ -3640,6 +3662,15 @@ ALIAS (set_metric, "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", @@ -4625,6 +4656,7 @@ bgp_route_map_init (void) 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 70d2c60010..5041e64eeb 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -12030,6 +12030,11 @@ bgp_show_peer (struct vty *vty, struct peer *p, u_char use_json, json_object *js } } + /* 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 (use_json) { diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 1e7a00628f..b3e508634e 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -569,6 +569,7 @@ struct peer /* 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 */