]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
CLI: v2 compatibility mode for attribute name display
authorMaria Matejka <mq@ucw.cz>
Wed, 18 Dec 2024 11:24:49 +0000 (12:24 +0100)
committerMaria Matejka <mq@ucw.cz>
Tue, 1 Apr 2025 13:03:28 +0000 (15:03 +0200)
14 files changed:
doc/bird.sgml
lib/route.h
nest/cli.c
nest/cli.h
nest/rt-attr.c
nest/rt-show.c
proto/babel/babel.c
proto/bgp/attrs.c
proto/ospf/ospf.c
proto/radv/radv.c
proto/rip/rip.c
sysdep/linux/netlink.c
sysdep/unix/config.Y
sysdep/unix/krt.c

index 9ce96ef33c8a9a633768a7611a22317fefb1a76a..4209c7028251eee7a3c23bac6958ae5d805e591b 100644 (file)
@@ -1362,16 +1362,25 @@ connects to it. If changed on the command line by the <tt/-s/ option,
 BIRD or the CLI tool connects there instead.
 
 <p>It's also possible to configure additional remote control sockets in the
-configuration file by <cf/cli "name";/ and you can open how many
+configuration file by <cf/cli "name" { <m/options/ };/ and you can open how many
 sockets you wish. There are no checks whether the user configured the same
 socket multiple times and BIRD may behave weirdly if this happens. On shutdown,
 the additional sockets get removed immediately and only the main socket stays
-until the very end.
+until the very end. If there are no options, the braces may be omitted.
 
-<p>The remote control socket can be also set as restricted by
-<cf/cli "name" { restrict; };/ instead of sending the <cf/restrict/ command
-after connecting. The user may still overload the daemon by requesting insanely
-complex filters so you shouldn't expose this socket to public anyway.
+<p>Options:
+
+<descrip>
+       <tag><label id="cli-conf-restrict">restrict</tag>
+       Set the socket to be restricted as if the user always sent the
+       <cf/restrict/ command after connecting. The user may still overload
+       the daemon by requesting insanely complex filters so you shouldn't
+       expose this socket to public even if restricted.
+
+       <tag><label id="cli-conf-v2-attributes">v2 attributes</tag>
+       Display the names and composition of route attributes the same way as BIRD 2 does.
+       This is a compatibility option for easier transition from BIRD 2 to BIRD 3.
+</descrip>
 
 <sect>Usage
 <label id="remote-control-usage">
index 6ad4a7c7d94b9d6ef6b579f866fa6c3c20cb04bd..21b46820867fbec7e8d39b8f13d093c58250dec7 100644 (file)
@@ -267,6 +267,7 @@ struct ea_storage {
 struct ea_class {
 #define EA_CLASS_INSIDE \
   const char *name;                    /* Name (both print and filter) */ \
+  const char *legacy_name;             /* Name for printing in v2 sockets */ \
   struct symbol *sym;                  /* Symbol to export to configs */ \
   uint id;                             /* Autoassigned attribute ID */ \
   uint uc;                             /* Reference count */ \
index b33ffd43789dbdf948de07d261b00db0042e6560..865e7f15fb5e659edfd688b5da18a0c261a2aaff 100644 (file)
@@ -320,6 +320,8 @@ cli_new(struct birdsock *sock, struct cli_config *cf)
   if (cf->restricted)
     c->restricted = 1;
 
+  c->v2attributes = cf->v2attributes;
+
   ev_schedule(c->event);
   return c;
 }
index 671be04d8cbc91bcf9ef3f769dc36b8a91ea98ff..5436219ee614c385e702cc996e53b0a8550ddd92 100644 (file)
@@ -43,6 +43,7 @@ typedef struct cli {
   struct config *main_config;          /* Main config currently in use */
   int last_reply;
   int restricted;                      /* CLI is restricted to read-only commands */
+  bool v2attributes;                   /* Route attributes are mimicking BIRD 2 */
   struct timeformat *tf;               /* Time format override */
   struct linpool *parser_pool;         /* Pool used during parsing */
   uint log_mask;                       /* Mask of allowed message levels */
@@ -63,6 +64,7 @@ struct cli_config {
   struct config *config;
   uint uid, gid, mode;
   _Bool restricted;
+  _Bool v2attributes;
 };
 #include "lib/tlists.h"
 
index f4e09083e4e7769519ec6897b40ac8044e4b88b7..3aaca0a463ecc2ee8ceeb2979da33e35e4be0b04 100644 (file)
@@ -196,6 +196,7 @@ ea_gen_aspa_providers_format(const eattr *a, byte *buf, uint size)
 
 struct ea_class ea_gen_aspa_providers = {
   .name = "aspa_providers",
+  .legacy_name = "aspa_providers",
   .type = T_CLIST,
   .format = ea_gen_aspa_providers_format,
 };
@@ -1311,7 +1312,12 @@ ea_show(struct cli *c, const eattr *e)
 
   if (e->undef || cls->hidden)
     return;
-  else if (cls->format)
+
+  const char *name = (c->v2attributes && !cls->conf) ? cls->legacy_name : cls->name;
+  if (!name)
+    return;
+
+  if (cls->format)
     cls->format(e, buf, end - buf);
   else
     switch (e->type)
@@ -1356,7 +1362,7 @@ ea_show(struct cli *c, const eattr *e)
          bsprintf(pos, "<type %02x>", e->type);
       }
 
-  cli_printf(c, -1012, "\t%s: %s", cls->name, buf);
+  cli_printf(c, -1012, "\t%s: %s", name, buf);
 }
 
 static void
