Filter: Add 'weight' route attribute
Add 'weight' route attribute that allows to get and set ECMP weight of nexthops. Similar to 'gw' attribute, it is limited to the first nexthop, but it is useful for handling BGP multipath, where an ECMP route is merged from multiple regular routes.
This commit is contained in:
parent
2465867712
commit
8cc5bb09e3
4 changed files with 27 additions and 1 deletions
|
@ -1674,6 +1674,15 @@ Common route attributes are:
|
||||||
creation/removal. Zero is returned for routes with undefined outgoing
|
creation/removal. Zero is returned for routes with undefined outgoing
|
||||||
interfaces. Read-only.
|
interfaces. Read-only.
|
||||||
|
|
||||||
|
<tag><label id="rta-weight"><m/int/ weight</tag>
|
||||||
|
Multipath weight of route next hops. Valid values are 1-256. Reading
|
||||||
|
returns the weight of the first next hop, setting it sets weights of all
|
||||||
|
next hops to the specified value. Therefore, this attribute is not much
|
||||||
|
useful for manipulating individual next hops of an ECMP route, but can
|
||||||
|
be used in BGP multipath setup to set weights of individual routes that
|
||||||
|
are merged to one ECMP route during export to the Kernel protocol
|
||||||
|
(with active <ref id="krt-merge-paths" name="marge paths"> option).
|
||||||
|
|
||||||
<tag><label id="rta-igp-metric"><m/int/ igp_metric</tag>
|
<tag><label id="rta-igp-metric"><m/int/ igp_metric</tag>
|
||||||
The optional attribute that can be used to specify a distance to the
|
The optional attribute that can be used to specify a distance to the
|
||||||
network for routes that do not have a native protocol metric attribute
|
network for routes that do not have a native protocol metric attribute
|
||||||
|
|
|
@ -278,7 +278,7 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
|
||||||
SET, STRING, BGPMASK, BGPPATH, CLIST, ECLIST, LCLIST,
|
SET, STRING, BGPMASK, BGPPATH, CLIST, ECLIST, LCLIST,
|
||||||
IF, THEN, ELSE, CASE,
|
IF, THEN, ELSE, CASE,
|
||||||
TRUE, FALSE, RT, RO, UNKNOWN, GENERIC,
|
TRUE, FALSE, RT, RO, UNKNOWN, GENERIC,
|
||||||
FROM, GW, NET, MASK, PROTO, SOURCE, SCOPE, DEST, IFNAME, IFINDEX,
|
FROM, GW, NET, MASK, PROTO, SOURCE, SCOPE, DEST, IFNAME, IFINDEX, WEIGHT,
|
||||||
PREFERENCE,
|
PREFERENCE,
|
||||||
ROA_CHECK, ASN, SRC, DST,
|
ROA_CHECK, ASN, SRC, DST,
|
||||||
IS_V4, IS_V6,
|
IS_V4, IS_V6,
|
||||||
|
@ -750,6 +750,7 @@ static_attr:
|
||||||
| DEST { $$ = f_new_static_attr(T_ENUM_RTD, SA_DEST, 0); }
|
| DEST { $$ = f_new_static_attr(T_ENUM_RTD, SA_DEST, 0); }
|
||||||
| IFNAME { $$ = f_new_static_attr(T_STRING, SA_IFNAME, 0); }
|
| IFNAME { $$ = f_new_static_attr(T_STRING, SA_IFNAME, 0); }
|
||||||
| IFINDEX { $$ = f_new_static_attr(T_INT, SA_IFINDEX, 1); }
|
| IFINDEX { $$ = f_new_static_attr(T_INT, SA_IFINDEX, 1); }
|
||||||
|
| WEIGHT { $$ = f_new_static_attr(T_INT, SA_WEIGHT, 0); }
|
||||||
;
|
;
|
||||||
|
|
||||||
term:
|
term:
|
||||||
|
|
|
@ -99,6 +99,7 @@ enum f_sa_code {
|
||||||
SA_DEST,
|
SA_DEST,
|
||||||
SA_IFNAME,
|
SA_IFNAME,
|
||||||
SA_IFINDEX,
|
SA_IFINDEX,
|
||||||
|
SA_WEIGHT,
|
||||||
} PACKED;
|
} PACKED;
|
||||||
|
|
||||||
/* Static attribute definition (members of struct rta) */
|
/* Static attribute definition (members of struct rta) */
|
||||||
|
|
|
@ -516,6 +516,7 @@
|
||||||
case SA_DEST: RESULT(sa.f_type, i, rta->dest); break;
|
case SA_DEST: RESULT(sa.f_type, i, rta->dest); break;
|
||||||
case SA_IFNAME: RESULT(sa.f_type, s, rta->nh.iface ? rta->nh.iface->name : ""); break;
|
case SA_IFNAME: RESULT(sa.f_type, s, rta->nh.iface ? rta->nh.iface->name : ""); break;
|
||||||
case SA_IFINDEX: RESULT(sa.f_type, i, rta->nh.iface ? rta->nh.iface->index : 0); break;
|
case SA_IFINDEX: RESULT(sa.f_type, i, rta->nh.iface ? rta->nh.iface->index : 0); break;
|
||||||
|
case SA_WEIGHT: RESULT(sa.f_type, i, rta->nh.weight + 1); break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
bug("Invalid static attribute access (%u/%u)", sa.f_type, sa.sa_code);
|
bug("Invalid static attribute access (%u/%u)", sa.f_type, sa.sa_code);
|
||||||
|
@ -586,6 +587,20 @@
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SA_WEIGHT:
|
||||||
|
{
|
||||||
|
int i = v1.val.i;
|
||||||
|
if (i < 1 || i > 256)
|
||||||
|
runtime( "Setting weight value out of bounds" );
|
||||||
|
if (rta->dest != RTD_UNICAST)
|
||||||
|
runtime( "Setting weight needs regular nexthop " );
|
||||||
|
|
||||||
|
/* Set weight on all next hops */
|
||||||
|
for (struct nexthop *nh = &rta->nh; nh; nh = nh->next)
|
||||||
|
nh->weight = i - 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
bug("Invalid static attribute access (%u/%u)", sa.f_type, sa.sa_code);
|
bug("Invalid static attribute access (%u/%u)", sa.f_type, sa.sa_code);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue