Merge pull request #17038 from opensourcerouting/feature/bgp_set_metric_internal

bgpd: Derive and set MED from IGP or AIGP
This commit is contained in:
Russ White 2024-10-15 17:58:05 -04:00 committed by GitHub
commit de02471a8d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 481 additions and 59 deletions

View File

@ -1177,8 +1177,7 @@ struct attr *bgp_attr_aggregate_intern(
SET_FLAG(attr.flag, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN));
/* MED */
attr.med = 0;
SET_FLAG(attr.flag, ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
bgp_attr_set_med(&attr, 0);
/* AS path attribute. */
if (aspath)
@ -1933,9 +1932,7 @@ static enum bgp_attr_parse_ret bgp_attr_med(struct bgp_attr_parser_args *args)
args->total);
}
attr->med = stream_getl(peer->curr);
SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
bgp_attr_set_med(attr, stream_getl(peer->curr));
return BGP_ATTR_PARSE_PROCEED;
}

View File

@ -608,6 +608,12 @@ static inline uint64_t bgp_aigp_metric_total(struct bgp_path_info *bpi)
return aigp;
}
static inline void bgp_attr_set_med(struct attr *attr, uint32_t med)
{
attr->med = med;
SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
}
static inline struct cluster_list *bgp_attr_get_cluster(const struct attr *attr)
{
return attr->cluster1;

View File

@ -3726,11 +3726,10 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
/* If there is a change of interest to peers, reannounce the
* route. */
if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
|| CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
|| CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED) ||
CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED) ||
bgp_zebra_has_route_changed(old_select)) {
group_announce_route(bgp, afi, safi, dest, new_select);
/* unicast routes must also be annouced to
* labeled-unicast update-groups */
if (safi == SAFI_UNICAST)
@ -6746,8 +6745,8 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p,
bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
attr.nexthop = bgp_static->igpnexthop;
attr.med = bgp_static->igpmetric;
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
bgp_attr_set_med(&attr, bgp_static->igpmetric);
if (afi == AFI_IP)
attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
@ -9014,9 +9013,8 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
else
UNSET_FLAG(attr.nh_flags, BGP_ATTR_NH_IF_OPERSTATE);
attr.med = metric;
bgp_attr_set_med(&attr, metric);
attr.distance = distance;
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
attr.tag = tag;
if (metric)

View File

@ -125,6 +125,10 @@ o Local extensions
#define RMAP_VALUE_ADD 1
#define RMAP_VALUE_SUB 2
#define RMAP_VALUE_TYPE_RTT 1
#define RMAP_VALUE_TYPE_IGP 2
#define RMAP_VALUE_TYPE_AIGP 3
struct rmap_value {
uint8_t action;
uint8_t variable;
@ -140,14 +144,21 @@ static int route_value_match(struct rmap_value *rv, uint32_t value)
}
static uint32_t route_value_adjust(struct rmap_value *rv, uint32_t current,
struct peer *peer)
struct bgp_path_info *bpi)
{
uint32_t value;
struct peer *peer = bpi->peer;
switch (rv->variable) {
case 1:
case RMAP_VALUE_TYPE_RTT:
value = peer->rtt;
break;
case RMAP_VALUE_TYPE_IGP:
value = bpi->extra ? bpi->extra->igpmetric : 0;
break;
case RMAP_VALUE_TYPE_AIGP:
value = MIN(bpi->attr->aigp_metric, UINT32_MAX);
break;
default:
value = rv->value;
break;
@ -187,11 +198,14 @@ static void *route_value_compile(const char *arg)
larg = strtoul(arg, &endptr, 10);
if (*arg == 0 || *endptr != 0 || errno || larg > UINT32_MAX)
return NULL;
} else if (strmatch(arg, "rtt")) {
var = RMAP_VALUE_TYPE_RTT;
} else if (strmatch(arg, "igp")) {
var = RMAP_VALUE_TYPE_IGP;
} else if (strmatch(arg, "aigp")) {
var = RMAP_VALUE_TYPE_AIGP;
} else {
if (strcmp(arg, "rtt") == 0)
var = 1;
else
return NULL;
return NULL;
}
rv = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_value));
@ -2145,7 +2159,7 @@ route_set_local_pref(void *rule, const struct prefix *prefix, void *object)
locpref = path->attr->local_pref;
path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
path->attr->local_pref = route_value_adjust(rv, locpref, path->peer);
path->attr->local_pref = route_value_adjust(rv, locpref, path);
return RMAP_OKAY;
}
@ -2172,7 +2186,7 @@ route_set_weight(void *rule, const struct prefix *prefix, void *object)
path = object;
/* Set weight value. */
path->attr->weight = route_value_adjust(rv, 0, path->peer);
path->attr->weight = route_value_adjust(rv, 0, path);
return RMAP_OKAY;
}
@ -2222,8 +2236,7 @@ route_set_metric(void *rule, const struct prefix *prefix, void *object)
if (path->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
med = path->attr->med;
path->attr->med = route_value_adjust(rv, med, path->peer);
path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
bgp_attr_set_med(path->attr, route_value_adjust(rv, med, path));
return RMAP_OKAY;
}

