]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Filter: Add 'weight' route attribute
authorOndrej Zajicek (work) <santiago@crfreenet.org>
Wed, 2 Dec 2020 04:02:26 +0000 (05:02 +0100)
committerOndrej Zajicek (work) <santiago@crfreenet.org>
Wed, 2 Dec 2020 04:02:26 +0000 (05:02 +0100)
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.

doc/bird.sgml
filter/config.Y
filter/data.h
filter/f-inst.c

index 05216c4aab59892585264b77c69a5c8276af4757..5408cb2a8073ead71ca4b54e919ba8e44796f4e7 100644 (file)
@@ -1674,6 +1674,15 @@ Common route attributes are:
        creation/removal. Zero is returned for routes with undefined outgoing
        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>
        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
index 557a951f07517b8151d1bb2ef382bef02c03a481..5cd52e40e4411d0236f430d8fcd525726b5f1aa3 100644 (file)
@@ -278,7 +278,7 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
        SET, STRING, BGPMASK, BGPPATH, CLIST, ECLIST, LCLIST,
        IF, THEN, ELSE, CASE,
        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,
        ROA_CHECK, ASN, SRC, DST,
        IS_V4, IS_V6,
@@ -750,6 +750,7 @@ static_attr:
  | DEST    { $$ = f_new_static_attr(T_ENUM_RTD,   SA_DEST,     0); }
  | IFNAME  { $$ = f_new_static_attr(T_STRING,     SA_IFNAME,   0); }
  | IFINDEX { $$ = f_new_static_attr(T_INT,        SA_IFINDEX,  1); }
+ | WEIGHT  { $$ = f_new_static_attr(T_INT,        SA_WEIGHT,   0); }
  ;
 
 term:
index 4ebce73b6556280473c795ff5acc3c9932a6ceb1..a0ec3819b4a27e6d8a271feeea63eb2a5d8bc958 100644 (file)
@@ -99,6 +99,7 @@ enum f_sa_code {
   SA_DEST,
   SA_IFNAME,
   SA_IFINDEX,
+  SA_WEIGHT,
 } PACKED;
 
 /* Static attribute definition (members of struct rta) */
index df908e26e8fcdd5ebcbfbf0760ecf5250b296494..58717d558556c0e48415f32f64a9364bd4f3f7b0 100644 (file)
       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_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:
        bug("Invalid static attribute access (%u/%u)", sa.f_type, sa.sa_code);
        }
        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:
        bug("Invalid static attribute access (%u/%u)", sa.f_type, sa.sa_code);
       }