]> git.proxmox.com Git - mirror_frr.git/blob - tests/ospfd/test_ospf_spf.c
bgpd: Allow self next-hop if `bgp allow-martian-nexthop` is enabled
[mirror_frr.git] / tests / ospfd / test_ospf_spf.c
1 #include <zebra.h>
2
3 #include "getopt.h"
4 #include "thread.h"
5 #include <lib/version.h>
6 #include "vty.h"
7 #include "command.h"
8 #include "log.h"
9 #include "vrf.h"
10 #include "table.h"
11 #include "mpls.h"
12
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"
22
23 #include "common.h"
24
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);
29
30 static struct ospf *test_init(struct ospf_test_node *root)
31 {
32 struct ospf *ospf;
33 struct ospf_area *area;
34 struct in_addr area_id;
35 struct in_addr router_id;
36
37 ospf = ospf_new_alloc(0, VRF_DEFAULT_NAME);
38
39 area_id.s_addr = OSPF_AREA_BACKBONE;
40 area = ospf_area_new(ospf, area_id);
41 listnode_add_sort(ospf->areas, area);
42
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;
47
48 return ospf;
49 }
50
51 static void test_run_spf(struct vty *vty, struct ospf *ospf,
52 enum protection_type protection_type, bool verbose)
53 {
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];
61
62 /* Just use the backbone for testing */
63 area = ospf->backbone;
64
65 new_table = route_table_init();
66 new_rtrs = route_table_init();
67 all_rtrs = route_table_init();
68
69 /* dryrun true, root_node false */
70 ospf_spf_calculate(area, area->router_lsa_self, new_table, all_rtrs,
71 new_rtrs, true, false);
72
73 if (verbose) {
74 vty_out(vty, "SPF Tree without TI-LFA backup paths:\n\n");
75 ospf_spf_print(vty, area->spf, 0);
76
77 vty_out(vty,
78 "\nRouting Table without TI-LFA backup paths:\n\n");
79 print_route_table(vty, new_table);
80 }
81
82 if (verbose)
83 vty_out(vty, "\n... generating TI-LFA backup paths ...\n");
84
85 /* TI-LFA testrun */
86 ospf_ti_lfa_generate_p_spaces(area, protection_type);
87 ospf_ti_lfa_insert_backup_paths(area, new_table);
88
89 /* Print P/Q space information */
90 if (verbose) {
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);
98
99 frr_each (q_spaces, p_space->q_spaces, q_space) {
100 vty_out(vty,
101 "\nQ Space for destination %pI4:\n",
102 &q_space->root->id);
103 ospf_spf_print(vty, q_space->root, 0);
104 if (q_space->label_stack) {
105 mpls_label2str(
106 q_space->label_stack
107 ->num_labels,
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",
112 label_buf);
113 } else {
114 vty_out(vty,
115 "\nLabel stack not generated!\n");
116 }
117 }
118
119 vty_out(vty, "\nPost-convergence SPF Tree:\n");
120 ospf_spf_print(vty, p_space->pc_spf, 0);
121 }
122 }
123
124 /* Cleanup */
125 ospf_ti_lfa_free_p_spaces(area);
126 ospf_spf_cleanup(area->spf, area->spf_vertex_list);
127
128 /*
129 * Print the new routing table which is augmented with TI-LFA backup
130 * paths (label stacks).
131 */
132 if (verbose)
133 vty_out(vty,
134 "\n\nFinal Routing Table including backup paths:\n\n");
135
136 print_route_table(vty, new_table);
137 }
138
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)
142 {
143 struct ospf *ospf;
144
145 ospf = test_init(root);
146
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");
150 return CMD_WARNING;
151 }
152
153 if (verbose) {
154 vty_out(vty, "\n");
155 show_ip_ospf_database_summary(vty, ospf, 0, NULL);
156 }
157
158 test_run_spf(vty, ospf, protection_type, verbose);
159
160 return 0;
161 }
162
163 DEFUN(test_ospf, test_ospf_cmd,
164 "test ospf topology WORD root HOSTNAME ti-lfa [node-protection] [verbose]",
165 "Test mode\n"
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"
173 "Verbose output\n")
174 {
175 struct ospf_topology *topology;
176 struct ospf_test_node *root;
177 enum protection_type protection_type = OSPF_TI_LFA_LINK_PROTECTION;
178 int idx = 0;
179 bool verbose = false;
180
181 /* Parse topology. */
182 argv_find(argv, argc, "topology", &idx);
183 topology = test_find_topology(argv[idx + 1]->arg);
184 if (!topology) {
185 vty_out(vty, "%% Topology not found\n");
186 return CMD_WARNING;
187 }
188
189 argv_find(argv, argc, "root", &idx);
190 root = test_find_node(topology, argv[idx + 1]->arg);
191 if (!root) {
192 vty_out(vty, "%% Root not found\n");
193 return CMD_WARNING;
194 }
195
196 if (argv_find(argv, argc, "node-protection", &idx))
197 protection_type = OSPF_TI_LFA_NODE_PROTECTION;
198
199 if (argv_find(argv, argc, "verbose", &idx))
200 verbose = true;
201
202 return test_run(vty, topology, root, protection_type, verbose);
203 }
204
205 static void vty_do_exit(int isexit)
206 {
207 printf("\nend.\n");
208
209 cmd_terminate();
210 vty_terminate();
211 thread_master_free(master);
212
213 if (!isexit)
214 exit(0);
215 }
216
217 struct option longopts[] = {{"help", no_argument, NULL, 'h'},
218 {"debug", no_argument, NULL, 'd'},
219 {0} };
220
221 /* Help information display. */
222 static void usage(char *progname, int status)
223 {
224 if (status != 0)
225 fprintf(stderr, "Try `%s --help' for more information.\n",
226 progname);
227 else {
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\
232 \n\
233 Report bugs to %s\n",
234 progname, FRR_BUG_ADDRESS);
235 }
236 exit(status);
237 }
238
239 int main(int argc, char **argv)
240 {
241 char *p;
242 char *progname;
243 struct thread thread;
244 bool debug = false;
245
246 /* Set umask before anything for security */
247 umask(0027);
248
249 /* get program name */
250 progname = ((p = strrchr(argv[0], '/')) ? ++p : argv[0]);
251
252 while (1) {
253 int opt;
254
255 opt = getopt_long(argc, argv, "hd", longopts, 0);
256
257 if (opt == EOF)
258 break;
259
260 switch (opt) {
261 case 0:
262 break;
263 case 'd':
264 debug = true;
265 break;
266 case 'h':
267 usage(progname, 0);
268 break;
269 default:
270 usage(progname, 1);
271 break;
272 }
273 }
274
275 /* master init. */
276 master = thread_master_create(NULL);
277
278 /* Library inits. */
279 cmd_init(1);
280 cmd_hostname_set("test");
281 vty_init(master, false);
282 if (debug)
283 zlog_aux_init("NONE: ", LOG_DEBUG);
284 else
285 zlog_aux_init("NONE: ", ZLOG_DISABLED);
286
287 /* Install test command. */
288 install_element(VIEW_NODE, &test_ospf_cmd);
289
290 /* needed for SR DB init */
291 ospf_vty_init();
292 ospf_sr_init();
293
294 term_debug_ospf_ti_lfa = 1;
295
296 /* Read input from .in file. */
297 vty_stdio(vty_do_exit);
298
299 /* Fetch next active thread. */
300 while (thread_fetch(master, &thread))
301 thread_call(&thread);
302
303 /* Not reached. */
304 exit(0);
305 }