5 #include <lib/version.h>
13 #include "ospfd/ospfd.h"
14 #include "ospfd/ospf_asbr.h"
15 #include "ospfd/ospf_lsa.h"
16 #include "ospfd/ospf_route.h"
17 #include "ospfd/ospf_spf.h"
18 #include "ospfd/ospf_ti_lfa.h"
19 #include "ospfd/ospf_vty.h"
20 #include "ospfd/ospf_dump.h"
21 #include "ospfd/ospf_sr.h"
25 DECLARE_RBTREE_UNIQ(p_spaces
, struct p_space
, p_spaces_item
,
26 p_spaces_compare_func
);
27 DECLARE_RBTREE_UNIQ(q_spaces
, struct q_space
, q_spaces_item
,
28 q_spaces_compare_func
);
30 static struct ospf
*test_init(struct ospf_test_node
*root
)
33 struct ospf_area
*area
;
34 struct in_addr area_id
;
35 struct in_addr router_id
;
37 ospf
= ospf_new_alloc(0, VRF_DEFAULT_NAME
);
39 area_id
.s_addr
= OSPF_AREA_BACKBONE
;
40 area
= ospf_area_new(ospf
, area_id
);
41 listnode_add_sort(ospf
->areas
, area
);
43 inet_aton(root
->router_id
, &router_id
);
44 ospf
->router_id
= router_id
;
45 ospf
->router_id_static
= router_id
;
46 ospf
->ti_lfa_enabled
= true;
51 static void test_run_spf(struct vty
*vty
, struct ospf
*ospf
,
52 enum protection_type protection_type
, bool verbose
)
54 struct route_table
*new_table
, *new_rtrs
;
55 struct route_table
*all_rtrs
= NULL
;
56 struct ospf_area
*area
;
57 struct p_space
*p_space
;
58 struct q_space
*q_space
;
59 char label_buf
[MPLS_LABEL_STRLEN
];
60 char res_buf
[PROTECTED_RESOURCE_STRLEN
];
62 /* Just use the backbone for testing */
63 area
= ospf
->backbone
;
65 new_table
= route_table_init();
66 new_rtrs
= route_table_init();
67 all_rtrs
= route_table_init();
69 /* dryrun true, root_node false */
70 ospf_spf_calculate(area
, area
->router_lsa_self
, new_table
, all_rtrs
,
71 new_rtrs
, true, false);
74 vty_out(vty
, "SPF Tree without TI-LFA backup paths:\n\n");
75 ospf_spf_print(vty
, area
->spf
, 0);
78 "\nRouting Table without TI-LFA backup paths:\n\n");
79 print_route_table(vty
, new_table
);
83 vty_out(vty
, "\n... generating TI-LFA backup paths ...\n");
86 ospf_ti_lfa_generate_p_spaces(area
, protection_type
);
87 ospf_ti_lfa_insert_backup_paths(area
, new_table
);
89 /* Print P/Q space information */
91 vty_out(vty
, "\nP and Q space info:\n");
92 frr_each (p_spaces
, area
->p_spaces
, p_space
) {
93 ospf_print_protected_resource(
94 p_space
->protected_resource
, res_buf
);
95 vty_out(vty
, "\nP Space for root %pI4 and %s\n",
96 &p_space
->root
->id
, res_buf
);
97 ospf_spf_print(vty
, p_space
->root
, 0);
99 frr_each (q_spaces
, p_space
->q_spaces
, q_space
) {
101 "\nQ Space for destination %pI4:\n",
103 ospf_spf_print(vty
, q_space
->root
, 0);
104 if (q_space
->label_stack
) {
108 q_space
->label_stack
->label
,
109 label_buf
, MPLS_LABEL_STRLEN
,
110 ZEBRA_LSP_NONE
, true);
111 vty_out(vty
, "\nLabel stack: %s\n",
115 "\nLabel stack not generated!\n");
119 vty_out(vty
, "\nPost-convergence SPF Tree:\n");
120 ospf_spf_print(vty
, p_space
->pc_spf
, 0);
125 ospf_ti_lfa_free_p_spaces(area
);
126 ospf_spf_cleanup(area
->spf
, area
->spf_vertex_list
);
129 * Print the new routing table which is augmented with TI-LFA backup
130 * paths (label stacks).
134 "\n\nFinal Routing Table including backup paths:\n\n");
136 print_route_table(vty
, new_table
);
139 static int test_run(struct vty
*vty
, struct ospf_topology
*topology
,
140 struct ospf_test_node
*root
,
141 enum protection_type protection_type
, bool verbose
)
145 ospf
= test_init(root
);
147 /* Inject LSAs into the OSPF backbone according to the topology */
148 if (topology_load(vty
, topology
, root
, ospf
)) {
149 vty_out(vty
, "%% Failed to load topology\n");
155 show_ip_ospf_database_summary(vty
, ospf
, 0, NULL
);
158 test_run_spf(vty
, ospf
, protection_type
, verbose
);
163 DEFUN(test_ospf
, test_ospf_cmd
,
164 "test ospf topology WORD root HOSTNAME ti-lfa [node-protection] [verbose]",
166 "Choose OSPF for SPF testing\n"
167 "Network topology to choose\n"
168 "Name of the network topology to choose\n"
169 "Root node to choose\n"
170 "Hostname of the root node to choose\n"
171 "Use Topology-Independent LFA\n"
172 "Use node protection (default is link protection)\n"
175 struct ospf_topology
*topology
;
176 struct ospf_test_node
*root
;
177 enum protection_type protection_type
= OSPF_TI_LFA_LINK_PROTECTION
;
179 bool verbose
= false;
181 /* Parse topology. */
182 argv_find(argv
, argc
, "topology", &idx
);
183 topology
= test_find_topology(argv
[idx
+ 1]->arg
);
185 vty_out(vty
, "%% Topology not found\n");
189 argv_find(argv
, argc
, "root", &idx
);
190 root
= test_find_node(topology
, argv
[idx
+ 1]->arg
);
192 vty_out(vty
, "%% Root not found\n");
196 if (argv_find(argv
, argc
, "node-protection", &idx
))
197 protection_type
= OSPF_TI_LFA_NODE_PROTECTION
;
199 if (argv_find(argv
, argc
, "verbose", &idx
))
202 return test_run(vty
, topology
, root
, protection_type
, verbose
);
205 static void vty_do_exit(int isexit
)
211 thread_master_free(master
);
217 struct option longopts
[] = {{"help", no_argument
, NULL
, 'h'},
218 {"debug", no_argument
, NULL
, 'd'},
221 /* Help information display. */
222 static void usage(char *progname
, int status
)
225 fprintf(stderr
, "Try `%s --help' for more information.\n",
228 printf("Usage : %s [OPTION...]\n\
229 ospfd SPF test program.\n\n\
230 -u, --debug Enable debugging\n\
231 -h, --help Display this help and exit\n\
233 Report bugs to %s\n",
234 progname
, FRR_BUG_ADDRESS
);
239 int main(int argc
, char **argv
)
243 struct thread thread
;
246 /* Set umask before anything for security */
249 /* get program name */
250 progname
= ((p
= strrchr(argv
[0], '/')) ? ++p
: argv
[0]);
255 opt
= getopt_long(argc
, argv
, "hd", longopts
, 0);
276 master
= thread_master_create(NULL
);
280 cmd_hostname_set("test");
281 vty_init(master
, false);
283 zlog_aux_init("NONE: ", LOG_DEBUG
);
285 zlog_aux_init("NONE: ", ZLOG_DISABLED
);
287 /* Install test command. */
288 install_element(VIEW_NODE
, &test_ospf_cmd
);
290 /* needed for SR DB init */
294 term_debug_ospf_ti_lfa
= 1;
296 /* Read input from .in file. */
297 vty_stdio(vty_do_exit
);
299 /* Fetch next active thread. */
300 while (thread_fetch(master
, &thread
))
301 thread_call(&thread
);