Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bgpd: Derive and set MED from IGP or AIGP #17038

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions bgpd/bgp_attr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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;
}
Expand Down
6 changes: 6 additions & 0 deletions bgpd/bgp_attr.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
14 changes: 6 additions & 8 deletions bgpd/bgp_route.c
Original file line number Diff line number Diff line change
Expand Up @@ -3727,11 +3727,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)
Expand Down Expand Up @@ -6747,8 +6746,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;
Expand Down Expand Up @@ -9015,9 +9014,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)
Expand Down
33 changes: 23 additions & 10 deletions bgpd/bgp_routemap.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
}
Expand Down
4 changes: 2 additions & 2 deletions bgpd/bgp_updgrp_adv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down
12 changes: 4 additions & 8 deletions bgpd/rfapi/rfapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);

Expand Down
22 changes: 12 additions & 10 deletions bgpd/rfapi/vnc_export_bgp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

/*
Expand Down Expand Up @@ -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);
}

/*
Expand Down
7 changes: 6 additions & 1 deletion doc/user/routemap.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
32 changes: 18 additions & 14 deletions lib/routemap_cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand All @@ -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);
Expand Down Expand Up @@ -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,
Expand Down
42 changes: 42 additions & 0 deletions lib/routemap_northbound.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand Down Expand Up @@ -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 = {
Expand Down
16 changes: 16 additions & 0 deletions tests/topotests/bgp_aigp/r1/bgpd.conf
Original file line number Diff line number Diff line change
Expand Up @@ -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
Loading
Loading