View File

@ -906,8 +906,8 @@ void subgroup_default_originate(struct update_subgroup *subgrp, bool withdraw)
assert(attr.aspath);
aspath = attr.aspath;
attr.med = 0;
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
bgp_attr_set_med(&attr, 0);
if ((afi == AFI_IP6) || peer_cap_enhe(peer, afi, safi)) {
/* IPv6 global nexthop must be included. */

View File

@ -667,10 +667,8 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
}
if (med) {
attr.med = *med;
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
}
if (med)
bgp_attr_set_med(&attr, *med);
/* override default weight assigned by bgp_attr_default_set() */
attr.weight = rfd->peer ? rfd->peer->weight[afi][safi] : 0;
@ -863,10 +861,8 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
red = bgp_redist_lookup(bgp, afi, type, 0);
if (red && red->redist_metric_flag) {
attr.med = red->redist_metric;
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
}
if (red && red->redist_metric_flag)
bgp_attr_set_med(&attr, red->redist_metric);
bn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);

View File

@ -96,15 +96,16 @@ static void encap_attr_export_ce(struct attr *new, struct attr *orig,
* neighbor NEIGHBOR attribute-unchanged med
*/
if (!CHECK_FLAG(new->flag, BGP_ATTR_MULTI_EXIT_DISC)) {
uint32_t med = 255;
if (CHECK_FLAG(new->flag, BGP_ATTR_LOCAL_PREF)) {
if (new->local_pref > 255)
new->med = 0;
med = 0;
else
new->med = 255 - new->local_pref;
} else {
new->med = 255; /* shouldn't happen */
med = 255 - new->local_pref;
}
new->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
bgp_attr_set_med(new, med);
}
/*
@ -642,15 +643,16 @@ encap_attr_export(struct attr *new, struct attr *orig,
* neighbor NEIGHBOR attribute-unchanged med
*/
if (!CHECK_FLAG(new->flag, BGP_ATTR_MULTI_EXIT_DISC)) {
uint32_t med = 255;
if (CHECK_FLAG(new->flag, BGP_ATTR_LOCAL_PREF)) {
if (new->local_pref > 255)
new->med = 0;
med = 0;
else
new->med = 255 - new->local_pref;
} else {
new->med = 255; /* shouldn't happen */
med = 255 - new->local_pref;
}
new->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
bgp_attr_set_med(new, med);
}
/*

View File

@ -305,13 +305,18 @@ Route Map Set Command
Set the route's weight.
.. clicmd:: set metric <[+|-](1-4294967295)|rtt|+rtt|-rtt>
.. clicmd:: set metric <[+|-](1-4294967295)|rtt|+rtt|-rtt|igp|aigp>
Set the route metric. When used with BGP, set the BGP attribute MED to a
specific value. Use `+`/`-` to add or subtract the specified value to/from
the existing/MED. Use `rtt` to set the MED to the round trip time or
`+rtt`/`-rtt` to add/subtract the round trip time to/from the MED.
If ``igp`` is specified, then the actual value from the IGP protocol is used.
If ``aigp`` is specified, then the actual value from the AIGP metric is used
(encoded as MED instead of AIGP attribute).
.. clicmd:: set min-metric <(0-4294967295)>
Set the minimum metric for the route.

View File

@ -922,13 +922,15 @@ DEFPY_YANG(
DEFPY_YANG(
set_metric, set_metric_cmd,
"set metric <(-4294967295-4294967295)$metric|rtt$rtt|+rtt$artt|-rtt$srtt>",
"set metric <(-4294967295-4294967295)$metric|rtt$rtt|+rtt$artt|-rtt$srtt|igp$igp|aigp$aigp>",
SET_STR
"Metric value for destination routing protocol\n"
"Metric value (use +/- for additions or subtractions)\n"
"Assign round trip time\n"
"Add round trip time\n"
"Subtract round trip time\n")
"Subtract round trip time\n"
"Metric value from IGP protocol\n"
"Metric value from AIGP (Accumulated IGP)\n")
{
const char *xpath = "./set-action[action='frr-route-map:set-metric']";
char xpath_value[XPATH_MAXLEN];
@ -939,6 +941,12 @@ DEFPY_YANG(
snprintf(xpath_value, sizeof(xpath_value),
"%s/rmap-set-action/use-round-trip-time", xpath);
snprintf(value, sizeof(value), "true");
} else if (igp) {
snprintf(xpath_value, sizeof(xpath_value), "%s/rmap-set-action/use-igp", xpath);
snprintf(value, sizeof(value), "true");
} else if (aigp) {
snprintf(xpath_value, sizeof(xpath_value), "%s/rmap-set-action/use-aigp", xpath);
snprintf(value, sizeof(value), "true");
} else if (artt) {
snprintf(xpath_value, sizeof(xpath_value),
"%s/rmap-set-action/add-round-trip-time", xpath);
@ -1148,23 +1156,19 @@ void route_map_action_show(struct vty *vty, const struct lyd_node *dnode,
if (yang_dnode_get(dnode,
"./rmap-set-action/use-round-trip-time")) {
vty_out(vty, " set metric rtt\n");
} else if (yang_dnode_get(
dnode,
"./rmap-set-action/add-round-trip-time")) {
} else if (yang_dnode_get(dnode, "./rmap-set-action/use-igp")) {
vty_out(vty, " set metric igp\n");
} else if (yang_dnode_get(dnode, "./rmap-set-action/use-aigp")) {
vty_out(vty, " set metric aigp\n");
} else if (yang_dnode_get(dnode, "./rmap-set-action/add-round-trip-time")) {
vty_out(vty, " set metric +rtt\n");
} else if (
yang_dnode_get(
dnode,
"./rmap-set-action/subtract-round-trip-time")) {
} else if (yang_dnode_get(dnode, "./rmap-set-action/subtract-round-trip-time")) {
vty_out(vty, " set metric -rtt\n");
} else if (yang_dnode_get(dnode,
"./rmap-set-action/add-metric")) {
} else if (yang_dnode_get(dnode, "./rmap-set-action/add-metric")) {
vty_out(vty, " set metric +%s\n",
yang_dnode_get_string(
dnode, "./rmap-set-action/add-metric"));
} else if (yang_dnode_get(
dnode,
"./rmap-set-action/subtract-metric")) {
} else if (yang_dnode_get(dnode, "./rmap-set-action/subtract-metric")) {
vty_out(vty, " set metric -%s\n",
yang_dnode_get_string(
dnode,

View File

@ -1213,6 +1213,34 @@ static int lib_route_map_entry_set_action_use_round_trip_time_destroy(
return lib_route_map_entry_set_action_value_destroy(args);
}
/*
* XPath: /frr-route-map:lib/route-map/entry/set-action/use-igp
*/
static int lib_route_map_entry_set_action_use_igp_modify(struct nb_cb_modify_args *args)
{
return set_action_modify(args->event, args->dnode, args->resource, "igp", args->errmsg,
args->errmsg_len);
}
static int lib_route_map_entry_set_action_use_igp_destroy(struct nb_cb_destroy_args *args)
{
return lib_route_map_entry_set_action_value_destroy(args);
}
/*
* XPath: /frr-route-map:lib/route-map/entry/set-action/use-aigp
*/
static int lib_route_map_entry_set_action_use_aigp_modify(struct nb_cb_modify_args *args)
{
return set_action_modify(args->event, args->dnode, args->resource, "aigp", args->errmsg,
args->errmsg_len);
}
static int lib_route_map_entry_set_action_use_aigp_destroy(struct nb_cb_destroy_args *args)
{
return lib_route_map_entry_set_action_value_destroy(args);
}
/*
* XPath: /frr-route-map:lib/route-map/entry/set-action/add-round-trip-time
*/
@ -1516,6 +1544,20 @@ const struct frr_yang_module_info frr_route_map_info = {
.destroy = lib_route_map_entry_set_action_use_round_trip_time_destroy,
}
},
{
.xpath = "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/use-igp",
.cbs = {
.modify = lib_route_map_entry_set_action_use_igp_modify,
.destroy = lib_route_map_entry_set_action_use_igp_destroy,
}
},
{
.xpath = "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/use-aigp",
.cbs = {
.modify = lib_route_map_entry_set_action_use_aigp_modify,
.destroy = lib_route_map_entry_set_action_use_aigp_destroy,
}
},
{
.xpath = "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/add-round-trip-time",
.cbs = {

View File

@ -9,4 +9,20 @@ router bgp 65001
neighbor 10.0.0.3 timers 1 3
neighbor 10.0.0.3 timers connect 1
neighbor 10.0.0.3 update-source lo
neighbor 192.168.18.8 remote-as external
neighbor 192.168.18.8 timers 1 3
neighbor 192.168.18.8 timers connect 1
address-family ipv4
neighbor 192.168.18.8 route-map r8 out
exit-address-family
!
ip prefix-list p71 seq 5 permit 10.0.0.71/32
ip prefix-list p72 seq 5 permit 10.0.0.72/32
!
route-map r8 permit 10
match ip address prefix-list p71
set metric igp
route-map r8 permit 20
match ip address prefix-list p72
set metric aigp
exit

View File

@ -8,3 +8,6 @@ interface r1-eth0
interface r1-eth1
ip address 192.168.13.1/24
!
interface r1-eth2
ip address 192.168.18.1/24
!

View File

@ -0,0 +1,4 @@
router bgp 65008
no bgp ebgp-requires-policy
neighbor 192.168.18.1 remote-as external
!

View File

@ -0,0 +1,4 @@
!
interface r8-eth0
ip address 192.168.18.8/24
!

View File

@ -15,6 +15,10 @@ r2 and r3 receives those routes with aigp-metric TLV increased by 20,
and 10 appropriately.
r1 receives routes with aigp-metric TLV 81, 91 and 82, 92 respectively.
r1 advertises MED from IGP protocol (set metric igp) to r8.
r1 advertises MED from AIGP (set metric aigp) to r8.
"""
import os
@ -34,7 +38,7 @@ pytestmark = [pytest.mark.bgpd]
def build_topo(tgen):
for routern in range(1, 8):
for routern in range(1, 9):
tgen.add_router("r{}".format(routern))
switch = tgen.add_switch("s1")
@ -65,6 +69,10 @@ def build_topo(tgen):
switch.add_link(tgen.gears["r6"])
switch.add_link(tgen.gears["r7"])
switch = tgen.add_switch("s8")
switch.add_link(tgen.gears["r1"])
switch.add_link(tgen.gears["r8"])
def setup_module(mod):
tgen = Topogen(build_topo, mod.__name__)
@ -102,6 +110,7 @@ def test_bgp_aigp():
r3 = tgen.gears["r3"]
r4 = tgen.gears["r4"]
r5 = tgen.gears["r5"]
r8 = tgen.gears["r8"]
def _bgp_converge():
output = json.loads(r1.vtysh_cmd("show bgp ipv4 unicast 10.0.0.71/32 json"))
@ -143,6 +152,18 @@ def test_bgp_aigp():
expected = {"paths": [{"aigpMetric": aigp, "valid": True}]}
return topotest.json_cmp(output, expected)
def _bgp_check_received_med():
output = json.loads(
r8.vtysh_cmd("show bgp ipv4 unicast 10.0.0.64/28 longer-prefixes json")
)
expected = {
"routes": {
"10.0.0.71/32": [{"valid": True, "metric": 10}],
"10.0.0.72/32": [{"valid": True, "metric": 92}],
}
}
return topotest.json_cmp(output, expected)
def _bgp_check_aigp_metric_bestpath():
output = json.loads(
r1.vtysh_cmd(
@ -252,6 +273,13 @@ def test_bgp_aigp():
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
assert result is None, "AIGP attribute is not considered in best-path selection"
# r8, check if MED is set derived from `set metric igp`, and `set metric aigp`
test_func = functools.partial(_bgp_check_received_med)
_, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
assert (
result is None
), "MED attribute values are not derived from `set metric [a]igp`"
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]

View File

@ -0,0 +1,13 @@
!
int r1-eth0
ip address 10.0.0.1/24
!
int r1-eth1
ip address 10.0.1.1/24
!
router bgp 65001
no bgp ebgp-requires-policy
no bgp network import-check
neighbor 10.0.0.2 remote-as external
neighbor 10.0.1.2 remote-as external
!

View File

@ -0,0 +1,36 @@
!
int r2-eth0
ip address 10.0.0.2/24
ip router isis n2
isis circuit-type level-2-only
isis fast-reroute lfa level-2
isis network point-to-point
isis hello-interval 1
isis hello-multiplier 10
!
int r2-eth1
ip address 10.0.2.1/24
ip router isis n2
isis circuit-type level-2-only
isis fast-reroute lfa level-2
isis network point-to-point
isis hello-interval 1
isis hello-multiplier 10
!
router bgp 65002
no bgp ebgp-requires-policy
neighbor 10.0.0.1 remote-as external
neighbor 10.0.2.2 remote-as internal
address-family ipv4 unicast
neighbor 10.0.0.1 route-map igp out
exit-address-family
!
router isis n2
is-type level-2-only
net 49.0001.0000.0000.0002.00
lsp-mtu 1440
exit
!
route-map igp permit 10
set metric igp
exit

View File

@ -0,0 +1,38 @@
!
int r3-eth0
ip address 10.0.1.2/24
ip router isis n3
isis circuit-type level-2-only
isis fast-reroute lfa level-2
isis network point-to-point
isis hello-interval 1
isis hello-multiplier 10
!
int r3-eth1
ip address 10.0.3.1/24
ip router isis n3
isis circuit-type level-2-only
isis fast-reroute lfa level-2
isis metric level-1 10
isis metric level-2 100
isis network point-to-point
isis hello-interval 1
isis hello-multiplier 10
!
router bgp 65002
no bgp ebgp-requires-policy
neighbor 10.0.1.1 remote-as external
neighbor 10.0.3.2 remote-as internal
address-family ipv4 unicast
neighbor 10.0.1.1 route-map igp out
exit-address-family
!
router isis n3
is-type level-2-only
net 49.0001.0000.0000.0003.00
lsp-mtu 1440
exit
!
route-map igp permit 10
set metric igp
exit

View File

@ -0,0 +1,41 @@
!
int r4-eth0
ip address 10.0.2.2/24
ip router isis n4
isis circuit-type level-2-only
isis fast-reroute lfa level-2
isis network point-to-point
isis hello-interval 1
isis hello-multiplier 10
!
int r4-eth1
ip address 10.0.3.2/24
ip router isis n4
isis circuit-type level-2-only
isis fast-reroute lfa level-2
isis metric level-1 10
isis metric level-2 100
isis network point-to-point
isis hello-interval 1
isis hello-multiplier 10
!
int r4-eth2
ip address 10.0.4.1/24
ip router isis n4
isis circuit-type level-2-only
isis fast-reroute lfa level-2
isis network point-to-point
isis hello-interval 1
isis hello-multiplier 10
!
router bgp 65002
no bgp ebgp-requires-policy
neighbor 10.0.2.1 remote-as internal
neighbor 10.0.3.1 remote-as internal
neighbor 10.0.4.2 remote-as external
!
router isis n4
is-type level-2-only
net 49.0001.0000.0000.0004.00
lsp-mtu 1440
exit

View File

@ -0,0 +1,14 @@
!
int r5-eth0
ip address 10.0.4.2/24
!
router bgp 65005
no bgp ebgp-requires-policy
no bgp network import-check
neighbor 10.0.4.1 remote-as external
neighbor 10.0.4.1 timers 1 3
neighbor 10.0.4.1 timers connect 1
address-family ipv4 unicast
network 10.5.5.5/32
exit-address-family
!

View File

@ -0,0 +1,146 @@
#!/usr/bin/env python
# SPDX-License-Identifier: ISC
# Copyright (c) 2024 by
# Donatas Abraitis <donatas@opensourcerouting.org>
#
import os
import sys
import json
import pytest
import functools
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
# pylint: disable=C0413
from lib import topotest
from lib.topogen import Topogen, get_topogen
pytestmark = [pytest.mark.bgpd]
def setup_module(mod):
topodef = {
"s1": ("r1", "r2"),
"s2": ("r1", "r3"),
"s3": ("r2", "r4"),
"s4": ("r3", "r4"),
"s5": ("r4", "r5"),
}
tgen = Topogen(topodef, mod.__name__)
tgen.start_topology()
router_list = tgen.routers()
for _, (rname, router) in enumerate(router_list.items(), 1):
router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname)))
tgen.start_router()
def teardown_module(mod):
tgen = get_topogen()
tgen.stop_topology()
def test_bgp_set_metric_igp():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
r1 = tgen.gears["r1"]
r2 = tgen.gears["r2"]
def _bgp_converge():
output = json.loads(r1.vtysh_cmd("show bgp ipv4 unicast json"))
expected = {
"routes": {
"10.5.5.5/32": [
{
"valid": True,
"bestpath": True,
"selectionReason": "MED",
"metric": 20,
"nexthops": [
{
"ip": "10.0.0.2",
"hostname": "r2",
}
],
},
{
"valid": True,
"bestpath": None,
"metric": 110,
"nexthops": [
{
"ip": "10.0.1.2",
"hostname": "r3",
}
],
},
]
}
}
return topotest.json_cmp(output, expected)
test_func = functools.partial(
_bgp_converge,
)
_, result = topotest.run_and_expect(test_func, None, count=120, wait=5)
assert result is None, "10.5.5.5/32 best path is not via r2 (MED == 20)"
r2.vtysh_cmd(
"""
configure terminal
interface r2-eth1
isis metric level-2 6000
"""
)
def _bgp_converge_after_isis_metric_changes():
output = json.loads(r1.vtysh_cmd("show bgp ipv4 unicast json"))
expected = {
"routes": {
"10.5.5.5/32": [
{
"valid": True,
"bestpath": None,
"metric": 6010,
"nexthops": [
{
"ip": "10.0.0.2",
"hostname": "r2",
}
],
},
{
"valid": True,
"bestpath": True,
"selectionReason": "MED",
"metric": 110,
"nexthops": [
{
"ip": "10.0.1.2",
"hostname": "r3",
}
],
},
]
}
}
return topotest.json_cmp(output, expected)
test_func = functools.partial(
_bgp_converge_after_isis_metric_changes,
)
_, result = topotest.run_and_expect(test_func, None, count=120, wait=5)
assert result is None, "10.5.5.5/32 best path is not via r3 (MED == 110)"
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))

View File

@ -355,6 +355,22 @@ module frr-route-map {
"Subtract round trip time to metric";
}
}
case use-igp {
leaf use-igp {
type boolean;
description
"Use metric from IGP procotol";
}
}
case use-aigp {
leaf use-aigp {
type boolean;
description
"Use metric from AIGP (Accumulated IGP)";
}
}
}
}