mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-07 23:58:44 +00:00
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:
commit
de02471a8d
@ -1177,8 +1177,7 @@ struct attr *bgp_attr_aggregate_intern(
|
|||||||
SET_FLAG(attr.flag, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN));
|
SET_FLAG(attr.flag, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN));
|
||||||
|
|
||||||
/* MED */
|
/* MED */
|
||||||
attr.med = 0;
|
bgp_attr_set_med(&attr, 0);
|
||||||
SET_FLAG(attr.flag, ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
|
|
||||||
|
|
||||||
/* AS path attribute. */
|
/* AS path attribute. */
|
||||||
if (aspath)
|
if (aspath)
|
||||||
@ -1933,9 +1932,7 @@ static enum bgp_attr_parse_ret bgp_attr_med(struct bgp_attr_parser_args *args)
|
|||||||
args->total);
|
args->total);
|
||||||
}
|
}
|
||||||
|
|
||||||
attr->med = stream_getl(peer->curr);
|
bgp_attr_set_med(attr, stream_getl(peer->curr));
|
||||||
|
|
||||||
SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
|
|
||||||
|
|
||||||
return BGP_ATTR_PARSE_PROCEED;
|
return BGP_ATTR_PARSE_PROCEED;
|
||||||
}
|
}
|
||||||
|
@ -608,6 +608,12 @@ static inline uint64_t bgp_aigp_metric_total(struct bgp_path_info *bpi)
|
|||||||
return aigp;
|
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)
|
static inline struct cluster_list *bgp_attr_get_cluster(const struct attr *attr)
|
||||||
{
|
{
|
||||||
return attr->cluster1;
|
return attr->cluster1;
|
||||||
|
@ -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
|
/* If there is a change of interest to peers, reannounce the
|
||||||
* route. */
|
* route. */
|
||||||
if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
|
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) ||
|
||||||
|| CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
|
bgp_zebra_has_route_changed(old_select)) {
|
||||||
group_announce_route(bgp, afi, safi, dest, new_select);
|
group_announce_route(bgp, afi, safi, dest, new_select);
|
||||||
|
|
||||||
/* unicast routes must also be annouced to
|
/* unicast routes must also be annouced to
|
||||||
* labeled-unicast update-groups */
|
* labeled-unicast update-groups */
|
||||||
if (safi == SAFI_UNICAST)
|
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);
|
bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
|
||||||
|
|
||||||
attr.nexthop = bgp_static->igpnexthop;
|
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)
|
if (afi == AFI_IP)
|
||||||
attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
|
attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
|
||||||
@ -9014,9 +9013,8 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
|
|||||||
else
|
else
|
||||||
UNSET_FLAG(attr.nh_flags, BGP_ATTR_NH_IF_OPERSTATE);
|
UNSET_FLAG(attr.nh_flags, BGP_ATTR_NH_IF_OPERSTATE);
|
||||||
|
|
||||||
attr.med = metric;
|
bgp_attr_set_med(&attr, metric);
|
||||||
attr.distance = distance;
|
attr.distance = distance;
|
||||||
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
|
|
||||||
attr.tag = tag;
|
attr.tag = tag;
|
||||||
|
|
||||||
if (metric)
|
if (metric)
|
||||||
|
@ -125,6 +125,10 @@ o Local extensions
|
|||||||
#define RMAP_VALUE_ADD 1
|
#define RMAP_VALUE_ADD 1
|
||||||
#define RMAP_VALUE_SUB 2
|
#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 {
|
struct rmap_value {
|
||||||
uint8_t action;
|
uint8_t action;
|
||||||
uint8_t variable;
|
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,
|
static uint32_t route_value_adjust(struct rmap_value *rv, uint32_t current,
|
||||||
struct peer *peer)
|
struct bgp_path_info *bpi)
|
||||||
{
|
{
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
|
struct peer *peer = bpi->peer;
|
||||||
|
|
||||||
switch (rv->variable) {
|
switch (rv->variable) {
|
||||||
case 1:
|
case RMAP_VALUE_TYPE_RTT:
|
||||||
value = peer->rtt;
|
value = peer->rtt;
|
||||||
break;
|
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:
|
default:
|
||||||
value = rv->value;
|
value = rv->value;
|
||||||
break;
|
break;
|
||||||
@ -187,11 +198,14 @@ static void *route_value_compile(const char *arg)
|
|||||||
larg = strtoul(arg, &endptr, 10);
|
larg = strtoul(arg, &endptr, 10);
|
||||||
if (*arg == 0 || *endptr != 0 || errno || larg > UINT32_MAX)
|
if (*arg == 0 || *endptr != 0 || errno || larg > UINT32_MAX)
|
||||||
return NULL;
|
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 {
|
} else {
|
||||||
if (strcmp(arg, "rtt") == 0)
|
return NULL;
|
||||||
var = 1;
|
|
||||||
else
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_value));
|
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;
|
locpref = path->attr->local_pref;
|
||||||
|
|
||||||
path->attr->flag |= ATTR_FLAG_BIT(BGP_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;
|
return RMAP_OKAY;
|
||||||
}
|
}
|
||||||
@ -2172,7 +2186,7 @@ route_set_weight(void *rule, const struct prefix *prefix, void *object)
|
|||||||
path = object;
|
path = object;
|
||||||
|
|
||||||
/* Set weight value. */
|
/* 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;
|
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))
|
if (path->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
|
||||||
med = path->attr->med;
|
med = path->attr->med;
|
||||||
|
|
||||||
path->attr->med = route_value_adjust(rv, med, path->peer);
|
bgp_attr_set_med(path->attr, route_value_adjust(rv, med, path));
|
||||||
path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
|
|
||||||
|
|
||||||
return RMAP_OKAY;
|
return RMAP_OKAY;
|
||||||
}
|
}
|
||||||
|
@ -906,8 +906,8 @@ void subgroup_default_originate(struct update_subgroup *subgrp, bool withdraw)
|
|||||||
assert(attr.aspath);
|
assert(attr.aspath);
|
||||||
|
|
||||||
aspath = 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)) {
|
if ((afi == AFI_IP6) || peer_cap_enhe(peer, afi, safi)) {
|
||||||
/* IPv6 global nexthop must be included. */
|
/* IPv6 global nexthop must be included. */
|
||||||
|
@ -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);
|
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (med) {
|
if (med)
|
||||||
attr.med = *med;
|
bgp_attr_set_med(&attr, *med);
|
||||||
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* override default weight assigned by bgp_attr_default_set() */
|
/* override default weight assigned by bgp_attr_default_set() */
|
||||||
attr.weight = rfd->peer ? rfd->peer->weight[afi][safi] : 0;
|
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);
|
red = bgp_redist_lookup(bgp, afi, type, 0);
|
||||||
|
|
||||||
if (red && red->redist_metric_flag) {
|
if (red && red->redist_metric_flag)
|
||||||
attr.med = red->redist_metric;
|
bgp_attr_set_med(&attr, red->redist_metric);
|
||||||
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
|
|
||||||
}
|
|
||||||
|
|
||||||
bn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
|
bn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
|
||||||
|
|
||||||
|
@ -96,15 +96,16 @@ static void encap_attr_export_ce(struct attr *new, struct attr *orig,
|
|||||||
* neighbor NEIGHBOR attribute-unchanged med
|
* neighbor NEIGHBOR attribute-unchanged med
|
||||||
*/
|
*/
|
||||||
if (!CHECK_FLAG(new->flag, BGP_ATTR_MULTI_EXIT_DISC)) {
|
if (!CHECK_FLAG(new->flag, BGP_ATTR_MULTI_EXIT_DISC)) {
|
||||||
|
uint32_t med = 255;
|
||||||
|
|
||||||
if (CHECK_FLAG(new->flag, BGP_ATTR_LOCAL_PREF)) {
|
if (CHECK_FLAG(new->flag, BGP_ATTR_LOCAL_PREF)) {
|
||||||
if (new->local_pref > 255)
|
if (new->local_pref > 255)
|
||||||
new->med = 0;
|
med = 0;
|
||||||
else
|
else
|
||||||
new->med = 255 - new->local_pref;
|
med = 255 - new->local_pref;
|
||||||
} else {
|
|
||||||
new->med = 255; /* shouldn't happen */
|
|
||||||
}
|
}
|
||||||
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
|
* neighbor NEIGHBOR attribute-unchanged med
|
||||||
*/
|
*/
|
||||||
if (!CHECK_FLAG(new->flag, BGP_ATTR_MULTI_EXIT_DISC)) {
|
if (!CHECK_FLAG(new->flag, BGP_ATTR_MULTI_EXIT_DISC)) {
|
||||||
|
uint32_t med = 255;
|
||||||
|
|
||||||
if (CHECK_FLAG(new->flag, BGP_ATTR_LOCAL_PREF)) {
|
if (CHECK_FLAG(new->flag, BGP_ATTR_LOCAL_PREF)) {
|
||||||
if (new->local_pref > 255)
|
if (new->local_pref > 255)
|
||||||
new->med = 0;
|
med = 0;
|
||||||
else
|
else
|
||||||
new->med = 255 - new->local_pref;
|
med = 255 - new->local_pref;
|
||||||
} else {
|
|
||||||
new->med = 255; /* shouldn't happen */
|
|
||||||
}
|
}
|
||||||
new->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
|
|
||||||
|
bgp_attr_set_med(new, med);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -305,13 +305,18 @@ Route Map Set Command
|
|||||||
|
|
||||||
Set the route's weight.
|
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
|
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
|
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
|
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.
|
`+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)>
|
.. clicmd:: set min-metric <(0-4294967295)>
|
||||||
|
|
||||||
Set the minimum metric for the route.
|
Set the minimum metric for the route.
|
||||||
|
@ -922,13 +922,15 @@ DEFPY_YANG(
|
|||||||
|
|
||||||
DEFPY_YANG(
|
DEFPY_YANG(
|
||||||
set_metric, set_metric_cmd,
|
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
|
SET_STR
|
||||||
"Metric value for destination routing protocol\n"
|
"Metric value for destination routing protocol\n"
|
||||||
"Metric value (use +/- for additions or subtractions)\n"
|
"Metric value (use +/- for additions or subtractions)\n"
|
||||||
"Assign round trip time\n"
|
"Assign round trip time\n"
|
||||||
"Add 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']";
|
const char *xpath = "./set-action[action='frr-route-map:set-metric']";
|
||||||
char xpath_value[XPATH_MAXLEN];
|
char xpath_value[XPATH_MAXLEN];
|
||||||
@ -939,6 +941,12 @@ DEFPY_YANG(
|
|||||||
snprintf(xpath_value, sizeof(xpath_value),
|
snprintf(xpath_value, sizeof(xpath_value),
|
||||||
"%s/rmap-set-action/use-round-trip-time", xpath);
|
"%s/rmap-set-action/use-round-trip-time", xpath);
|
||||||
snprintf(value, sizeof(value), "true");
|
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) {
|
} else if (artt) {
|
||||||
snprintf(xpath_value, sizeof(xpath_value),
|
snprintf(xpath_value, sizeof(xpath_value),
|
||||||
"%s/rmap-set-action/add-round-trip-time", xpath);
|
"%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,
|
if (yang_dnode_get(dnode,
|
||||||
"./rmap-set-action/use-round-trip-time")) {
|
"./rmap-set-action/use-round-trip-time")) {
|
||||||
vty_out(vty, " set metric rtt\n");
|
vty_out(vty, " set metric rtt\n");
|
||||||
} else if (yang_dnode_get(
|
} else if (yang_dnode_get(dnode, "./rmap-set-action/use-igp")) {
|
||||||
dnode,
|
vty_out(vty, " set metric igp\n");
|
||||||
"./rmap-set-action/add-round-trip-time")) {
|
} 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");
|
vty_out(vty, " set metric +rtt\n");
|
||||||
} else if (
|
} else if (yang_dnode_get(dnode, "./rmap-set-action/subtract-round-trip-time")) {
|
||||||
yang_dnode_get(
|
|
||||||
dnode,
|
|
||||||
"./rmap-set-action/subtract-round-trip-time")) {
|
|
||||||
vty_out(vty, " set metric -rtt\n");
|
vty_out(vty, " set metric -rtt\n");
|
||||||
} else if (yang_dnode_get(dnode,
|
} else if (yang_dnode_get(dnode, "./rmap-set-action/add-metric")) {
|
||||||
"./rmap-set-action/add-metric")) {
|
|
||||||
vty_out(vty, " set metric +%s\n",
|
vty_out(vty, " set metric +%s\n",
|
||||||
yang_dnode_get_string(
|
yang_dnode_get_string(
|
||||||
dnode, "./rmap-set-action/add-metric"));
|
dnode, "./rmap-set-action/add-metric"));
|
||||||
} else if (yang_dnode_get(
|
} else if (yang_dnode_get(dnode, "./rmap-set-action/subtract-metric")) {
|
||||||
dnode,
|
|
||||||
"./rmap-set-action/subtract-metric")) {
|
|
||||||
vty_out(vty, " set metric -%s\n",
|
vty_out(vty, " set metric -%s\n",
|
||||||
yang_dnode_get_string(
|
yang_dnode_get_string(
|
||||||
dnode,
|
dnode,
|
||||||
|
@ -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);
|
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
|
* 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,
|
.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",
|
.xpath = "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/add-round-trip-time",
|
||||||
.cbs = {
|
.cbs = {
|
||||||
|
@ -9,4 +9,20 @@ router bgp 65001
|
|||||||
neighbor 10.0.0.3 timers 1 3
|
neighbor 10.0.0.3 timers 1 3
|
||||||
neighbor 10.0.0.3 timers connect 1
|
neighbor 10.0.0.3 timers connect 1
|
||||||
neighbor 10.0.0.3 update-source lo
|
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
|
||||||
|
@ -8,3 +8,6 @@ interface r1-eth0
|
|||||||
interface r1-eth1
|
interface r1-eth1
|
||||||
ip address 192.168.13.1/24
|
ip address 192.168.13.1/24
|
||||||
!
|
!
|
||||||
|
interface r1-eth2
|
||||||
|
ip address 192.168.18.1/24
|
||||||
|
!
|
||||||
|
4
tests/topotests/bgp_aigp/r8/bgpd.conf
Normal file
4
tests/topotests/bgp_aigp/r8/bgpd.conf
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
router bgp 65008
|
||||||
|
no bgp ebgp-requires-policy
|
||||||
|
neighbor 192.168.18.1 remote-as external
|
||||||
|
!
|
4
tests/topotests/bgp_aigp/r8/zebra.conf
Normal file
4
tests/topotests/bgp_aigp/r8/zebra.conf
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
!
|
||||||
|
interface r8-eth0
|
||||||
|
ip address 192.168.18.8/24
|
||||||
|
!
|
@ -15,6 +15,10 @@ r2 and r3 receives those routes with aigp-metric TLV increased by 20,
|
|||||||
and 10 appropriately.
|
and 10 appropriately.
|
||||||
|
|
||||||
r1 receives routes with aigp-metric TLV 81, 91 and 82, 92 respectively.
|
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
|
import os
|
||||||
@ -34,7 +38,7 @@ pytestmark = [pytest.mark.bgpd]
|
|||||||
|
|
||||||
|
|
||||||
def build_topo(tgen):
|
def build_topo(tgen):
|
||||||
for routern in range(1, 8):
|
for routern in range(1, 9):
|
||||||
tgen.add_router("r{}".format(routern))
|
tgen.add_router("r{}".format(routern))
|
||||||
|
|
||||||
switch = tgen.add_switch("s1")
|
switch = tgen.add_switch("s1")
|
||||||
@ -65,6 +69,10 @@ def build_topo(tgen):
|
|||||||
switch.add_link(tgen.gears["r6"])
|
switch.add_link(tgen.gears["r6"])
|
||||||
switch.add_link(tgen.gears["r7"])
|
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):
|
def setup_module(mod):
|
||||||
tgen = Topogen(build_topo, mod.__name__)
|
tgen = Topogen(build_topo, mod.__name__)
|
||||||
@ -102,6 +110,7 @@ def test_bgp_aigp():
|
|||||||
r3 = tgen.gears["r3"]
|
r3 = tgen.gears["r3"]
|
||||||
r4 = tgen.gears["r4"]
|
r4 = tgen.gears["r4"]
|
||||||
r5 = tgen.gears["r5"]
|
r5 = tgen.gears["r5"]
|
||||||
|
r8 = tgen.gears["r8"]
|
||||||
|
|
||||||
def _bgp_converge():
|
def _bgp_converge():
|
||||||
output = json.loads(r1.vtysh_cmd("show bgp ipv4 unicast 10.0.0.71/32 json"))
|
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}]}
|
expected = {"paths": [{"aigpMetric": aigp, "valid": True}]}
|
||||||
return topotest.json_cmp(output, expected)
|
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():
|
def _bgp_check_aigp_metric_bestpath():
|
||||||
output = json.loads(
|
output = json.loads(
|
||||||
r1.vtysh_cmd(
|
r1.vtysh_cmd(
|
||||||
@ -252,6 +273,13 @@ def test_bgp_aigp():
|
|||||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
|
_, 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"
|
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__":
|
if __name__ == "__main__":
|
||||||
args = ["-s"] + sys.argv[1:]
|
args = ["-s"] + sys.argv[1:]
|
||||||
|
0
tests/topotests/bgp_set_metric_igp/__init__.py
Normal file
0
tests/topotests/bgp_set_metric_igp/__init__.py
Normal file
13
tests/topotests/bgp_set_metric_igp/r1/frr.conf
Normal file
13
tests/topotests/bgp_set_metric_igp/r1/frr.conf
Normal 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
|
||||||
|
!
|
36
tests/topotests/bgp_set_metric_igp/r2/frr.conf
Normal file
36
tests/topotests/bgp_set_metric_igp/r2/frr.conf
Normal 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
|
38
tests/topotests/bgp_set_metric_igp/r3/frr.conf
Normal file
38
tests/topotests/bgp_set_metric_igp/r3/frr.conf
Normal 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
|
41
tests/topotests/bgp_set_metric_igp/r4/frr.conf
Normal file
41
tests/topotests/bgp_set_metric_igp/r4/frr.conf
Normal 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
|
14
tests/topotests/bgp_set_metric_igp/r5/frr.conf
Normal file
14
tests/topotests/bgp_set_metric_igp/r5/frr.conf
Normal 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
|
||||||
|
!
|
146
tests/topotests/bgp_set_metric_igp/test_bgp_set_metric_igp.py
Normal file
146
tests/topotests/bgp_set_metric_igp/test_bgp_set_metric_igp.py
Normal 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))
|
@ -355,6 +355,22 @@ module frr-route-map {
|
|||||||
"Subtract round trip time to metric";
|
"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)";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user