]>
git.ipfire.org Git - thirdparty/bird.git/blob - nest/rt-show.c
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
, int primary
)
34 byte from
[IPA_MAX_TEXT_LENGTH
+8];
35 byte tm
[TM_DATETIME_BUFFER_SIZE
], info
[256];
37 int sync_error
= (e
->net
->n
.flags
& KRF_SYNC_ERROR
);
38 void (*get_route_info
)(struct rte
*, byte
*buf
);
41 tm_format_time(tm
, &config
->tf_route
, e
->lastmod
);
42 if (ipa_nonzero(a
->from
) && !ipa_equal(a
->from
, a
->nh
.gw
))
43 bsprintf(from
, " from %I", a
->from
);
47 /* Need to normalize the extended attributes */
48 if (d
->verbose
&& !rta_is_cached(a
) && a
->eattrs
)
49 ea_normalize(a
->eattrs
);
51 get_route_info
= a
->src
->proto
->proto
->get_route_info
;
53 get_route_info(e
, info
);
55 bsprintf(info
, " (%d)", e
->pref
);
57 if (d
->last_table
!= d
->tab
)
60 cli_printf(c
, -1007, "%-20s %s [%s %s%s]%s%s", ia
, rta_dest_name(a
->dest
),
61 a
->src
->proto
->name
, tm
, from
, primary
? (sync_error
? " !" : " *") : "", info
);
63 if (a
->dest
== RTD_UNICAST
)
64 for (nh
= &(a
->nh
); nh
; nh
= nh
->next
)
66 char mpls
[MPLS_MAX_LABEL_STACK
*12 + 5], *lsp
= mpls
;
67 char *onlink
= (nh
->flags
& RNF_ONLINK
) ? " onlink" : "";
72 lsp
+= bsprintf(lsp
, " mpls %d", nh
->label
[0]);
73 for (int i
=1;i
<nh
->labels
; i
++)
74 lsp
+= bsprintf(lsp
, "/%d", nh
->label
[i
]);
79 bsprintf(weight
, " weight %d", nh
->weight
+ 1);
81 if (ipa_nonzero(nh
->gw
))
82 cli_printf(c
, -1007, "\tvia %I on %s%s%s%s",
83 nh
->gw
, nh
->iface
->name
, mpls
, onlink
, weight
);
85 cli_printf(c
, -1007, "\tdev %s%s%s",
86 nh
->iface
->name
, mpls
, onlink
, weight
);
94 rt_show_net(struct cli
*c
, net
*n
, struct rt_show_data
*d
)
97 byte ia
[NET_MAX_TEXT_LENGTH
+1];
98 struct channel
*ec
= d
->tab
->export_channel
;
102 bsnprintf(ia
, sizeof(ia
), "%N", n
->n
.addr
);
104 for (e
= n
->routes
; e
; e
= e
->next
)
106 if (rte_is_filtered(e
) != d
->filtered
)
110 d
->net_counter
+= first
;
117 rte_make_tmp_attrs(&e
, c
->show_pool
, NULL
);
119 /* Export channel is down, do not try to export routes to it */
120 if (ec
&& (ec
->export_state
== ES_DOWN
))
123 /* Special case for merged export */
124 if ((d
->export_mode
== RSEM_EXPORT
) && (ec
->ra_mode
== RA_MERGED
))
127 e
= rt_export_merged(ec
, n
, &rt_free
, c
->show_pool
, 1);
131 { e
= ee
; goto skip
; }
133 else if (d
->export_mode
)
135 struct proto
*ep
= ec
->proto
;
136 int ic
= ep
->preexport
? ep
->preexport(ep
, &e
, c
->show_pool
) : 0;
138 if (ec
->ra_mode
== RA_OPTIMAL
|| ec
->ra_mode
== RA_MERGED
)
144 if (d
->export_mode
> RSEM_PREEXPORT
)
147 * FIXME - This shows what should be exported according to current
148 * filters, but not what was really exported. 'configure soft'
149 * command may change the export filter and do not update routes.
151 int do_export
= (ic
> 0) ||
152 (f_run(ec
->out_filter
, &e
, c
->show_pool
, FF_SILENT
) <= F_ACCEPT
);
154 if (do_export
!= (d
->export_mode
== RSEM_EXPORT
))
157 if ((d
->export_mode
== RSEM_EXPORT
) && (ec
->ra_mode
== RA_ACCEPTED
))
162 if (d
->show_protocol
&& (d
->show_protocol
!= e
->attrs
->src
->proto
))
165 if (f_run(d
->filter
, &e
, c
->show_pool
, 0) > F_ACCEPT
)
169 rt_show_rte(c
, ia
, e
, d
, (e
->net
->routes
== ee
));
180 lp_flush(c
->show_pool
);
188 rt_show_cleanup(struct cli
*c
)
190 struct rt_show_data
*d
= c
->rover
;
191 struct rt_show_data_rtable
*tab
;
193 /* Unlink the iterator */
195 fit_get(&d
->tab
->table
->fib
, &d
->fit
);
197 /* Unlock referenced tables */
198 WALK_LIST(tab
, d
->tables
)
199 rt_unlock_table(tab
->table
);
203 rt_show_cont(struct cli
*c
)
205 struct rt_show_data
*d
= c
->rover
;
211 struct fib
*fib
= &d
->tab
->table
->fib
;
212 struct fib_iterator
*it
= &d
->fit
;
214 if (d
->running_on_config
&& (d
->running_on_config
!= config
))
216 cli_printf(c
, 8004, "Stopped due to reconfiguration");
222 FIB_ITERATE_INIT(&d
->fit
, &d
->tab
->table
->fib
);
226 d
->show_counter_last
= d
->show_counter
;
227 d
->rt_counter_last
= d
->rt_counter
;
228 d
->net_counter_last
= d
->net_counter
;
230 if (d
->tables_defined_by
& RSD_TDB_SET
)
234 FIB_ITERATE_START(fib
, it
, net
, n
)
241 rt_show_net(c
, n
, d
);
247 if (d
->last_table
!= d
->tab
)
250 cli_printf(c
, -1007, "%d of %d routes for %d networks in table %s",
251 d
->show_counter
- d
->show_counter_last
, d
->rt_counter
- d
->rt_counter_last
,
252 d
->net_counter
- d
->net_counter_last
, d
->tab
->table
->name
);
256 d
->tab
= NODE_NEXT(d
->tab
);
258 if (NODE_VALID(d
->tab
))
261 if (d
->stats
&& (d
->table_counter
> 1))
263 if (d
->last_table
) cli_printf(c
, -1007, "");
264 cli_printf(c
, 14, "Total: %d of %d routes for %d networks in %d tables",
265 d
->show_counter
, d
->rt_counter
, d
->net_counter
, d
->table_counter
);
268 cli_printf(c
, 0, "");
272 c
->cont
= c
->cleanup
= NULL
;
275 struct rt_show_data_rtable
*
276 rt_show_add_table(struct rt_show_data
*d
, rtable
*t
)
278 struct rt_show_data_rtable
*tab
= cfg_allocz(sizeof(struct rt_show_data_rtable
));
280 add_tail(&(d
->tables
), &(tab
->n
));
285 rt_show_get_default_tables(struct rt_show_data
*d
)
288 struct rt_show_data_rtable
*tab
;
290 if (d
->export_channel
)
292 c
= d
->export_channel
;
293 tab
= rt_show_add_table(d
, c
->table
);
294 tab
->export_channel
= c
;
298 if (d
->export_protocol
)
300 WALK_LIST(c
, d
->export_protocol
->channels
)
302 if (c
->export_state
== ES_DOWN
)
305 tab
= rt_show_add_table(d
, c
->table
);
306 tab
->export_channel
= c
;
311 if (d
->show_protocol
)
313 WALK_LIST(c
, d
->show_protocol
->channels
)
314 rt_show_add_table(d
, c
->table
);
318 for (int i
=1; i
<NET_MAX
; i
++)
319 if (config
->def_tables
[i
])
320 rt_show_add_table(d
, config
->def_tables
[i
]->table
);
324 rt_show_prepare_tables(struct rt_show_data
*d
)
326 struct rt_show_data_rtable
*tab
, *tabx
;
328 /* Add implicit tables if no table is specified */
329 if (EMPTY_LIST(d
->tables
))
330 rt_show_get_default_tables(d
);
332 WALK_LIST_DELSAFE(tab
, tabx
, d
->tables
)
334 /* Ensure there is defined export_channel for each table */
337 if (!tab
->export_channel
&& d
->export_channel
&&
338 (tab
->table
== d
->export_channel
->table
))
339 tab
->export_channel
= d
->export_channel
;
341 if (!tab
->export_channel
&& d
->export_protocol
)
342 tab
->export_channel
= proto_find_channel_by_table(d
->export_protocol
, tab
->table
);
344 if (!tab
->export_channel
)
346 if (d
->tables_defined_by
& RSD_TDB_NMN
)
347 cf_error("No export channel for table %s", tab
->table
->name
);
354 /* Ensure specified network is compatible with each table */
355 if (d
->addr
&& (tab
->table
->addr_type
!= d
->addr
->type
))
357 if (d
->tables_defined_by
& RSD_TDB_NMN
)
358 cf_error("Incompatible type of prefix/ip for table %s", tab
->table
->name
);
365 /* Ensure there is at least one table */
366 if (EMPTY_LIST(d
->tables
))
367 cf_error("No valid tables");
371 rt_show(struct rt_show_data
*d
)
373 struct rt_show_data_rtable
*tab
;
376 /* Filtered routes are neither exported nor have sensible ordering */
377 if (d
->filtered
&& (d
->export_mode
|| d
->primary_only
))
378 cf_error("Incompatible show route options");
380 rt_show_prepare_tables(d
);
384 WALK_LIST(tab
, d
->tables
)
385 rt_lock_table(tab
->table
);
387 /* There is at least one table */
388 d
->tab
= HEAD(d
->tables
);
389 this_cli
->cont
= rt_show_cont
;
390 this_cli
->cleanup
= rt_show_cleanup
;
395 WALK_LIST(tab
, d
->tables
)
400 n
= net_route(tab
->table
, d
->addr
);
402 n
= net_find(tab
->table
, d
->addr
);
405 rt_show_net(this_cli
, n
, d
);
411 cli_msg(8001, "Network not found");