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">
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 */ \
if (cf->restricted)
c->restricted = 1;
+ c->v2attributes = cf->v2attributes;
+
ev_schedule(c->event);
return c;
}
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 */
struct config *config;
uint uid, gid, mode;
_Bool restricted;
+ _Bool v2attributes;
};
#include "lib/tlists.h"
struct ea_class ea_gen_aspa_providers = {
.name = "aspa_providers",
+ .legacy_name = "aspa_providers",
.type = T_CLIST,
.format = ea_gen_aspa_providers_format,
};
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)
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
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)
{
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);
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,
static struct ea_class ea_babel_seqno = {
.name = "babel_seqno",
+ .legacy_name = "Babel.seqno",
.type = T_INT,
.readonly = 1,
.hidden = 1,
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,
},
[BA_AS_PATH] = {
.name = "bgp_path",
+ .legacy_name = "BGP.as_path",
.type = T_PATH,
.flags = BAF_TRANSITIVE,
.encode = bgp_encode_as_path,
},
[BA_NEXT_HOP] = {
.name = "bgp_next_hop",
+ .legacy_name = "BGP.next_hop",
.type = T_IP,
.flags = BAF_TRANSITIVE,
.encode = bgp_encode_next_hop,
},
[BA_MULTI_EXIT_DISC] = {
.name = "bgp_med",
+ .legacy_name = "BGP.med",
.type = T_INT,
.flags = BAF_OPTIONAL,
.encode = bgp_encode_u32,
},
[BA_LOCAL_PREF] = {
.name = "bgp_local_pref",
+ .legacy_name = "BGP.local_pref",
.type = T_INT,
.flags = BAF_TRANSITIVE,
.export = bgp_export_local_pref,
},
[BA_ATOMIC_AGGR] = {
.name = "bgp_atomic_aggr",
+ .legacy_name = "BGP.atomic_aggr",
.type = T_OPAQUE,
.flags = BAF_TRANSITIVE,
.encode = bgp_encode_raw,
},
[BA_AGGREGATOR] = {
.name = "bgp_aggregator",
+ .legacy_name = "BGP.aggregator",
.type = T_OPAQUE,
.flags = BAF_OPTIONAL | BAF_TRANSITIVE,
.encode = bgp_encode_aggregator,
},
[BA_COMMUNITY] = {
.name = "bgp_community",
+ .legacy_name = "BGP.community",
.type = T_CLIST,
.flags = BAF_OPTIONAL | BAF_TRANSITIVE,
.export = bgp_export_community,
},
[BA_ORIGINATOR_ID] = {
.name = "bgp_originator_id",
+ .legacy_name = "BGP.originator_id",
.type = T_QUAD,
.flags = BAF_OPTIONAL,
.export = bgp_export_originator_id,
},
[BA_CLUSTER_LIST] = {
.name = "bgp_cluster_list",
+ .legacy_name = "BGP.cluster_list",
.type = T_CLIST,
.flags = BAF_OPTIONAL,
.export = bgp_export_cluster_list,
},
[BA_MP_REACH_NLRI] = {
.name = "bgp_mp_reach_nlri",
+ .legacy_name = "BGP.mp_reach_nlri",
.type = T_OPAQUE,
.hidden = 1,
.flags = BAF_OPTIONAL,
},
[BA_MP_UNREACH_NLRI] = {
.name = "bgp_mp_unreach_nlri",
+ .legacy_name = "BGP.mp_unreach_nlri",
.type = T_OPAQUE,
.hidden = 1,
.flags = BAF_OPTIONAL,
},
[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,
},
[BA_AS4_PATH] = {
.name = "bgp_as4_path",
+ .legacy_name = "BGP.as4_path",
.type = T_PATH,
.hidden = 1,
.flags = BAF_OPTIONAL | BAF_TRANSITIVE,
},
[BA_AS4_AGGREGATOR] = {
.name = "bgp_as4_aggregator",
+ .legacy_name = "BGP.as4_aggregator",
.type = T_OPAQUE,
.hidden = 1,
.flags = BAF_OPTIONAL | BAF_TRANSITIVE,
},
[BA_AIGP] = {
.name = "bgp_aigp",
+ .legacy_name = "BGP.aigp",
.type = T_OPAQUE,
.flags = BAF_OPTIONAL | BAF_DECODE_FLAGS,
.export = bgp_export_aigp,
},
[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,
},
[BA_ONLY_TO_CUSTOMER] = {
.name = "bgp_otc",
+ .legacy_name = "BGP.otc",
.type = T_INT,
.flags = BAF_OPTIONAL | BAF_TRANSITIVE,
.encode = bgp_encode_u32,
},
[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,
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,
};
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,
};
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,
};
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
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
};
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 {
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,
};