Commit 2e8838ecbb for frr

commit 2e8838ecbbe99e0ddf3147c691d689250ce6fafa
Author: Philippe Guibert <philippe.guibert@6wind.com>
Date:   Mon Oct 12 17:45:50 2026 +0200

    bgpd: add set aigp-metric +(0-4294967295)

    RFC 7311 section 3.4.3 requires a BGP speaker that changes the nexthop
    of a route to increase the AIGP metric by a non-zero amount, including
    when the previous nexthop is reached over a direct link on which no IGP
    is running, such as an eBGP link between two ASBRs. In that case, the
    IGP metric to the nexthop is 0, and the AIGP metric is not increased.

    "set aigp-metric" only sets an absolute value, which loses the AIGP
    metric accumulated so far. "set aigp-metric +10" is accepted by the
    CLI, but it sets the AIGP metric to 10.

    Fix this by adding the value to the AIGP metric of the route when it is
    prefixed with '+', capped at 0xffffffffffffffff. A route without the
    AIGP attribute is left unchanged. In the outbound route-map of a
    neighbor, this value is added to the IGP metric to the nexthop, since
    the outbound route-map is applied first.

    The documentation of "neighbor PEER aigp" also describes how to increase
    the AIGP metric when the previous nexthop is resolved by a static route,
    whose metric is 0 by default.

    Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>

diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index 35a10e3dc3..6a3381873a 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -3822,13 +3822,18 @@ route_set_aigp_metric(void *rule, const struct prefix *pfx, void *object)
 {
 	const char *aigp_metric = rule;
 	struct bgp_path_info *path = object;
-	uint32_t aigp;
+	uint64_t aigp;

 	/* Note: the metric is stored as MED for a locally redistributed. */
 	if (strmatch(aigp_metric, "igp-metric"))
 		aigp = path->nexthop ? path->nexthop->metric : path->attr->med;
-	else
-		aigp = atoi(aigp_metric);
+	else if (aigp_metric[0] == '+') {
+		if (!bgp_attr_exists(path->attr, BGP_ATTR_AIGP))
+			return RMAP_OKAY;
+		aigp = bgp_aigp_metric_add(bgp_attr_get_aigp_metric(path->attr),
+					   strtoul(aigp_metric + 1, NULL, 10));
+	} else
+		aigp = strtoul(aigp_metric, NULL, 10);

 	bgp_attr_set_aigp_metric(path->attr, aigp);

@@ -7909,7 +7914,7 @@ DEFPY_YANG (set_aigp_metric,
 	    SET_STR
 	    "BGP AIGP attribute (AIGP Metric TLV)\n"
 	    "AIGP Metric value from IGP protocol\n"
-	    "Manual AIGP Metric value\n")
+	    "Manual AIGP Metric value (use + for an addition)\n")
 {
 	const char *xpath =
 		"./set-action[action='frr-bgp-route-map:aigp-metric']";
@@ -7930,7 +7935,7 @@ DEFPY_YANG (no_set_aigp_metric,
 	    SET_STR
 	    "BGP AIGP attribute (AIGP Metric TLV)\n"
 	    "AIGP Metric value from IGP protocol\n"
-	    "Manual AIGP Metric value\n")
+	    "Manual AIGP Metric value (use + for an addition)\n")
 {
 	const char *xpath =
 		"./set-action[action='frr-bgp-route-map:aigp-metric']";
diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst
index 99d3b53763..613c703ed1 100644
--- a/doc/user/bgp.rst
+++ b/doc/user/bgp.rst
@@ -2884,10 +2884,17 @@ Capability Negotiation

    This command does not add the AIGP attribute to the advertised routes: only
    the routes that already carry it are sent with it. A route gets the AIGP
-   attribute from :clicmd:`set aigp-metric \<igp-metric|(0-4294967295)\>`, or
-   from a neighbor with AIGP enabled. When the nexthop is changed to the local
-   address, the AIGP metric is increased by the IGP metric to the previous
-   nexthop.
+   attribute from :clicmd:`set aigp-metric \<igp-metric|[+](0-4294967295)\>`,
+   or from a neighbor with AIGP enabled. When the nexthop is changed to the
+   local address, the AIGP metric is increased by the IGP metric to the
+   previous nexthop.
+
+   When the previous nexthop is resolved by a static route, the AIGP metric is
+   increased by the metric of the static route, which is 0 by default, and not
+   by the IGP metric to the gateway of the static route. This metric can be set
+   with the ``metric`` option of the static route (see
+   :ref:`static-route-distance-metric`), or the AIGP metric can be increased
+   with ``set aigp-metric +N`` in the outbound route-map.

    Disabled by default. iBGP and confederation neighbors have this option
    enabled implicitly.
diff --git a/doc/user/routemap.rst b/doc/user/routemap.rst
index 1b3aaab4a4..3086cceaf4 100644
--- a/doc/user/routemap.rst
+++ b/doc/user/routemap.rst
@@ -342,13 +342,20 @@ Route Map Set Command

    Set the maximum metric for the route.

-.. clicmd:: set aigp-metric <igp-metric|(0-4294967295)>
+.. clicmd:: set aigp-metric <igp-metric|[+](0-4294967295)>

    Set the BGP attribute AIGP to a specific value. If ``igp-metric`` is specified,
    then the value is taken from the IGP protocol, otherwise an arbitrary value.
    A value of 0 is valid: the route carries the AIGP attribute with a metric
    of 0, which is compared in the best path selection.

+   If the value is prefixed with ``+``, it is added to the AIGP metric of the
+   route, and the result is capped at 0xffffffffffffffff. A route without the
+   AIGP attribute is left unchanged. RFC 7311 requires the AIGP metric to be
+   increased by a non-zero amount when the nexthop is changed, even on a direct
+   link where no IGP is running: for instance, ``set aigp-metric +10`` in the
+   outbound route-map of an eBGP neighbor provides this increase.
+
 .. clicmd:: set as-path prepend AS_PATH

    Set the BGP AS path to prepend.