index aa9209ca5f843a1033cad28da72aeda103688be5..3e1e9b54f3948a8db63c51fd5078038720f9c811 100644 (file)
@@ -21,6 +21,8 @@
 static void rt_show_cont(struct cli *c);
 static void rt_show_done(struct rt_show_data *d);
 
+extern const char * const rta_src_names[RTS_MAX];
+
 static void
 rt_show_table(struct rt_show_data *d)
 {
@@ -81,9 +83,19 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, int primary
 
   if (d->verbose)
   {
+    if (c->v2attributes)
+    {
+      ea_show_nexthop_list(c, nhad);
+
+      uint src = ea_get_int(a, &ea_gen_source, 0);
+      cli_printf(c, -1008, "\tType: %s univ", rta_src_names[src]);
+    }
+
     ea_show_list(c, a);
-    cli_printf(c, -1008, "\tInternal route handling values: %luL %uG %uS id %u",
-       e->src->private_id, e->src->global_id, e->stale_cycle, e->id);
+
+    if (!c->v2attributes)
+      cli_printf(c, -1008, "\tInternal route handling values: %luL %uG %uS id %u",
+         e->src->private_id, e->src->global_id, e->stale_cycle, e->id);
   }
   else if (dest == RTD_UNICAST)
     ea_show_nexthop_list(c, nhad);
index d8d4e555b3b2e74533f1b2f93a533ef2551c9e0e..e249938addcb55c559b4ed31c2aae20d01f1d00b 100644 (file)
@@ -2211,11 +2211,13 @@ babel_router_id_format(const eattr *a, byte *buf, uint len)
 
 static struct ea_class ea_babel_metric = {
   .name = "babel_metric",
+  .legacy_name = "Babel.metric",
   .type = T_INT,
 };
 
 static struct ea_class ea_babel_router_id = {
   .name = "babel_router_id",
+  .legacy_name = "Babel.router_id",
   .type = T_OPAQUE,
   .readonly = 1,
   .format = babel_router_id_format,
@@ -2223,6 +2225,7 @@ static struct ea_class ea_babel_router_id = {
 
 static struct ea_class ea_babel_seqno = {
   .name = "babel_seqno",
+  .legacy_name = "Babel.seqno",
   .type = T_INT,
   .readonly = 1,
   .hidden = 1,
index aa1263f06c666591c9fd2fd6e813c9e0ca52e041..69390dd53d9ea6322f7845f6c9d5662432ff5dce 100644 (file)
@@ -1058,6 +1058,7 @@ bgp_format_unknown(const eattr *a, byte *buf, uint size)
 static union bgp_attr_desc bgp_attr_table[BGP_ATTR_MAX] = {
   [BA_ORIGIN] = {
     .name = "bgp_origin",
+    .legacy_name = "BGP.origin",
     .type = T_ENUM_BGP_ORIGIN,
     .flags = BAF_TRANSITIVE,
     .export = bgp_export_origin,
@@ -1067,6 +1068,7 @@ static union bgp_attr_desc bgp_attr_table[BGP_ATTR_MAX] = {
   },
   [BA_AS_PATH] = {
     .name = "bgp_path",
+    .legacy_name = "BGP.as_path",
     .type = T_PATH,
     .flags = BAF_TRANSITIVE,
     .encode = bgp_encode_as_path,
@@ -1074,6 +1076,7 @@ static union bgp_attr_desc bgp_attr_table[BGP_ATTR_MAX] = {
   },
   [BA_NEXT_HOP] = {
     .name = "bgp_next_hop",
+    .legacy_name = "BGP.next_hop",
     .type = T_IP,
     .flags = BAF_TRANSITIVE,
     .encode = bgp_encode_next_hop,
@@ -1082,6 +1085,7 @@ static union bgp_attr_desc bgp_attr_table[BGP_ATTR_MAX] = {
   },
   [BA_MULTI_EXIT_DISC] = {
     .name = "bgp_med",
+    .legacy_name = "BGP.med",
     .type = T_INT,
     .flags = BAF_OPTIONAL,
     .encode = bgp_encode_u32,
@@ -1089,6 +1093,7 @@ static union bgp_attr_desc bgp_attr_table[BGP_ATTR_MAX] = {
   },
   [BA_LOCAL_PREF] = {
     .name = "bgp_local_pref",
+    .legacy_name = "BGP.local_pref",
     .type = T_INT,
     .flags = BAF_TRANSITIVE,
     .export = bgp_export_local_pref,
@@ -1097,6 +1102,7 @@ static union bgp_attr_desc bgp_attr_table[BGP_ATTR_MAX] = {
   },
   [BA_ATOMIC_AGGR] = {
     .name = "bgp_atomic_aggr",
+    .legacy_name = "BGP.atomic_aggr",
     .type = T_OPAQUE,
     .flags = BAF_TRANSITIVE,
     .encode = bgp_encode_raw,
@@ -1104,6 +1110,7 @@ static union bgp_attr_desc bgp_attr_table[BGP_ATTR_MAX] = {
   },
   [BA_AGGREGATOR] = {
     .name = "bgp_aggregator",
+    .legacy_name = "BGP.aggregator",
     .type = T_OPAQUE,
     .flags = BAF_OPTIONAL | BAF_TRANSITIVE,
     .encode = bgp_encode_aggregator,
@@ -1112,6 +1119,7 @@ static union bgp_attr_desc bgp_attr_table[BGP_ATTR_MAX] = {
   },
   [BA_COMMUNITY] = {
     .name = "bgp_community",
+    .legacy_name = "BGP.community",
     .type = T_CLIST,
     .flags = BAF_OPTIONAL | BAF_TRANSITIVE,
     .export = bgp_export_community,
@@ -1120,6 +1128,7 @@ static union bgp_attr_desc bgp_attr_table[BGP_ATTR_MAX] = {
   },
   [BA_ORIGINATOR_ID] = {
     .name = "bgp_originator_id",
+    .legacy_name = "BGP.originator_id",
     .type = T_QUAD,
     .flags = BAF_OPTIONAL,
     .export = bgp_export_originator_id,
@@ -1128,6 +1137,7 @@ static union bgp_attr_desc bgp_attr_table[BGP_ATTR_MAX] = {
   },
   [BA_CLUSTER_LIST] = {
     .name = "bgp_cluster_list",
+    .legacy_name = "BGP.cluster_list",
     .type = T_CLIST,
     .flags = BAF_OPTIONAL,
     .export = bgp_export_cluster_list,
@@ -1137,6 +1147,7 @@ static union bgp_attr_desc bgp_attr_table[BGP_ATTR_MAX] = {
   },
   [BA_MP_REACH_NLRI] = {
     .name = "bgp_mp_reach_nlri",
+    .legacy_name = "BGP.mp_reach_nlri",
     .type = T_OPAQUE,
     .hidden = 1,
     .flags = BAF_OPTIONAL,
@@ -1144,6 +1155,7 @@ static union bgp_attr_desc bgp_attr_table[BGP_ATTR_MAX] = {
   },
   [BA_MP_UNREACH_NLRI] = {
     .name = "bgp_mp_unreach_nlri",
+    .legacy_name = "BGP.mp_unreach_nlri",
     .type = T_OPAQUE,
     .hidden = 1,
     .flags = BAF_OPTIONAL,
@@ -1151,6 +1163,7 @@ static union bgp_attr_desc bgp_attr_table[BGP_ATTR_MAX] = {
   },
   [BA_EXT_COMMUNITY] = {
     .name = "bgp_ext_community",
+    .legacy_name = "BGP.ext_community",
     .type = T_ECLIST,
     .flags = BAF_OPTIONAL | BAF_TRANSITIVE,
     .export = bgp_export_ext_community,
@@ -1159,6 +1172,7 @@ static union bgp_attr_desc bgp_attr_table[BGP_ATTR_MAX] = {
   },
   [BA_AS4_PATH] = {
     .name = "bgp_as4_path",
+    .legacy_name = "BGP.as4_path",
     .type = T_PATH,
     .hidden = 1,
     .flags = BAF_OPTIONAL | BAF_TRANSITIVE,
@@ -1167,6 +1181,7 @@ static union bgp_attr_desc bgp_attr_table[BGP_ATTR_MAX] = {
   },
   [BA_AS4_AGGREGATOR] = {
     .name = "bgp_as4_aggregator",
+    .legacy_name = "BGP.as4_aggregator",
     .type = T_OPAQUE,
     .hidden = 1,
     .flags = BAF_OPTIONAL | BAF_TRANSITIVE,
@@ -1176,6 +1191,7 @@ static union bgp_attr_desc bgp_attr_table[BGP_ATTR_MAX] = {
   },
   [BA_AIGP] = {
     .name = "bgp_aigp",
+    .legacy_name = "BGP.aigp",
     .type = T_OPAQUE,
     .flags = BAF_OPTIONAL | BAF_DECODE_FLAGS,
     .export = bgp_export_aigp,
@@ -1185,6 +1201,7 @@ static union bgp_attr_desc bgp_attr_table[BGP_ATTR_MAX] = {
   },
   [BA_LARGE_COMMUNITY] = {
     .name = "bgp_large_community",
+    .legacy_name = "BGP.large_community",
     .type = T_LCLIST,
     .flags = BAF_OPTIONAL | BAF_TRANSITIVE,
     .export = bgp_export_large_community,
@@ -1193,6 +1210,7 @@ static union bgp_attr_desc bgp_attr_table[BGP_ATTR_MAX] = {
   },
   [BA_ONLY_TO_CUSTOMER] = {
     .name = "bgp_otc",
+    .legacy_name = "BGP.otc",
     .type = T_INT,
     .flags = BAF_OPTIONAL | BAF_TRANSITIVE,
     .encode = bgp_encode_u32,
@@ -1200,6 +1218,7 @@ static union bgp_attr_desc bgp_attr_table[BGP_ATTR_MAX] = {
   },
   [BA_MPLS_LABEL_STACK] = {
     .name = "bgp_mpls_label_stack",
+    .legacy_name = "BGP.mpls_label_stack",
     .type = T_CLIST,
     .readonly = 1,
     .export = bgp_export_mpls_label_stack,
index e10be62252f235cafcbd60b4817858badad6ab68..bde7d8051804ac6aa58592761c92b65aeea27fbe 100644 (file)
@@ -1527,22 +1527,26 @@ struct protocol proto_ospf = {
 
 struct ea_class ea_ospf_metric1 = {
   .name = "ospf_metric1",
+  .legacy_name = "OSPF.metric1",
   .type = T_INT,
 };
 
 struct ea_class ea_ospf_metric2 = {
   .name = "ospf_metric2",
+  .legacy_name = "OSPF.metric2",
   .type = T_INT,
 };
 
 struct ea_class ea_ospf_tag = {
   .name = "ospf_tag",
+  .legacy_name = "OSPF.tag",
   .type = T_INT,
   .format = ospf_tag_format,
 };
 
 struct ea_class ea_ospf_router_id = {
   .name = "ospf_router_id",
+  .legacy_name = "OSPF.router_id",
   .type = T_QUAD,
 };
 
index f574565338de90129413753eb0def8e912d93d11..8ae411dae1b683262d184ea38a6615615b559d33 100644 (file)
@@ -754,12 +754,14 @@ radv_preference_format(const eattr *a, byte *buf, uint buflen)
 
 static struct ea_class ea_radv_preference = {
   .name = "radv_preference",
+  .legacy_name = "RAdv.preference",
   .type = T_ENUM_RA_PREFERENCE,
   .format = radv_preference_format,
 };
 
 static struct ea_class ea_radv_lifetime = {
   .name = "radv_lifetime",
+  .legacy_name = "RAdv.lifetime",
   .type = T_INT,
 };
 
index 003c0355d42bc07e6acc62b3c13608b3ea4fa8ae..27c9408bc7b6519378184bd3aacd780038222c4b 100644 (file)
@@ -1269,11 +1269,13 @@ rip_tag_format(const eattr *a, byte *buf, uint buflen)
 
 static struct ea_class ea_rip_metric = {
   .name = "rip_metric",
+  .legacy_name = "RIP.metric",
   .type = T_INT,
 };
 
 static struct ea_class ea_rip_tag = {
   .name = "rip_tag",
+  .legacy_name = "RIP.tag",
   .type = T_INT,
   .format = rip_tag_format,
 };
index 75ed9ef7c7519e2539d6f99a1455b405394fdd1a..b6d800681f2fe9b8e63ac1622a23f77978bd625f 100644 (file)
@@ -57,50 +57,56 @@ static struct f_val krt_bitfield_empty(const struct ea_class *cls UNUSED)
 static struct ea_class
   ea_krt_prefsrc = {
     .name = "krt_prefsrc",
+    .legacy_name = "Kernel.prefsrc",
     .type = T_IP,
   },
   ea_krt_realm = {
     .name = "krt_realm",
+    .legacy_name = "Kernel.realm",
     .type = T_INT,
   },
   ea_krt_scope = {
     .name = "krt_scope",
+    .legacy_name = "Kernel.scope",
     .type = T_INT,
   };
 
 static struct ea_class ea_krt_metrics[] = {
   [RTAX_LOCK] = {
     .name = "krt_lock",
+    .legacy_name = "Kernel.lock",
     .type = T_INT,
     .format = krt_bitfield_format,
     .empty = krt_bitfield_empty,
   },
   [RTAX_FEATURES] = {
     .name = "krt_features",
+    .legacy_name = "Kernel.features",
     .type = T_INT,
     .format = krt_bitfield_format,
     .empty = krt_bitfield_empty,
   },
   [RTAX_CC_ALGO] = {
     .name = "krt_congctl",
+    .legacy_name = "Kernel.congctl",
     .type = T_STRING,
   },
-#define KRT_METRIC_INT(_rtax, _name)   [_rtax] = { .name = _name, .type = T_INT }
-  KRT_METRIC_INT(RTAX_MTU, "krt_mtu"),
-  KRT_METRIC_INT(RTAX_WINDOW, "krt_window"),
-  KRT_METRIC_INT(RTAX_RTT, "krt_rtt"),
-  KRT_METRIC_INT(RTAX_RTTVAR, "krt_rttvar"),
-  KRT_METRIC_INT(RTAX_SSTHRESH, "krt_ssthresh"),
-  KRT_METRIC_INT(RTAX_CWND, "krt_cwnd"),
-  KRT_METRIC_INT(RTAX_ADVMSS, "krt_advmss"),
-  KRT_METRIC_INT(RTAX_REORDERING, "krt_reordering"),
-  KRT_METRIC_INT(RTAX_HOPLIMIT, "krt_hoplimit"),
-  KRT_METRIC_INT(RTAX_INITCWND, "krt_initcwnd"),
-  KRT_METRIC_INT(RTAX_RTO_MIN, "krt_rto_min"),
-  KRT_METRIC_INT(RTAX_INITRWND, "krt_initrwnd"),
-  KRT_METRIC_INT(RTAX_QUICKACK, "krt_quickack"),
+#define KRT_METRIC_INT(_rtax, _name)   [_rtax] = { .name = "krt_" _name, .legacy_name = "Kernel." _name, .type = T_INT }
+  KRT_METRIC_INT(RTAX_MTU, "mtu"),
+  KRT_METRIC_INT(RTAX_WINDOW, "window"),
+  KRT_METRIC_INT(RTAX_RTT, "rtt"),
+  KRT_METRIC_INT(RTAX_RTTVAR, "rttvar"),
+  KRT_METRIC_INT(RTAX_SSTHRESH, "ssthresh"),
+  KRT_METRIC_INT(RTAX_CWND, "cwnd"),
+  KRT_METRIC_INT(RTAX_ADVMSS, "advmss"),
+  KRT_METRIC_INT(RTAX_REORDERING, "reordering"),
+  KRT_METRIC_INT(RTAX_HOPLIMIT, "hoplimit"),
+  KRT_METRIC_INT(RTAX_INITCWND, "initcwnd"),
+  KRT_METRIC_INT(RTAX_RTO_MIN, "rto_min"),
+  KRT_METRIC_INT(RTAX_INITRWND, "initrwnd"),
+  KRT_METRIC_INT(RTAX_QUICKACK, "quickack"),
 #ifdef RTAX_FASTOPEN_NO_COOKIE
-  KRT_METRIC_INT(RTAX_FASTOPEN_NO_COOKIE, "krt_fastopen_no_cookie"),
+  KRT_METRIC_INT(RTAX_FASTOPEN_NO_COOKIE, "fastopen_no_cookie"),
 #else
 #warning "Definition of RTAX_FASTOPEN_NO_COOKIE not found"
 #endif
index b520a6d9975bb03984e41774611c266196498eb5..4599b547192b7d9e67336f17b44b8f2cf8a164fb 100644 (file)
@@ -22,7 +22,7 @@ CF_DECLS
 CF_KEYWORDS(LOG, SYSLOG, ALL, DEBUG, TRACE, INFO, REMOTE, WARNING, ERROR, AUTH, FATAL, BUG, STDERR, SOFT, UDP, PORT, CLI)
 CF_KEYWORDS(NAME, CONFIRM, UNDO, CHECK, TIMEOUT, DEBUG, LATENCY, LIMIT, WATCHDOG, WARNING, STATUS)
 CF_KEYWORDS(PING, WAKEUP, SOCKETS, SCHEDULING, EVENTS, TIMERS, ALLOCATOR)
-CF_KEYWORDS(GRACEFUL, RESTART, FIXED)
+CF_KEYWORDS(GRACEFUL, RESTART, FIXED, V2)
 CF_KEYWORDS(THREAD, THREADS, GROUP, MIN, MAX, TIME, LATENCY, DEFAULT)
 
 %type <i> log_mask log_mask_list log_cat cfg_timeout debug_unix latency_debug_mask latency_debug_flag latency_debug_list
@@ -143,8 +143,9 @@ cli_opts_begin: {
 };
 
 cli_opts_block:
-  /* EMPTY */ |
-  cli_opts_block RESTRICT { this_cli_config->restricted = 1; }
+  /* EMPTY */
+  | cli_opts_block RESTRICT ';' { this_cli_config->restricted = 1; }
+  | cli_opts_block V2 ATTRIBUTES ';' { this_cli_config->v2attributes = 1; }
 ;
 
 conf: THREADS NUM {
index 6b4f0521f357d19cd6e33df786d2c2e27714f64a..a656bc15f3dc2e98efb5be1e8618d3cdcbaa4dfb 100644 (file)
@@ -1014,11 +1014,13 @@ krt_copy_config(struct proto_config *dest, struct proto_config *src)
 
 struct ea_class ea_krt_source = {
   .name = "krt_source",
+  .legacy_name = "Kernel.source",
   .type = T_INT,
 };
 
 struct ea_class ea_krt_metric = {
   .name = "krt_metric",
+  .legacy_name = "Kernel.metric",
   .type = T_INT,
 };