]> git.proxmox.com Git - mirror_frr.git/blob - tests/ospfd/common.c
Merge pull request #12796 from donaldsharp/routemap_debugging
[mirror_frr.git] / tests / ospfd / common.c
1 #include <zebra.h>
2
3 #include "lib/stream.h"
4 #include "lib/vty.h"
5 #include "lib/mpls.h"
6 #include "lib/if.h"
7 #include "lib/table.h"
8
9 #include "ospfd/ospfd.h"
10 #include "ospfd/ospf_route.h"
11 #include "ospfd/ospf_spf.h"
12 #include "ospfd/ospf_flood.h"
13 #include "ospfd/ospf_lsa.h"
14 #include "ospfd/ospf_lsdb.h"
15 #include "ospfd/ospf_interface.h"
16 #include "ospfd/ospf_sr.h"
17
18 #include "common.h"
19
20 struct thread_master *master;
21 struct zebra_privs_t ospfd_privs;
22
23
24 struct ospf_topology *test_find_topology(const char *name)
25 {
26 if (strmatch(name, "topo1"))
27 return &topo1;
28 else if (strmatch(name, "topo2"))
29 return &topo2;
30 else if (strmatch(name, "topo3"))
31 return &topo3;
32 else if (strmatch(name, "topo4"))
33 return &topo4;
34 else if (strmatch(name, "topo5"))
35 return &topo5;
36
37 return NULL;
38 }
39
40 int sort_paths(const void **path1, const void **path2)
41 {
42 const struct ospf_path *p1 = *path1;
43 const struct ospf_path *p2 = *path2;
44
45 return (p1->nexthop.s_addr - p2->nexthop.s_addr);
46 }
47
48 void print_route_table(struct vty *vty, struct route_table *rt)
49 {
50 struct route_node *rn;
51 struct ospf_route * or ;
52 struct listnode *pnode;
53 struct ospf_path *path;
54 struct mpls_label_stack *label_stack;
55 char buf[MPLS_LABEL_STRLEN];
56
57 for (rn = route_top(rt); rn; rn = route_next(rn)) {
58 if ((or = rn->info) == NULL)
59 continue;
60
61 vty_out(vty, "N %-18pFX %-15pI4 %d\n", &rn->p,
62 & or->u.std.area_id, or->cost);
63
64 list_sort(or->paths, sort_paths);
65
66 for (ALL_LIST_ELEMENTS_RO(or->paths, pnode, path)) {
67 if (path->nexthop.s_addr == 0)
68 continue;
69
70 vty_out(vty, " -> %pI4 with adv router %pI4",
71 &path->nexthop, &path->adv_router);
72
73 if (path->srni.backup_label_stack) {
74 label_stack = path->srni.backup_label_stack;
75 mpls_label2str(label_stack->num_labels,
76 label_stack->label, buf,
77 MPLS_LABEL_STRLEN,
78 ZEBRA_LSP_NONE, true);
79 vty_out(vty, " and backup path %s", buf);
80 }
81 vty_out(vty, "\n");
82 }
83 }
84 }
85
86 struct ospf_test_node *test_find_node(struct ospf_topology *topology,
87 const char *hostname)
88 {
89 for (int i = 0; topology->nodes[i].hostname[0]; i++)
90 if (strmatch(hostname, topology->nodes[i].hostname))
91 return &topology->nodes[i];
92
93 return NULL;
94 }
95
96 static void inject_router_lsa(struct vty *vty, struct ospf *ospf,
97 struct ospf_topology *topology,
98 struct ospf_test_node *root,
99 struct ospf_test_node *tnode)
100 {
101 struct ospf_area *area;
102 struct in_addr router_id;
103 struct in_addr adj_router_id;
104 struct prefix_ipv4 prefix;
105 struct in_addr data;
106 struct stream *s;
107 struct lsa_header *lsah;
108 struct ospf_lsa *new;
109 int length;
110 unsigned long putp;
111 uint16_t link_count;
112 struct ospf_test_node *tfound_adj_node;
113 struct ospf_test_adj *tadj;
114 bool is_self_lsa = false;
115
116 area = ospf->backbone;
117 inet_aton(tnode->router_id, &router_id);
118
119 if (strncmp(root->router_id, tnode->router_id, 256) == 0)
120 is_self_lsa = true;
121
122 s = stream_new(OSPF_MAX_LSA_SIZE);
123 lsa_header_set(s, LSA_OPTIONS_GET(area) | LSA_OPTIONS_NSSA_GET(area),
124 OSPF_ROUTER_LSA, router_id, router_id);
125
126 stream_putc(s, router_lsa_flags(area));
127 stream_putc(s, 0);
128
129 putp = stream_get_endp(s);
130 stream_putw(s, 0);
131
132 for (link_count = 0; tnode->adjacencies[link_count].hostname[0];
133 link_count++) {
134 tadj = &tnode->adjacencies[link_count];
135 tfound_adj_node = test_find_node(topology, tadj->hostname);
136 str2prefix_ipv4(tnode->adjacencies[link_count].network,
137 &prefix);
138
139 inet_aton(tfound_adj_node->router_id, &adj_router_id);
140 data.s_addr = prefix.prefix.s_addr;
141 link_info_set(&s, adj_router_id, data,
142 LSA_LINK_TYPE_POINTOPOINT, 0, tadj->metric);
143
144 masklen2ip(prefix.prefixlen, &data);
145 link_info_set(&s, prefix.prefix, data, LSA_LINK_TYPE_STUB, 0,
146 tadj->metric);
147 }
148
149 /* Don't forget the node itself (just a stub) */
150 str2prefix_ipv4(tnode->router_id, &prefix);
151 data.s_addr = 0xffffffff;
152 link_info_set(&s, prefix.prefix, data, LSA_LINK_TYPE_STUB, 0, 0);
153
154 /* Take twice the link count (for P2P and stub) plus the local stub */
155 stream_putw_at(s, putp, (2 * link_count) + 1);
156
157 length = stream_get_endp(s);
158 lsah = (struct lsa_header *)STREAM_DATA(s);
159 lsah->length = htons(length);
160
161 new = ospf_lsa_new_and_data(length);
162 new->area = area;
163 new->vrf_id = area->ospf->vrf_id;
164
165 if (is_self_lsa)
166 SET_FLAG(new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED);
167
168 memcpy(new->data, lsah, length);
169 stream_free(s);
170
171 ospf_lsdb_add(area->lsdb, new);
172
173 if (is_self_lsa) {
174 ospf_lsa_unlock(&area->router_lsa_self);
175 area->router_lsa_self = ospf_lsa_lock(new);
176 }
177 }
178
179 static void inject_sr_db_entry(struct vty *vty, struct ospf_test_node *tnode,
180 struct ospf_topology *topology)
181 {
182 struct ospf_test_node *tfound_adj_node;
183 struct ospf_test_adj *tadj;
184 struct in_addr router_id;
185 struct in_addr remote_id;
186 struct sr_node *srn;
187 struct sr_prefix *srp;
188 struct sr_link *srl;
189 int link_count;
190
191 inet_aton(tnode->router_id, &router_id);
192
193 srn = ospf_sr_node_create(&router_id);
194
195 srn->srgb.range_size = 8000;
196 srn->srgb.lower_bound = 16000;
197 srn->msd = 16;
198
199 srn->srlb.range_size = 1000;
200 srn->srlb.lower_bound = 15000;
201
202 /* Prefix SID */
203 srp = XCALLOC(MTYPE_OSPF_SR_PARAMS, sizeof(struct sr_prefix));
204 srp->adv_router = router_id;
205 srp->sid = tnode->label;
206 srp->srn = srn;
207
208 listnode_add(srn->ext_prefix, srp);
209
210 /* Adjacency SIDs for all adjacencies */
211 for (link_count = 0; tnode->adjacencies[link_count].hostname[0];
212 link_count++) {
213 tadj = &tnode->adjacencies[link_count];
214 tfound_adj_node = test_find_node(topology, tadj->hostname);
215
216 srl = XCALLOC(MTYPE_OSPF_SR_PARAMS, sizeof(struct sr_link));
217 srl->adv_router = router_id;
218
219 inet_aton(tfound_adj_node->router_id, &remote_id);
220 srl->remote_id = remote_id;
221
222 srl->type = ADJ_SID;
223 srl->sid[0] = srn->srlb.lower_bound + tadj->label;
224 srl->srn = srn;
225
226 listnode_add(srn->ext_link, srl);
227 }
228 }
229
230 int topology_load(struct vty *vty, struct ospf_topology *topology,
231 struct ospf_test_node *root, struct ospf *ospf)
232 {
233 struct ospf_test_node *tnode;
234
235 for (int i = 0; topology->nodes[i].hostname[0]; i++) {
236 tnode = &topology->nodes[i];
237
238 /* Inject a router LSA for each node, used for SPF */
239 inject_router_lsa(vty, ospf, topology, root, tnode);
240
241 /*
242 * SR information could also be inected via LSAs, but directly
243 * filling the SR DB with labels is just easier.
244 */
245 inject_sr_db_entry(vty, tnode, topology);
246 }
247
248 return 0;
249 }