]>
Commit | Line | Data |
---|---|---|
7fd0729f G |
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" | |
66dc21bb | 7 | #include "lib/table.h" |
7fd0729f G |
8 | |
9 | #include "ospfd/ospfd.h" | |
66dc21bb | 10 | #include "ospfd/ospf_route.h" |
7fd0729f G |
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 | ||
cd9d0537 | 20 | struct event_loop *master; |
7fd0729f G |
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; | |
385a1e07 G |
32 | else if (strmatch(name, "topo4")) |
33 | return &topo4; | |
bdcfd34a G |
34 | else if (strmatch(name, "topo5")) |
35 | return &topo5; | |
7fd0729f G |
36 | |
37 | return NULL; | |
38 | } | |
39 | ||
66dc21bb G |
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, | |
6712f624 SW |
77 | MPLS_LABEL_STRLEN, |
78 | ZEBRA_LSP_NONE, true); | |
66dc21bb G |
79 | vty_out(vty, " and backup path %s", buf); |
80 | } | |
81 | vty_out(vty, "\n"); | |
82 | } | |
83 | } | |
84 | } | |
85 | ||
7fd0729f G |
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 | ||
cc1725bd G |
179 | static void inject_sr_db_entry(struct vty *vty, struct ospf_test_node *tnode, |
180 | struct ospf_topology *topology) | |
7fd0729f | 181 | { |
cc1725bd G |
182 | struct ospf_test_node *tfound_adj_node; |
183 | struct ospf_test_adj *tadj; | |
7fd0729f | 184 | struct in_addr router_id; |
cc1725bd | 185 | struct in_addr remote_id; |
7fd0729f G |
186 | struct sr_node *srn; |
187 | struct sr_prefix *srp; | |
cc1725bd G |
188 | struct sr_link *srl; |
189 | int link_count; | |
7fd0729f G |
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 | ||
cc1725bd G |
199 | srn->srlb.range_size = 1000; |
200 | srn->srlb.lower_bound = 15000; | |
7fd0729f | 201 | |
cc1725bd G |
202 | /* Prefix SID */ |
203 | srp = XCALLOC(MTYPE_OSPF_SR_PARAMS, sizeof(struct sr_prefix)); | |
7fd0729f G |
204 | srp->adv_router = router_id; |
205 | srp->sid = tnode->label; | |
206 | srp->srn = srn; | |
207 | ||
208 | listnode_add(srn->ext_prefix, srp); | |
cc1725bd G |
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 | } | |
7fd0729f G |
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 | */ | |
cc1725bd | 245 | inject_sr_db_entry(vty, tnode, topology); |
7fd0729f G |
246 | } |
247 | ||
248 | return 0; | |
249 | } |