]> git.proxmox.com Git - mirror_frr.git/blob - tests/ospfd/common.c
Merge pull request #7218 from kuldeepkash/multicast_pim_bsm
[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, true);
78 vty_out(vty, " and backup path %s", buf);
79 }
80 vty_out(vty, "\n");
81 }
82 }
83 }
84
85 struct ospf_test_node *test_find_node(struct ospf_topology *topology,
86 const char *hostname)
87 {
88 for (int i = 0; topology->nodes[i].hostname[0]; i++)
89 if (strmatch(hostname, topology->nodes[i].hostname))
90 return &topology->nodes[i];
91
92 return NULL;
93 }
94
95 static void inject_router_lsa(struct vty *vty, struct ospf *ospf,
96 struct ospf_topology *topology,
97 struct ospf_test_node *root,
98 struct ospf_test_node *tnode)
99 {
100 struct ospf_area *area;
101 struct in_addr router_id;
102 struct in_addr adj_router_id;
103 struct prefix_ipv4 prefix;
104 struct in_addr data;
105 struct stream *s;
106 struct lsa_header *lsah;
107 struct ospf_lsa *new;
108 int length;
109 unsigned long putp;
110 uint16_t link_count;
111 struct ospf_test_node *tfound_adj_node;
112 struct ospf_test_adj *tadj;
113 bool is_self_lsa = false;
114
115 area = ospf->backbone;
116 inet_aton(tnode->router_id, &router_id);
117
118 if (strncmp(root->router_id, tnode->router_id, 256) == 0)
119 is_self_lsa = true;
120
121 s = stream_new(OSPF_MAX_LSA_SIZE);
122 lsa_header_set(s, LSA_OPTIONS_GET(area) | LSA_OPTIONS_NSSA_GET(area),
123 OSPF_ROUTER_LSA, router_id, router_id);
124
125 stream_putc(s, router_lsa_flags(area));
126 stream_putc(s, 0);
127
128 putp = stream_get_endp(s);
129 stream_putw(s, 0);
130
131 for (link_count = 0; tnode->adjacencies[link_count].hostname[0];
132 link_count++) {
133 tadj = &tnode->adjacencies[link_count];
134 tfound_adj_node = test_find_node(topology, tadj->hostname);
135 str2prefix_ipv4(tnode->adjacencies[link_count].network,
136 &prefix);
137
138 inet_aton(tfound_adj_node->router_id, &adj_router_id);
139 data.s_addr = prefix.prefix.s_addr;
140 link_info_set(&s, adj_router_id, data,
141 LSA_LINK_TYPE_POINTOPOINT, 0, tadj->metric);
142
143 masklen2ip(prefix.prefixlen, &data);
144 link_info_set(&s, prefix.prefix, data, LSA_LINK_TYPE_STUB, 0,
145 tadj->metric);
146 }
147
148 /* Don't forget the node itself (just a stub) */
149 str2prefix_ipv4(tnode->router_id, &prefix);
150 data.s_addr = 0xffffffff;
151 link_info_set(&s, prefix.prefix, data, LSA_LINK_TYPE_STUB, 0, 0);
152
153 /* Take twice the link count (for P2P and stub) plus the local stub */
154 stream_putw_at(s, putp, (2 * link_count) + 1);
155
156 length = stream_get_endp(s);
157 lsah = (struct lsa_header *)STREAM_DATA(s);
158 lsah->length = htons(length);
159
160 new = ospf_lsa_new_and_data(length);
161 new->area = area;
162 new->vrf_id = area->ospf->vrf_id;
163
164 if (is_self_lsa)
165 SET_FLAG(new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED);
166
167 memcpy(new->data, lsah, length);
168 stream_free(s);
169
170 ospf_lsdb_add(area->lsdb, new);
171
172 if (is_self_lsa) {
173 ospf_lsa_unlock(&area->router_lsa_self);
174 area->router_lsa_self = ospf_lsa_lock(new);
175 }
176 }
177
178 static void inject_sr_db_entry(struct vty *vty, struct ospf_test_node *tnode,
179 struct ospf_topology *topology)
180 {
181 struct ospf_test_node *tfound_adj_node;
182 struct ospf_test_adj *tadj;
183 struct in_addr router_id;
184 struct in_addr remote_id;
185 struct sr_node *srn;
186 struct sr_prefix *srp;
187 struct sr_link *srl;
188 int link_count;
189
190 inet_aton(tnode->router_id, &router_id);
191
192 srn = ospf_sr_node_create(&router_id);
193
194 srn->srgb.range_size = 8000;
195 srn->srgb.lower_bound = 16000;
196 srn->msd = 16;
197
198 srn->srlb.range_size = 1000;
199 srn->srlb.lower_bound = 15000;
200
201 /* Prefix SID */
202 srp = XCALLOC(MTYPE_OSPF_SR_PARAMS, sizeof(struct sr_prefix));
203 srp->adv_router = router_id;
204 srp->sid = tnode->label;
205 srp->srn = srn;
206
207 listnode_add(srn->ext_prefix, srp);
208
209 /* Adjacency SIDs for all adjacencies */
210 for (link_count = 0; tnode->adjacencies[link_count].hostname[0];
211 link_count++) {
212 tadj = &tnode->adjacencies[link_count];
213 tfound_adj_node = test_find_node(topology, tadj->hostname);
214
215 srl = XCALLOC(MTYPE_OSPF_SR_PARAMS, sizeof(struct sr_link));
216 srl->adv_router = router_id;
217
218 inet_aton(tfound_adj_node->router_id, &remote_id);
219 srl->remote_id = remote_id;
220
221 srl->type = ADJ_SID;
222 srl->sid[0] = srn->srlb.lower_bound + tadj->label;
223 srl->srn = srn;
224
225 listnode_add(srn->ext_link, srl);
226 }
227 }
228
229 int topology_load(struct vty *vty, struct ospf_topology *topology,
230 struct ospf_test_node *root, struct ospf *ospf)
231 {
232 struct ospf_test_node *tnode;
233
234 for (int i = 0; topology->nodes[i].hostname[0]; i++) {
235 tnode = &topology->nodes[i];
236
237 /* Inject a router LSA for each node, used for SPF */
238 inject_router_lsa(vty, ospf, topology, root, tnode);
239
240 /*
241 * SR information could also be inected via LSAs, but directly
242 * filling the SR DB with labels is just easier.
243 */
244 inject_sr_db_entry(vty, tnode, topology);
245 }
246
247 return 0;
248 }