]>
git.ipfire.org Git - thirdparty/bird.git/blob - nest/rt-show.c
002a6039c961d23b233d37aac66b135136966b4a
2 * BIRD -- Route Display Routines
4 * (c) 1998--2000 Martin Mares <mj@ucw.cz>
5 * (c) 2017 Jan Moskyto Matejka <mq@jmq.cz>
7 * Can be freely distributed and used under the terms of the GNU GPL.
12 #include "nest/bird.h"
13 #include "nest/route.h"
14 #include "nest/protocol.h"
16 #include "nest/iface.h"
17 #include "filter/filter.h"
20 rt_show_table(struct cli
*c
, struct rt_show_data
*d
)
22 /* No table blocks in 'show route count' */
26 if (d
->last_table
) cli_printf(c
, -1007, "");
27 cli_printf(c
, -1007, "Table %s:", d
->tab
->table
->name
);
28 d
->last_table
= d
->tab
;
32 rt_show_rte(struct cli
*c
, byte
*ia
, rte
*e
, struct rt_show_data
*d
)
34 byte from
[IPA_MAX_TEXT_LENGTH
+8];
35 byte tm
[TM_DATETIME_BUFFER_SIZE
], info
[256];
37 int primary
= (e
->net
->routes
== e
);
38 int sync_error
= (e
->net
->n
.flags
& KRF_SYNC_ERROR
);
39 void (*get_route_info
)(struct rte
*, byte
*buf
);
42 tm_format_time(tm
, &config
->tf_route
, e
->lastmod
);
43 if (ipa_nonzero(a
->from
) && !ipa_equal(a
->from
, a
->nh
.gw
))
44 bsprintf(from
, " from %I", a
->from
);
48 /* Need to normalize the extended attributes */
49 if (d
->verbose
&& !rta_is_cached(a
) && a
->eattrs
)
50 ea_normalize(a
->eattrs
);
52 get_route_info
= a
->src
->proto
->proto
->get_route_info
;
54 get_route_info(e
, info
);
56 bsprintf(info
, " (%d)", e
->pref
);
58 if (d
->last_table
!= d
->tab
)
61 cli_printf(c
, -1007, "%-20s %s [%s %s%s]%s%s", ia
, rta_dest_name(a
->dest
),
62 a
->src
->proto
->name
, tm
, from
, primary
? (sync_error
? " !" : " *") : "", info
);
64 if (a
->dest
== RTD_UNICAST
)
65 for (nh
= &(a
->nh
); nh
; nh
= nh
->next
)
67 char mpls
[MPLS_MAX_LABEL_STACK
*12 + 5], *lsp
= mpls
;
68 char *onlink
= (nh
->flags
& RNF_ONLINK
) ? " onlink" : "";
73 lsp
+= bsprintf(lsp
, " mpls %d", nh
->label
[0]);
74 for (int i
=1;i
<nh
->labels
; i
++)
75 lsp
+= bsprintf(lsp
, "/%d", nh
->label
[i
]);
80 bsprintf(weight
, " weight %d", nh
->weight
+ 1);
82 if (ipa_nonzero(nh
->gw
))
83 cli_printf(c
, -1007, "\tvia %I on %s%s%s%s",
84 nh
->gw
, nh
->iface
->name
, mpls
, onlink
, weight
);
86 cli_printf(c
, -1007, "\tdev %s%s%s",
87 nh
->iface
->name
, mpls
, onlink
, weight
);
95 rt_show_net(struct cli
*c
, net
*n
, struct rt_show_data
*d
)
98 byte ia
[NET_MAX_TEXT_LENGTH
+1];
99 struct channel
*ec
= d
->tab
->export_channel
;
103 bsnprintf(ia
, sizeof(ia
), "%N", n
->n
.addr
);
105 for (e
= n
->routes
; e
; e
= e
->next
)
107 if (rte_is_filtered(e
) != d
->filtered
)
111 d
->net_counter
+= first
;
118 rte_make_tmp_attrs(&e
, c
->show_pool
, NULL
);
120 /* Export channel is down, do not try to export routes to it */
121 if (ec
&& (ec
->export_state
== ES_DOWN
))
124 /* Special case for merged export */
125 if ((d
->export_mode
== RSEM_EXPORT
) && (ec
->ra_mode
== RA_MERGED
))
128 e
= rt_export_merged(ec
, n
, &rt_free
, c
->show_pool
, 1);
132 { e
= ee
; goto skip
; }
134 else if (d
->export_mode
)
136 struct proto
*ep
= ec
->proto
;
137 int ic
= ep
->preexport
? ep
->preexport(ep
, &e
, c
->show_pool
) : 0;
139 if (ec
->ra_mode
== RA_OPTIMAL
|| ec
->ra_mode
== RA_MERGED
)
145 if (d
->export_mode
> RSEM_PREEXPORT
)
148 * FIXME - This shows what should be exported according to current
149 * filters, but not what was really exported. 'configure soft'
150 * command may change the export filter and do not update routes.
152 int do_export
= (ic
> 0) ||
153 (f_run(ec
->out_filter
, &e
, c
->show_pool
, FF_SILENT
) <= F_ACCEPT
);
155 if (do_export
!= (d
->export_mode
== RSEM_EXPORT
))
158 if ((d
->export_mode
== RSEM_EXPORT
) && (ec
->ra_mode
== RA_ACCEPTED
))
163 if (d
->show_protocol
&& (d
->show_protocol
!= e
->attrs
->src
->proto
))
166 if (f_run(d
->filter
, &e
, c
->show_pool
, 0) > F_ACCEPT
)
170 rt_show_rte(c
, ia
, e
, d
);
181 lp_flush(c
->show_pool
);
189 rt_show_cleanup(struct cli
*c
)
191 struct rt_show_data
*d
= c
->rover
;
192 struct rt_show_data_rtable
*tab
;
194 /* Unlink the iterator */
196 fit_get(&d
->tab
->table
->fib
, &d
->fit
);
198 /* Unlock referenced tables */
199 WALK_LIST(tab
, d
->tables
)
200 rt_unlock_table(tab
->table
);
204 rt_show_cont(struct cli
*c
)
206 struct rt_show_data
*d
= c
->rover
;
212 struct fib
*fib
= &d
->tab
->table
->fib
;
213 struct fib_iterator
*it
= &d
->fit
;
215 if (d
->running_on_config
&& (d
->running_on_config
!= config
))
217 cli_printf(c
, 8004, "Stopped due to reconfiguration");
223 FIB_ITERATE_INIT(&d
->fit
, &d
->tab
->table
->fib
);
227 d
->show_counter_last
= d
->show_counter
;
228 d
->rt_counter_last
= d
->rt_counter
;
229 d
->net_counter_last
= d
->net_counter
;
231 if (d
->tables_defined_by
& RSD_TDB_SET
)
235 FIB_ITERATE_START(fib
, it
, net
, n
)
242 rt_show_net(c
, n
, d
);
248 if (d
->last_table
!= d
->tab
)
251 cli_printf(c
, -1007, "%d of %d routes for %d networks in table %s",
252 d
->show_counter
- d
->show_counter_last
, d
->rt_counter
- d
->rt_counter_last
,
253 d
->net_counter
- d
->net_counter_last
, d
->tab
->table
->name
);
257 d
->tab
= NODE_NEXT(d
->tab
);
259 if (NODE_VALID(d
->tab
))
262 if (d
->stats
&& (d
->table_counter
> 1))
264 if (d
->last_table
) cli_printf(c
, -1007, "");
265 cli_printf(c
, 14, "Total: %d of %d routes for %d networks in %d tables",
266 d
->show_counter
, d
->rt_counter
, d
->net_counter
, d
->table_counter
);
269 cli_printf(c
, 0, "");
273 c
->cont
= c
->cleanup
= NULL
;
276 struct rt_show_data_rtable
*
277 rt_show_add_table(struct rt_show_data
*d
, rtable
*t
)
279 struct rt_show_data_rtable
*tab
= cfg_allocz(sizeof(struct rt_show_data_rtable
));
281 add_tail(&(d
->tables
), &(tab
->n
));
286 rt_show_get_default_tables(struct rt_show_data
*d
)
289 struct rt_show_data_rtable
*tab
;
291 if (d
->export_channel
)
293 c
= d
->export_channel
;
294 tab
= rt_show_add_table(d
, c
->table
);
295 tab
->export_channel
= c
;
299 if (d
->export_protocol
)
301 WALK_LIST(c
, d
->export_protocol
->channels
)
303 if (c
->export_state
== ES_DOWN
)
306 tab
= rt_show_add_table(d
, c
->table
);
307 tab
->export_channel
= c
;
312 if (d
->show_protocol
)
314 WALK_LIST(c
, d
->show_protocol
->channels
)
315 rt_show_add_table(d
, c
->table
);
319 for (int i
=1; i
<NET_MAX
; i
++)
320 if (config
->def_tables
[i
])
321 rt_show_add_table(d
, config
->def_tables
[i
]->table
);
325 rt_show_prepare_tables(struct rt_show_data
*d
)
327 struct rt_show_data_rtable
*tab
, *tabx
;
329 /* Add implicit tables if no table is specified */
330 if (EMPTY_LIST(d
->tables
))
331 rt_show_get_default_tables(d
);
333 WALK_LIST_DELSAFE(tab
, tabx
, d
->tables
)
335 /* Ensure there is defined export_channel for each table */
338 if (!tab
->export_channel
&& d
->export_channel
&&
339 (tab
->table
== d
->export_channel
->table
))
340 tab
->export_channel
= d
->export_channel
;
342 if (!tab
->export_channel
&& d
->export_protocol
)
343 tab
->export_channel
= proto_find_channel_by_table(d
->export_protocol
, tab
->table
);
345 if (!tab
->export_channel
)
347 if (d
->tables_defined_by
& RSD_TDB_NMN
)
348 cf_error("No export channel for table %s", tab
->table
->name
);
355 /* Ensure specified network is compatible with each table */
356 if (d
->addr
&& (tab
->table
->addr_type
!= d
->addr
->type
))
358 if (d
->tables_defined_by
& RSD_TDB_NMN
)
359 cf_error("Incompatible type of prefix/ip for table %s", tab
->table
->name
);
366 /* Ensure there is at least one table */
367 if (EMPTY_LIST(d
->tables
))
368 cf_error("No valid tables");
372 rt_show(struct rt_show_data
*d
)
374 struct rt_show_data_rtable
*tab
;
377 /* Filtered routes are neither exported nor have sensible ordering */
378 if (d
->filtered
&& (d
->export_mode
|| d
->primary_only
))
379 cf_error("Incompatible show route options");
381 rt_show_prepare_tables(d
);
385 WALK_LIST(tab
, d
->tables
)
386 rt_lock_table(tab
->table
);
388 /* There is at least one table */
389 d
->tab
= HEAD(d
->tables
);
390 this_cli
->cont
= rt_show_cont
;
391 this_cli
->cleanup
= rt_show_cleanup
;
396 WALK_LIST(tab
, d
->tables
)
401 n
= net_route(tab
->table
, d
->addr
);
403 n
= net_find(tab
->table
, d
->addr
);
406 rt_show_net(this_cli
, n
, d
);
412 cli_msg(8001, "Network not found");