/src/frr/ospfd/ospf_zebra.c
Line | Count | Source |
1 | | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | | /* |
3 | | * Zebra connect library for OSPFd |
4 | | * Copyright (C) 1997, 98, 99, 2000 Kunihiro Ishiguro, Toshiaki Takada |
5 | | */ |
6 | | |
7 | | #include <zebra.h> |
8 | | |
9 | | #include "frrevent.h" |
10 | | #include "command.h" |
11 | | #include "network.h" |
12 | | #include "prefix.h" |
13 | | #include "routemap.h" |
14 | | #include "table.h" |
15 | | #include "stream.h" |
16 | | #include "memory.h" |
17 | | #include "zclient.h" |
18 | | #include "filter.h" |
19 | | #include "plist.h" |
20 | | #include "log.h" |
21 | | #include "route_opaque.h" |
22 | | #include "lib/bfd.h" |
23 | | #include "lib/lib_errors.h" |
24 | | #include "nexthop.h" |
25 | | |
26 | | #include "ospfd/ospfd.h" |
27 | | #include "ospfd/ospf_interface.h" |
28 | | #include "ospfd/ospf_ism.h" |
29 | | #include "ospfd/ospf_asbr.h" |
30 | | #include "ospfd/ospf_asbr.h" |
31 | | #include "ospfd/ospf_abr.h" |
32 | | #include "ospfd/ospf_lsa.h" |
33 | | #include "ospfd/ospf_dump.h" |
34 | | #include "ospfd/ospf_route.h" |
35 | | #include "ospfd/ospf_lsdb.h" |
36 | | #include "ospfd/ospf_neighbor.h" |
37 | | #include "ospfd/ospf_nsm.h" |
38 | | #include "ospfd/ospf_zebra.h" |
39 | | #include "ospfd/ospf_te.h" |
40 | | #include "ospfd/ospf_sr.h" |
41 | | #include "ospfd/ospf_ldp_sync.h" |
42 | | |
43 | 2 | DEFINE_MTYPE_STATIC(OSPFD, OSPF_EXTERNAL, "OSPF External route table"); |
44 | 2 | DEFINE_MTYPE_STATIC(OSPFD, OSPF_REDISTRIBUTE, "OSPF Redistriute"); |
45 | 2 | |
46 | 2 | |
47 | 2 | /* Zebra structure to hold current status. */ |
48 | 2 | struct zclient *zclient = NULL; |
49 | 2 | /* and for the Synchronous connection to the Label Manager */ |
50 | 2 | static struct zclient *zclient_sync; |
51 | 2 | |
52 | 2 | /* For registering threads. */ |
53 | 2 | extern struct event_loop *master; |
54 | 2 | |
55 | 2 | /* Router-id update message from zebra. */ |
56 | 2 | static int ospf_router_id_update_zebra(ZAPI_CALLBACK_ARGS) |
57 | 2 | { |
58 | 0 | struct ospf *ospf = NULL; |
59 | 0 | struct prefix router_id; |
60 | 0 | zebra_router_id_update_read(zclient->ibuf, &router_id); |
61 | |
|
62 | 0 | if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE)) |
63 | 0 | zlog_debug("Zebra rcvd: router id update %pFX vrf %s id %u", |
64 | 0 | &router_id, ospf_vrf_id_to_name(vrf_id), vrf_id); |
65 | |
|
66 | 0 | ospf = ospf_lookup_by_vrf_id(vrf_id); |
67 | |
|
68 | 0 | if (ospf != NULL) { |
69 | 0 | ospf->router_id_zebra = router_id.u.prefix4; |
70 | 0 | ospf_router_id_update(ospf); |
71 | 0 | } else { |
72 | 0 | if (IS_DEBUG_OSPF_EVENT) |
73 | 0 | zlog_debug( |
74 | 0 | "%s: ospf instance not found for vrf %s id %u router_id %pFX", |
75 | 0 | __func__, ospf_vrf_id_to_name(vrf_id), vrf_id, |
76 | 0 | &router_id); |
77 | 0 | } |
78 | 0 | return 0; |
79 | 0 | } |
80 | | |
81 | | static int ospf_interface_address_add(ZAPI_CALLBACK_ARGS) |
82 | 0 | { |
83 | 0 | struct connected *c; |
84 | 0 | struct ospf *ospf = NULL; |
85 | | |
86 | |
|
87 | 0 | c = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id); |
88 | |
|
89 | 0 | if (c == NULL) |
90 | 0 | return 0; |
91 | | |
92 | 0 | if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE)) |
93 | 0 | zlog_debug("Zebra: interface %s address add %pFX vrf %s id %u", |
94 | 0 | c->ifp->name, c->address, |
95 | 0 | ospf_vrf_id_to_name(vrf_id), vrf_id); |
96 | |
|
97 | 0 | ospf = ospf_lookup_by_vrf_id(vrf_id); |
98 | 0 | if (!ospf) |
99 | 0 | return 0; |
100 | | |
101 | 0 | ospf_if_update(ospf, c->ifp); |
102 | |
|
103 | 0 | ospf_if_interface(c->ifp); |
104 | |
|
105 | 0 | return 0; |
106 | 0 | } |
107 | | |
108 | | static int ospf_interface_address_delete(ZAPI_CALLBACK_ARGS) |
109 | 0 | { |
110 | 0 | struct connected *c; |
111 | 0 | struct interface *ifp; |
112 | 0 | struct ospf_interface *oi; |
113 | 0 | struct route_node *rn; |
114 | 0 | struct prefix p; |
115 | |
|
116 | 0 | c = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id); |
117 | |
|
118 | 0 | if (c == NULL) |
119 | 0 | return 0; |
120 | | |
121 | 0 | if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE)) |
122 | 0 | zlog_debug("Zebra: interface %s address delete %pFX", |
123 | 0 | c->ifp->name, c->address); |
124 | |
|
125 | 0 | ifp = c->ifp; |
126 | 0 | p = *c->address; |
127 | 0 | p.prefixlen = IPV4_MAX_BITLEN; |
128 | |
|
129 | 0 | rn = route_node_lookup(IF_OIFS(ifp), &p); |
130 | 0 | if (!rn) { |
131 | 0 | connected_free(&c); |
132 | 0 | return 0; |
133 | 0 | } |
134 | | |
135 | 0 | assert(rn->info); |
136 | 0 | oi = rn->info; |
137 | 0 | route_unlock_node(rn); |
138 | | |
139 | | /* Call interface hook functions to clean up */ |
140 | 0 | ospf_if_free(oi); |
141 | |
|
142 | 0 | ospf_if_interface(c->ifp); |
143 | |
|
144 | 0 | connected_free(&c); |
145 | |
|
146 | 0 | return 0; |
147 | 0 | } |
148 | | |
149 | | static int ospf_interface_link_params(ZAPI_CALLBACK_ARGS) |
150 | 0 | { |
151 | 0 | struct interface *ifp; |
152 | 0 | bool changed = false; |
153 | |
|
154 | 0 | ifp = zebra_interface_link_params_read(zclient->ibuf, vrf_id, &changed); |
155 | |
|
156 | 0 | if (ifp == NULL || !changed) |
157 | 0 | return 0; |
158 | | |
159 | | /* Update TE TLV */ |
160 | 0 | ospf_mpls_te_update_if(ifp); |
161 | |
|
162 | 0 | return 0; |
163 | 0 | } |
164 | | |
165 | | /* VRF update for an interface. */ |
166 | | static int ospf_interface_vrf_update(ZAPI_CALLBACK_ARGS) |
167 | 0 | { |
168 | 0 | struct interface *ifp = NULL; |
169 | 0 | vrf_id_t new_vrf_id; |
170 | |
|
171 | 0 | ifp = zebra_interface_vrf_update_read(zclient->ibuf, vrf_id, |
172 | 0 | &new_vrf_id); |
173 | 0 | if (!ifp) |
174 | 0 | return 0; |
175 | | |
176 | 0 | if (IS_DEBUG_OSPF_EVENT) |
177 | 0 | zlog_debug( |
178 | 0 | "%s: Rx Interface %s VRF change vrf_id %u New vrf %s id %u", |
179 | 0 | __func__, ifp->name, vrf_id, |
180 | 0 | ospf_vrf_id_to_name(new_vrf_id), new_vrf_id); |
181 | | |
182 | | /*if_update(ifp, ifp->name, strlen(ifp->name), new_vrf_id);*/ |
183 | 0 | if_update_to_new_vrf(ifp, new_vrf_id); |
184 | |
|
185 | 0 | return 0; |
186 | 0 | } |
187 | | |
188 | | /* Nexthop, ifindex, distance and metric information. */ |
189 | | static void ospf_zebra_add_nexthop(struct ospf *ospf, struct ospf_path *path, |
190 | | struct zapi_route *api) |
191 | 0 | { |
192 | 0 | struct zapi_nexthop *api_nh; |
193 | 0 | struct zapi_nexthop *api_nh_backup; |
194 | | |
195 | | /* TI-LFA backup path label stack comes first, if present */ |
196 | 0 | if (path->srni.backup_label_stack) { |
197 | 0 | api_nh_backup = &api->backup_nexthops[api->backup_nexthop_num]; |
198 | 0 | api_nh_backup->vrf_id = ospf->vrf_id; |
199 | |
|
200 | 0 | api_nh_backup->type = NEXTHOP_TYPE_IPV4; |
201 | 0 | api_nh_backup->gate.ipv4 = path->srni.backup_nexthop; |
202 | |
|
203 | 0 | api_nh_backup->label_num = |
204 | 0 | path->srni.backup_label_stack->num_labels; |
205 | 0 | memcpy(api_nh_backup->labels, |
206 | 0 | path->srni.backup_label_stack->label, |
207 | 0 | sizeof(mpls_label_t) * api_nh_backup->label_num); |
208 | |
|
209 | 0 | api->backup_nexthop_num++; |
210 | 0 | } |
211 | | |
212 | | /* And here comes the primary nexthop */ |
213 | 0 | api_nh = &api->nexthops[api->nexthop_num]; |
214 | 0 | #ifdef HAVE_NETLINK |
215 | 0 | if (path->unnumbered |
216 | 0 | || (path->nexthop.s_addr != INADDR_ANY && path->ifindex != 0)) { |
217 | | #else /* HAVE_NETLINK */ |
218 | | if (path->nexthop.s_addr != INADDR_ANY && path->ifindex != 0) { |
219 | | #endif /* HAVE_NETLINK */ |
220 | 0 | api_nh->gate.ipv4 = path->nexthop; |
221 | 0 | api_nh->ifindex = path->ifindex; |
222 | 0 | api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX; |
223 | 0 | } else if (path->nexthop.s_addr != INADDR_ANY) { |
224 | 0 | api_nh->gate.ipv4 = path->nexthop; |
225 | 0 | api_nh->type = NEXTHOP_TYPE_IPV4; |
226 | 0 | } else { |
227 | 0 | api_nh->ifindex = path->ifindex; |
228 | 0 | api_nh->type = NEXTHOP_TYPE_IFINDEX; |
229 | 0 | } |
230 | 0 | api_nh->vrf_id = ospf->vrf_id; |
231 | | |
232 | | /* Set TI-LFA backup nexthop info if present */ |
233 | 0 | if (path->srni.backup_label_stack) { |
234 | 0 | SET_FLAG(api->message, ZAPI_MESSAGE_BACKUP_NEXTHOPS); |
235 | 0 | SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP); |
236 | | |
237 | | /* Just care about a single TI-LFA backup path for now */ |
238 | 0 | api_nh->backup_num = 1; |
239 | 0 | api_nh->backup_idx[0] = api->backup_nexthop_num - 1; |
240 | 0 | } |
241 | |
|
242 | 0 | api->nexthop_num++; |
243 | 0 | } |
244 | | |
245 | | static void ospf_zebra_append_opaque_attr(struct ospf_route *or, |
246 | | struct zapi_route *api) |
247 | 0 | { |
248 | 0 | struct ospf_zebra_opaque ospf_opaque = {}; |
249 | | |
250 | | /* OSPF path type */ |
251 | 0 | snprintf(ospf_opaque.path_type, sizeof(ospf_opaque.path_type), "%s", |
252 | 0 | ospf_path_type_name(or->path_type)); |
253 | |
|
254 | 0 | switch (or->path_type) { |
255 | 0 | case OSPF_PATH_INTRA_AREA: |
256 | 0 | case OSPF_PATH_INTER_AREA: |
257 | | /* OSPF area ID */ |
258 | 0 | (void)inet_ntop(AF_INET, &or->u.std.area_id, |
259 | 0 | ospf_opaque.area_id, |
260 | 0 | sizeof(ospf_opaque.area_id)); |
261 | 0 | break; |
262 | 0 | case OSPF_PATH_TYPE1_EXTERNAL: |
263 | 0 | case OSPF_PATH_TYPE2_EXTERNAL: |
264 | | /* OSPF route tag */ |
265 | 0 | snprintf(ospf_opaque.tag, sizeof(ospf_opaque.tag), "%u", |
266 | 0 | or->u.ext.tag); |
267 | 0 | break; |
268 | 0 | default: |
269 | 0 | break; |
270 | 0 | } |
271 | | |
272 | 0 | SET_FLAG(api->message, ZAPI_MESSAGE_OPAQUE); |
273 | 0 | api->opaque.length = sizeof(struct ospf_zebra_opaque); |
274 | 0 | memcpy(api->opaque.data, &ospf_opaque, api->opaque.length); |
275 | 0 | } |
276 | | |
277 | | void ospf_zebra_add(struct ospf *ospf, struct prefix_ipv4 *p, |
278 | | struct ospf_route * or) |
279 | 0 | { |
280 | 0 | struct zapi_route api; |
281 | 0 | uint8_t distance; |
282 | 0 | struct ospf_path *path; |
283 | 0 | struct listnode *node; |
284 | |
|
285 | 0 | if (ospf->gr_info.restart_in_progress) { |
286 | 0 | if (IS_DEBUG_OSPF_GR) |
287 | 0 | zlog_debug( |
288 | 0 | "Zebra: Graceful Restart in progress -- not installing %pFX", |
289 | 0 | p); |
290 | 0 | return; |
291 | 0 | } |
292 | | |
293 | 0 | memset(&api, 0, sizeof(api)); |
294 | 0 | api.vrf_id = ospf->vrf_id; |
295 | 0 | api.type = ZEBRA_ROUTE_OSPF; |
296 | 0 | api.instance = ospf->instance; |
297 | 0 | api.safi = SAFI_UNICAST; |
298 | |
|
299 | 0 | memcpy(&api.prefix, p, sizeof(*p)); |
300 | 0 | SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); |
301 | | |
302 | | /* Metric value. */ |
303 | 0 | SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); |
304 | 0 | if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL) |
305 | 0 | api.metric = or->cost + or->u.ext.type2_cost; |
306 | 0 | else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL) |
307 | 0 | api.metric = or->u.ext.type2_cost; |
308 | 0 | else |
309 | 0 | api.metric = or->cost; |
310 | | |
311 | | /* Check if path type is ASE */ |
312 | 0 | if (((or->path_type == OSPF_PATH_TYPE1_EXTERNAL) |
313 | 0 | || (or->path_type == OSPF_PATH_TYPE2_EXTERNAL)) |
314 | 0 | && (or->u.ext.tag > 0) && (or->u.ext.tag <= ROUTE_TAG_MAX)) { |
315 | 0 | SET_FLAG(api.message, ZAPI_MESSAGE_TAG); |
316 | 0 | api.tag = or->u.ext.tag; |
317 | 0 | } |
318 | | |
319 | | /* Distance value. */ |
320 | 0 | distance = ospf_distance_apply(ospf, p, or); |
321 | 0 | if (distance) { |
322 | 0 | SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); |
323 | 0 | api.distance = distance; |
324 | 0 | } |
325 | |
|
326 | 0 | for (ALL_LIST_ELEMENTS_RO(or->paths, node, path)) { |
327 | 0 | if (api.nexthop_num >= ospf->max_multipath) |
328 | 0 | break; |
329 | | |
330 | 0 | ospf_zebra_add_nexthop(ospf, path, &api); |
331 | |
|
332 | 0 | if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) { |
333 | 0 | struct interface *ifp; |
334 | |
|
335 | 0 | ifp = if_lookup_by_index(path->ifindex, ospf->vrf_id); |
336 | |
|
337 | 0 | zlog_debug( |
338 | 0 | "Zebra: Route add %pFX nexthop %pI4, ifindex=%d %s", |
339 | 0 | p, &path->nexthop, path->ifindex, |
340 | 0 | ifp ? ifp->name : " "); |
341 | 0 | } |
342 | 0 | } |
343 | |
|
344 | 0 | if (CHECK_FLAG(ospf->config, OSPF_SEND_EXTRA_DATA_TO_ZEBRA)) |
345 | 0 | ospf_zebra_append_opaque_attr(or, &api); |
346 | |
|
347 | 0 | zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api); |
348 | 0 | } |
349 | | |
350 | | void ospf_zebra_delete(struct ospf *ospf, struct prefix_ipv4 *p, |
351 | | struct ospf_route * or) |
352 | 0 | { |
353 | 0 | struct zapi_route api; |
354 | |
|
355 | 0 | if (ospf->gr_info.restart_in_progress) { |
356 | 0 | if (IS_DEBUG_OSPF_GR) |
357 | 0 | zlog_debug( |
358 | 0 | "Zebra: Graceful Restart in progress -- not uninstalling %pFX", |
359 | 0 | p); |
360 | 0 | return; |
361 | 0 | } |
362 | | |
363 | 0 | memset(&api, 0, sizeof(api)); |
364 | 0 | api.vrf_id = ospf->vrf_id; |
365 | 0 | api.type = ZEBRA_ROUTE_OSPF; |
366 | 0 | api.instance = ospf->instance; |
367 | 0 | api.safi = SAFI_UNICAST; |
368 | 0 | memcpy(&api.prefix, p, sizeof(*p)); |
369 | |
|
370 | 0 | if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) |
371 | 0 | zlog_debug("Zebra: Route delete %pFX", p); |
372 | |
|
373 | 0 | zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api); |
374 | 0 | } |
375 | | |
376 | | void ospf_zebra_add_discard(struct ospf *ospf, struct prefix_ipv4 *p) |
377 | 0 | { |
378 | 0 | struct zapi_route api; |
379 | |
|
380 | 0 | if (ospf->gr_info.restart_in_progress) { |
381 | 0 | if (IS_DEBUG_OSPF_GR) |
382 | 0 | zlog_debug( |
383 | 0 | "Zebra: Graceful Restart in progress -- not installing %pFX", |
384 | 0 | p); |
385 | 0 | return; |
386 | 0 | } |
387 | | |
388 | 0 | memset(&api, 0, sizeof(api)); |
389 | 0 | api.vrf_id = ospf->vrf_id; |
390 | 0 | api.type = ZEBRA_ROUTE_OSPF; |
391 | 0 | api.instance = ospf->instance; |
392 | 0 | api.safi = SAFI_UNICAST; |
393 | 0 | memcpy(&api.prefix, p, sizeof(*p)); |
394 | 0 | zapi_route_set_blackhole(&api, BLACKHOLE_NULL); |
395 | |
|
396 | 0 | zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api); |
397 | |
|
398 | 0 | if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) |
399 | 0 | zlog_debug("Zebra: Route add discard %pFX", p); |
400 | 0 | } |
401 | | |
402 | | void ospf_zebra_delete_discard(struct ospf *ospf, struct prefix_ipv4 *p) |
403 | 0 | { |
404 | 0 | struct zapi_route api; |
405 | |
|
406 | 0 | if (ospf->gr_info.restart_in_progress) { |
407 | 0 | if (IS_DEBUG_OSPF_GR) |
408 | 0 | zlog_debug( |
409 | 0 | "Zebra: Graceful Restart in progress -- not uninstalling %pFX", |
410 | 0 | p); |
411 | 0 | return; |
412 | 0 | } |
413 | | |
414 | 0 | memset(&api, 0, sizeof(api)); |
415 | 0 | api.vrf_id = ospf->vrf_id; |
416 | 0 | api.type = ZEBRA_ROUTE_OSPF; |
417 | 0 | api.instance = ospf->instance; |
418 | 0 | api.safi = SAFI_UNICAST; |
419 | 0 | memcpy(&api.prefix, p, sizeof(*p)); |
420 | 0 | zapi_route_set_blackhole(&api, BLACKHOLE_NULL); |
421 | |
|
422 | 0 | zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api); |
423 | |
|
424 | 0 | if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) |
425 | 0 | zlog_debug("Zebra: Route delete discard %pFX", p); |
426 | 0 | } |
427 | | |
428 | | struct ospf_external *ospf_external_lookup(struct ospf *ospf, uint8_t type, |
429 | | unsigned short instance) |
430 | 0 | { |
431 | 0 | struct list *ext_list; |
432 | 0 | struct listnode *node; |
433 | 0 | struct ospf_external *ext; |
434 | |
|
435 | 0 | ext_list = ospf->external[type]; |
436 | 0 | if (!ext_list) |
437 | 0 | return (NULL); |
438 | | |
439 | 0 | for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) |
440 | 0 | if (ext->instance == instance) |
441 | 0 | return ext; |
442 | | |
443 | 0 | return NULL; |
444 | 0 | } |
445 | | |
446 | | struct ospf_external *ospf_external_add(struct ospf *ospf, uint8_t type, |
447 | | unsigned short instance) |
448 | 0 | { |
449 | 0 | struct list *ext_list; |
450 | 0 | struct ospf_external *ext; |
451 | |
|
452 | 0 | ext = ospf_external_lookup(ospf, type, instance); |
453 | 0 | if (ext) |
454 | 0 | return ext; |
455 | | |
456 | 0 | if (!ospf->external[type]) |
457 | 0 | ospf->external[type] = list_new(); |
458 | |
|
459 | 0 | ext_list = ospf->external[type]; |
460 | 0 | ext = XCALLOC(MTYPE_OSPF_EXTERNAL, sizeof(struct ospf_external)); |
461 | 0 | ext->instance = instance; |
462 | 0 | EXTERNAL_INFO(ext) = route_table_init(); |
463 | |
|
464 | 0 | listnode_add(ext_list, ext); |
465 | |
|
466 | 0 | return ext; |
467 | 0 | } |
468 | | |
469 | | /* |
470 | | * Walk all the ei received from zebra for a route type and apply |
471 | | * default route-map. |
472 | | */ |
473 | | bool ospf_external_default_routemap_apply_walk(struct ospf *ospf, |
474 | | struct list *ext_list, |
475 | | struct external_info *default_ei) |
476 | 0 | { |
477 | 0 | struct listnode *node; |
478 | 0 | struct ospf_external *ext; |
479 | 0 | struct route_node *rn; |
480 | 0 | struct external_info *ei = NULL; |
481 | 0 | int ret = 0; |
482 | |
|
483 | 0 | for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) { |
484 | 0 | if (!ext->external_info) |
485 | 0 | continue; |
486 | | |
487 | 0 | for (rn = route_top(ext->external_info); rn; |
488 | 0 | rn = route_next(rn)) { |
489 | 0 | ei = rn->info; |
490 | 0 | if (!ei) |
491 | 0 | continue; |
492 | 0 | ret = ospf_external_info_apply_default_routemap( |
493 | 0 | ospf, ei, default_ei); |
494 | 0 | if (ret) |
495 | 0 | break; |
496 | 0 | } |
497 | 0 | } |
498 | |
|
499 | 0 | if (ret && ei) { |
500 | 0 | if (IS_DEBUG_OSPF_DEFAULT_INFO) |
501 | 0 | zlog_debug("Default originate routemap permit ei: %pI4", |
502 | 0 | &ei->p.prefix); |
503 | 0 | return true; |
504 | 0 | } |
505 | | |
506 | 0 | return false; |
507 | 0 | } |
508 | | |
509 | | /* |
510 | | * Function to originate or flush default after applying |
511 | | * route-map on all ei. |
512 | | */ |
513 | | static void ospf_external_lsa_default_routemap_timer(struct event *thread) |
514 | 0 | { |
515 | 0 | struct list *ext_list; |
516 | 0 | struct ospf *ospf = EVENT_ARG(thread); |
517 | 0 | struct prefix_ipv4 p; |
518 | 0 | int type; |
519 | 0 | int ret = 0; |
520 | 0 | struct ospf_lsa *lsa; |
521 | 0 | struct external_info *default_ei; |
522 | 0 |
|
523 | 0 | p.family = AF_INET; |
524 | 0 | p.prefixlen = 0; |
525 | 0 | p.prefix.s_addr = INADDR_ANY; |
526 | 0 |
|
527 | 0 | /* Get the default extenal info. */ |
528 | 0 | default_ei = ospf_external_info_lookup(ospf, DEFAULT_ROUTE, |
529 | 0 | ospf->instance, &p); |
530 | 0 | if (!default_ei) { |
531 | 0 | /* Nothing to be done here. */ |
532 | 0 | if (IS_DEBUG_OSPF_DEFAULT_INFO) |
533 | 0 | zlog_debug("Default originate info not present"); |
534 | 0 | return; |
535 | 0 | } |
536 | 0 |
|
537 | 0 | /* For all the ei apply route-map */ |
538 | 0 | for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) { |
539 | 0 | ext_list = ospf->external[type]; |
540 | 0 | if (!ext_list || type == ZEBRA_ROUTE_OSPF) |
541 | 0 | continue; |
542 | 0 |
|
543 | 0 | ret = ospf_external_default_routemap_apply_walk(ospf, ext_list, |
544 | 0 | default_ei); |
545 | 0 | if (ret) |
546 | 0 | break; |
547 | 0 | } |
548 | 0 |
|
549 | 0 | /* Get the default LSA. */ |
550 | 0 | lsa = ospf_external_info_find_lsa(ospf, &p); |
551 | 0 |
|
552 | 0 | /* If permit then originate default. */ |
553 | 0 | if (ret && !lsa) |
554 | 0 | ospf_external_lsa_originate(ospf, default_ei); |
555 | 0 | else if (ret && lsa && IS_LSA_MAXAGE(lsa)) |
556 | 0 | ospf_external_lsa_refresh(ospf, lsa, default_ei, true, false); |
557 | 0 | else if (!ret && lsa) |
558 | 0 | ospf_external_lsa_flush(ospf, DEFAULT_ROUTE, &default_ei->p, 0); |
559 | 0 | } |
560 | | |
561 | | |
562 | | void ospf_external_del(struct ospf *ospf, uint8_t type, unsigned short instance) |
563 | 0 | { |
564 | 0 | struct ospf_external *ext; |
565 | |
|
566 | 0 | ext = ospf_external_lookup(ospf, type, instance); |
567 | |
|
568 | 0 | if (ext) { |
569 | 0 | if (EXTERNAL_INFO(ext)) |
570 | 0 | route_table_finish(EXTERNAL_INFO(ext)); |
571 | |
|
572 | 0 | listnode_delete(ospf->external[type], ext); |
573 | |
|
574 | 0 | if (!ospf->external[type]->count) |
575 | 0 | list_delete(&ospf->external[type]); |
576 | |
|
577 | 0 | XFREE(MTYPE_OSPF_EXTERNAL, ext); |
578 | 0 | } |
579 | | |
580 | | /* |
581 | | * Check if default needs to be flushed too. |
582 | | */ |
583 | 0 | event_add_event(master, ospf_external_lsa_default_routemap_timer, ospf, |
584 | 0 | 0, &ospf->t_default_routemap_timer); |
585 | 0 | } |
586 | | |
587 | | /* Update NHLFE for Prefix SID */ |
588 | | void ospf_zebra_update_prefix_sid(const struct sr_prefix *srp) |
589 | 0 | { |
590 | 0 | struct zapi_labels zl; |
591 | 0 | struct zapi_nexthop *znh; |
592 | 0 | struct zapi_nexthop *znh_backup; |
593 | 0 | struct listnode *node; |
594 | 0 | struct ospf_path *path; |
595 | | |
596 | | /* Prepare message. */ |
597 | 0 | memset(&zl, 0, sizeof(zl)); |
598 | 0 | zl.type = ZEBRA_LSP_OSPF_SR; |
599 | 0 | zl.local_label = srp->label_in; |
600 | |
|
601 | 0 | switch (srp->type) { |
602 | 0 | case LOCAL_SID: |
603 | | /* Set Label for local Prefix */ |
604 | 0 | znh = &zl.nexthops[zl.nexthop_num++]; |
605 | 0 | znh->type = NEXTHOP_TYPE_IFINDEX; |
606 | 0 | znh->ifindex = srp->nhlfe.ifindex; |
607 | 0 | znh->label_num = 1; |
608 | 0 | znh->labels[0] = srp->nhlfe.label_out; |
609 | |
|
610 | 0 | osr_debug("SR (%s): Configure Prefix %pFX with labels %u/%u", |
611 | 0 | __func__, (struct prefix *)&srp->prefv4, |
612 | 0 | srp->label_in, srp->nhlfe.label_out); |
613 | |
|
614 | 0 | break; |
615 | | |
616 | 0 | case PREF_SID: |
617 | | /* Update route in the RIB too. */ |
618 | 0 | SET_FLAG(zl.message, ZAPI_LABELS_FTN); |
619 | 0 | zl.route.prefix.u.prefix4 = srp->prefv4.prefix; |
620 | 0 | zl.route.prefix.prefixlen = srp->prefv4.prefixlen; |
621 | 0 | zl.route.prefix.family = srp->prefv4.family; |
622 | 0 | zl.route.type = ZEBRA_ROUTE_OSPF; |
623 | 0 | zl.route.instance = 0; |
624 | | |
625 | | /* Check that SRP contains at least one valid path */ |
626 | 0 | if (srp->route == NULL) { |
627 | 0 | return; |
628 | 0 | } |
629 | | |
630 | 0 | osr_debug("SR (%s): Configure Prefix %pFX with", |
631 | 0 | __func__, (struct prefix *)&srp->prefv4); |
632 | |
|
633 | 0 | for (ALL_LIST_ELEMENTS_RO(srp->route->paths, node, path)) { |
634 | 0 | if (path->srni.label_out == MPLS_INVALID_LABEL) |
635 | 0 | continue; |
636 | | |
637 | 0 | if (zl.nexthop_num >= MULTIPATH_NUM) |
638 | 0 | break; |
639 | | |
640 | | /* |
641 | | * TI-LFA backup path label stack comes first, if |
642 | | * present. |
643 | | */ |
644 | 0 | if (path->srni.backup_label_stack) { |
645 | 0 | znh_backup = &zl.backup_nexthops |
646 | 0 | [zl.backup_nexthop_num++]; |
647 | 0 | znh_backup->type = NEXTHOP_TYPE_IPV4; |
648 | 0 | znh_backup->gate.ipv4 = |
649 | 0 | path->srni.backup_nexthop; |
650 | |
|
651 | 0 | memcpy(znh_backup->labels, |
652 | 0 | path->srni.backup_label_stack->label, |
653 | 0 | sizeof(mpls_label_t) |
654 | 0 | * path->srni.backup_label_stack |
655 | 0 | ->num_labels); |
656 | |
|
657 | 0 | znh_backup->label_num = |
658 | 0 | path->srni.backup_label_stack |
659 | 0 | ->num_labels; |
660 | 0 | if (path->srni.label_out |
661 | 0 | != MPLS_LABEL_IPV4_EXPLICIT_NULL |
662 | 0 | && path->srni.label_out |
663 | 0 | != MPLS_LABEL_IMPLICIT_NULL) |
664 | 0 | znh_backup->labels |
665 | 0 | [znh_backup->label_num++] = |
666 | 0 | path->srni.label_out; |
667 | 0 | } |
668 | |
|
669 | 0 | znh = &zl.nexthops[zl.nexthop_num++]; |
670 | 0 | znh->type = NEXTHOP_TYPE_IPV4_IFINDEX; |
671 | 0 | znh->gate.ipv4 = path->nexthop; |
672 | 0 | znh->ifindex = path->ifindex; |
673 | 0 | znh->label_num = 1; |
674 | 0 | znh->labels[0] = path->srni.label_out; |
675 | |
|
676 | 0 | osr_debug(" |- labels %u/%u", srp->label_in, |
677 | 0 | path->srni.label_out); |
678 | | |
679 | | /* Set TI-LFA backup nexthop info if present */ |
680 | 0 | if (path->srni.backup_label_stack) { |
681 | 0 | SET_FLAG(zl.message, ZAPI_LABELS_HAS_BACKUPS); |
682 | 0 | SET_FLAG(znh->flags, |
683 | 0 | ZAPI_NEXTHOP_FLAG_HAS_BACKUP); |
684 | | |
685 | | /* Just care about a single TI-LFA backup path |
686 | | * for now */ |
687 | 0 | znh->backup_num = 1; |
688 | 0 | znh->backup_idx[0] = zl.backup_nexthop_num - 1; |
689 | 0 | } |
690 | 0 | } |
691 | 0 | break; |
692 | 0 | case ADJ_SID: |
693 | 0 | case LAN_ADJ_SID: |
694 | 0 | return; |
695 | 0 | } |
696 | | |
697 | | /* Finally, send message to zebra. */ |
698 | 0 | (void)zebra_send_mpls_labels(zclient, ZEBRA_MPLS_LABELS_REPLACE, &zl); |
699 | 0 | } |
700 | | |
701 | | /* Remove NHLFE for Prefix-SID */ |
702 | | void ospf_zebra_delete_prefix_sid(const struct sr_prefix *srp) |
703 | 0 | { |
704 | 0 | struct zapi_labels zl; |
705 | |
|
706 | 0 | osr_debug("SR (%s): Delete Labels %u for Prefix %pFX", __func__, |
707 | 0 | srp->label_in, (struct prefix *)&srp->prefv4); |
708 | | |
709 | | /* Prepare message. */ |
710 | 0 | memset(&zl, 0, sizeof(zl)); |
711 | 0 | zl.type = ZEBRA_LSP_OSPF_SR; |
712 | 0 | zl.local_label = srp->label_in; |
713 | |
|
714 | 0 | if (srp->type == PREF_SID) { |
715 | | /* Update route in the RIB too */ |
716 | 0 | SET_FLAG(zl.message, ZAPI_LABELS_FTN); |
717 | 0 | zl.route.prefix.u.prefix4 = srp->prefv4.prefix; |
718 | 0 | zl.route.prefix.prefixlen = srp->prefv4.prefixlen; |
719 | 0 | zl.route.prefix.family = srp->prefv4.family; |
720 | 0 | zl.route.type = ZEBRA_ROUTE_OSPF; |
721 | 0 | zl.route.instance = 0; |
722 | 0 | } |
723 | | |
724 | | /* Send message to zebra. */ |
725 | 0 | (void)zebra_send_mpls_labels(zclient, ZEBRA_MPLS_LABELS_DELETE, &zl); |
726 | 0 | } |
727 | | |
728 | | /* Send MPLS Label entry to Zebra for installation or deletion */ |
729 | | void ospf_zebra_send_adjacency_sid(int cmd, struct sr_nhlfe nhlfe) |
730 | 0 | { |
731 | 0 | struct zapi_labels zl; |
732 | 0 | struct zapi_nexthop *znh; |
733 | |
|
734 | 0 | osr_debug("SR (%s): %s Labels %u/%u for Adjacency via %u", __func__, |
735 | 0 | cmd == ZEBRA_MPLS_LABELS_ADD ? "Add" : "Delete", |
736 | 0 | nhlfe.label_in, nhlfe.label_out, nhlfe.ifindex); |
737 | |
|
738 | 0 | memset(&zl, 0, sizeof(zl)); |
739 | 0 | zl.type = ZEBRA_LSP_OSPF_SR; |
740 | 0 | zl.local_label = nhlfe.label_in; |
741 | 0 | zl.nexthop_num = 1; |
742 | 0 | znh = &zl.nexthops[0]; |
743 | 0 | znh->type = NEXTHOP_TYPE_IPV4_IFINDEX; |
744 | 0 | znh->gate.ipv4 = nhlfe.nexthop; |
745 | 0 | znh->ifindex = nhlfe.ifindex; |
746 | 0 | znh->label_num = 1; |
747 | 0 | znh->labels[0] = nhlfe.label_out; |
748 | |
|
749 | 0 | (void)zebra_send_mpls_labels(zclient, cmd, &zl); |
750 | 0 | } |
751 | | |
752 | | struct ospf_redist *ospf_redist_lookup(struct ospf *ospf, uint8_t type, |
753 | | unsigned short instance) |
754 | 0 | { |
755 | 0 | struct list *red_list; |
756 | 0 | struct listnode *node; |
757 | 0 | struct ospf_redist *red; |
758 | |
|
759 | 0 | red_list = ospf->redist[type]; |
760 | 0 | if (!red_list) |
761 | 0 | return (NULL); |
762 | | |
763 | 0 | for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) |
764 | 0 | if (red->instance == instance) |
765 | 0 | return red; |
766 | | |
767 | 0 | return NULL; |
768 | 0 | } |
769 | | |
770 | | struct ospf_redist *ospf_redist_add(struct ospf *ospf, uint8_t type, |
771 | | unsigned short instance) |
772 | 0 | { |
773 | 0 | struct list *red_list; |
774 | 0 | struct ospf_redist *red; |
775 | |
|
776 | 0 | red = ospf_redist_lookup(ospf, type, instance); |
777 | 0 | if (red) |
778 | 0 | return red; |
779 | | |
780 | 0 | if (!ospf->redist[type]) |
781 | 0 | ospf->redist[type] = list_new(); |
782 | |
|
783 | 0 | red_list = ospf->redist[type]; |
784 | 0 | red = XCALLOC(MTYPE_OSPF_REDISTRIBUTE, sizeof(struct ospf_redist)); |
785 | 0 | red->instance = instance; |
786 | 0 | red->dmetric.type = -1; |
787 | 0 | red->dmetric.value = -1; |
788 | 0 | ROUTEMAP_NAME(red) = NULL; |
789 | 0 | ROUTEMAP(red) = NULL; |
790 | |
|
791 | 0 | listnode_add(red_list, red); |
792 | |
|
793 | 0 | return red; |
794 | 0 | } |
795 | | |
796 | | void ospf_redist_del(struct ospf *ospf, uint8_t type, unsigned short instance) |
797 | 0 | { |
798 | 0 | struct ospf_redist *red; |
799 | |
|
800 | 0 | red = ospf_redist_lookup(ospf, type, instance); |
801 | |
|
802 | 0 | if (red) { |
803 | 0 | listnode_delete(ospf->redist[type], red); |
804 | 0 | if (!ospf->redist[type]->count) { |
805 | 0 | list_delete(&ospf->redist[type]); |
806 | 0 | } |
807 | 0 | ospf_routemap_unset(red); |
808 | 0 | XFREE(MTYPE_OSPF_REDISTRIBUTE, red); |
809 | 0 | } |
810 | 0 | } |
811 | | |
812 | | |
813 | | int ospf_is_type_redistributed(struct ospf *ospf, int type, |
814 | | unsigned short instance) |
815 | 0 | { |
816 | 0 | return (DEFAULT_ROUTE_TYPE(type) |
817 | 0 | ? vrf_bitmap_check(zclient->default_information[AFI_IP], |
818 | 0 | ospf->vrf_id) |
819 | 0 | : ((instance |
820 | 0 | && redist_check_instance( |
821 | 0 | &zclient->mi_redist[AFI_IP][type], |
822 | 0 | instance)) |
823 | 0 | || (!instance |
824 | 0 | && vrf_bitmap_check( |
825 | 0 | zclient->redist[AFI_IP][type], |
826 | 0 | ospf->vrf_id)))); |
827 | 0 | } |
828 | | |
829 | | int ospf_redistribute_update(struct ospf *ospf, struct ospf_redist *red, |
830 | | int type, unsigned short instance, int mtype, |
831 | | int mvalue) |
832 | 0 | { |
833 | 0 | int force = 0; |
834 | |
|
835 | 0 | if (mtype != red->dmetric.type) { |
836 | 0 | red->dmetric.type = mtype; |
837 | 0 | force = LSA_REFRESH_FORCE; |
838 | 0 | } |
839 | 0 | if (mvalue != red->dmetric.value) { |
840 | 0 | red->dmetric.value = mvalue; |
841 | 0 | force = LSA_REFRESH_FORCE; |
842 | 0 | } |
843 | |
|
844 | 0 | ospf_external_lsa_refresh_type(ospf, type, instance, force); |
845 | |
|
846 | 0 | if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) |
847 | 0 | zlog_debug( |
848 | 0 | "Redistribute[%s][%d]: Refresh Type[%d], Metric[%d]", |
849 | 0 | ospf_redist_string(type), instance, |
850 | 0 | metric_type(ospf, type, instance), |
851 | 0 | metric_value(ospf, type, instance)); |
852 | |
|
853 | 0 | return CMD_SUCCESS; |
854 | 0 | } |
855 | | |
856 | | int ospf_redistribute_set(struct ospf *ospf, struct ospf_redist *red, int type, |
857 | | unsigned short instance, int mtype, int mvalue) |
858 | 0 | { |
859 | 0 | red->dmetric.type = mtype; |
860 | 0 | red->dmetric.value = mvalue; |
861 | |
|
862 | 0 | ospf_external_add(ospf, type, instance); |
863 | |
|
864 | 0 | zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, type, |
865 | 0 | instance, ospf->vrf_id); |
866 | |
|
867 | 0 | if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) |
868 | 0 | zlog_debug( |
869 | 0 | "Redistribute[%s][%d] vrf id %u: Start Type[%d], Metric[%d]", |
870 | 0 | ospf_redist_string(type), instance, ospf->vrf_id, |
871 | 0 | metric_type(ospf, type, instance), |
872 | 0 | metric_value(ospf, type, instance)); |
873 | |
|
874 | 0 | ospf_asbr_status_update(ospf, ++ospf->redistribute); |
875 | |
|
876 | 0 | return CMD_SUCCESS; |
877 | 0 | } |
878 | | |
879 | | int ospf_redistribute_unset(struct ospf *ospf, int type, |
880 | | unsigned short instance) |
881 | 0 | { |
882 | 0 | if (type == zclient->redist_default && instance == zclient->instance) |
883 | 0 | return CMD_SUCCESS; |
884 | | |
885 | 0 | zclient_redistribute(ZEBRA_REDISTRIBUTE_DELETE, zclient, AFI_IP, type, |
886 | 0 | instance, ospf->vrf_id); |
887 | |
|
888 | 0 | if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) |
889 | 0 | zlog_debug("Redistribute[%s][%d] vrf id %u: Stop", |
890 | 0 | ospf_redist_string(type), instance, ospf->vrf_id); |
891 | | |
892 | | /* Remove the routes from OSPF table. */ |
893 | 0 | ospf_redistribute_withdraw(ospf, type, instance); |
894 | |
|
895 | 0 | ospf_external_del(ospf, type, instance); |
896 | |
|
897 | 0 | ospf_asbr_status_update(ospf, --ospf->redistribute); |
898 | |
|
899 | 0 | return CMD_SUCCESS; |
900 | 0 | } |
901 | | |
902 | | int ospf_redistribute_default_set(struct ospf *ospf, int originate, int mtype, |
903 | | int mvalue) |
904 | 0 | { |
905 | 0 | struct prefix_ipv4 p; |
906 | 0 | struct in_addr nexthop; |
907 | 0 | int cur_originate = ospf->default_originate; |
908 | 0 | const char *type_str = NULL; |
909 | |
|
910 | 0 | nexthop.s_addr = INADDR_ANY; |
911 | 0 | p.family = AF_INET; |
912 | 0 | p.prefix.s_addr = INADDR_ANY; |
913 | 0 | p.prefixlen = 0; |
914 | |
|
915 | 0 | ospf->default_originate = originate; |
916 | |
|
917 | 0 | if (cur_originate == originate) { |
918 | | /* Refresh the lsa since metric might different */ |
919 | 0 | if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) |
920 | 0 | zlog_debug( |
921 | 0 | "Redistribute[%s]: Refresh Type[%d], Metric[%d]", |
922 | 0 | ospf_redist_string(DEFAULT_ROUTE), |
923 | 0 | metric_type(ospf, DEFAULT_ROUTE, 0), |
924 | 0 | metric_value(ospf, DEFAULT_ROUTE, 0)); |
925 | |
|
926 | 0 | ospf_external_lsa_refresh_default(ospf); |
927 | 0 | return CMD_SUCCESS; |
928 | 0 | } |
929 | | |
930 | 0 | switch (cur_originate) { |
931 | 0 | case DEFAULT_ORIGINATE_NONE: |
932 | 0 | break; |
933 | 0 | case DEFAULT_ORIGINATE_ZEBRA: |
934 | 0 | zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, |
935 | 0 | zclient, AFI_IP, ospf->vrf_id); |
936 | 0 | ospf->redistribute--; |
937 | 0 | break; |
938 | 0 | case DEFAULT_ORIGINATE_ALWAYS: |
939 | 0 | ospf_external_info_delete(ospf, DEFAULT_ROUTE, 0, p); |
940 | 0 | ospf_external_del(ospf, DEFAULT_ROUTE, 0); |
941 | 0 | ospf->redistribute--; |
942 | 0 | break; |
943 | 0 | } |
944 | | |
945 | 0 | switch (originate) { |
946 | 0 | case DEFAULT_ORIGINATE_NONE: |
947 | 0 | type_str = "none"; |
948 | 0 | break; |
949 | 0 | case DEFAULT_ORIGINATE_ZEBRA: |
950 | 0 | type_str = "normal"; |
951 | 0 | ospf->redistribute++; |
952 | 0 | zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD, |
953 | 0 | zclient, AFI_IP, ospf->vrf_id); |
954 | 0 | break; |
955 | 0 | case DEFAULT_ORIGINATE_ALWAYS: |
956 | 0 | type_str = "always"; |
957 | 0 | ospf->redistribute++; |
958 | 0 | ospf_external_add(ospf, DEFAULT_ROUTE, 0); |
959 | 0 | ospf_external_info_add(ospf, DEFAULT_ROUTE, 0, p, 0, nexthop, 0, |
960 | 0 | DEFAULT_DEFAULT_METRIC); |
961 | 0 | break; |
962 | 0 | } |
963 | | |
964 | 0 | if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) |
965 | 0 | zlog_debug("Redistribute[DEFAULT]: %s Type[%d], Metric[%d]", |
966 | 0 | type_str, |
967 | 0 | metric_type(ospf, DEFAULT_ROUTE, 0), |
968 | 0 | metric_value(ospf, DEFAULT_ROUTE, 0)); |
969 | |
|
970 | 0 | ospf_external_lsa_refresh_default(ospf); |
971 | 0 | ospf_asbr_status_update(ospf, ospf->redistribute); |
972 | 0 | return CMD_SUCCESS; |
973 | 0 | } |
974 | | |
975 | | static int ospf_external_lsa_originate_check(struct ospf *ospf, |
976 | | struct external_info *ei) |
977 | 0 | { |
978 | | /* If prefix is multicast, then do not originate LSA. */ |
979 | 0 | if (IN_MULTICAST(htonl(ei->p.prefix.s_addr))) { |
980 | 0 | zlog_info( |
981 | 0 | "LSA[Type5:%pI4]: Not originate AS-external-LSA, Prefix belongs multicast", |
982 | 0 | &ei->p.prefix); |
983 | 0 | return 0; |
984 | 0 | } |
985 | | |
986 | | /* Take care of default-originate. */ |
987 | 0 | if (is_default_prefix4(&ei->p)) |
988 | 0 | if (ospf->default_originate == DEFAULT_ORIGINATE_NONE) { |
989 | 0 | zlog_info( |
990 | 0 | "LSA[Type5:0.0.0.0]: Not originate AS-external-LSA for default"); |
991 | 0 | return 0; |
992 | 0 | } |
993 | | |
994 | 0 | return 1; |
995 | 0 | } |
996 | | |
997 | | /* If connected prefix is OSPF enable interface, then do not announce. */ |
998 | | int ospf_distribute_check_connected(struct ospf *ospf, struct external_info *ei) |
999 | 0 | { |
1000 | 0 | struct listnode *node; |
1001 | 0 | struct ospf_interface *oi; |
1002 | | |
1003 | |
|
1004 | 0 | for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) |
1005 | 0 | if (prefix_match(oi->address, (struct prefix *)&ei->p)) |
1006 | 0 | return 0; |
1007 | 0 | return 1; |
1008 | 0 | } |
1009 | | |
1010 | | |
1011 | | /* Apply default route-map on ei received. */ |
1012 | | int ospf_external_info_apply_default_routemap(struct ospf *ospf, |
1013 | | struct external_info *ei, |
1014 | | struct external_info *default_ei) |
1015 | 0 | { |
1016 | 0 | struct ospf_redist *red; |
1017 | 0 | int type = default_ei->type; |
1018 | 0 | struct prefix_ipv4 *p = &ei->p; |
1019 | 0 | struct route_map_set_values save_values; |
1020 | | |
1021 | |
|
1022 | 0 | if (!ospf_external_lsa_originate_check(ospf, default_ei)) |
1023 | 0 | return 0; |
1024 | | |
1025 | 0 | save_values = default_ei->route_map_set; |
1026 | 0 | ospf_reset_route_map_set_values(&default_ei->route_map_set); |
1027 | | |
1028 | | /* apply route-map if needed */ |
1029 | 0 | red = ospf_redist_lookup(ospf, type, ospf->instance); |
1030 | 0 | if (red && ROUTEMAP_NAME(red)) { |
1031 | 0 | route_map_result_t ret; |
1032 | |
|
1033 | 0 | ret = route_map_apply(ROUTEMAP(red), (struct prefix *)p, ei); |
1034 | |
|
1035 | 0 | if (ret == RMAP_DENYMATCH) { |
1036 | 0 | ei->route_map_set = save_values; |
1037 | 0 | return 0; |
1038 | 0 | } |
1039 | 0 | } |
1040 | | |
1041 | 0 | return 1; |
1042 | 0 | } |
1043 | | |
1044 | | |
1045 | | /* |
1046 | | * Default originated is based on route-map condition then |
1047 | | * apply route-map on received external info. Originate or |
1048 | | * flush based on route-map condition. |
1049 | | */ |
1050 | | static bool ospf_external_lsa_default_routemap_apply(struct ospf *ospf, |
1051 | | struct external_info *ei, |
1052 | | int cmd) |
1053 | 0 | { |
1054 | 0 | struct external_info *default_ei; |
1055 | 0 | struct prefix_ipv4 p; |
1056 | 0 | struct ospf_lsa *lsa; |
1057 | 0 | int ret; |
1058 | |
|
1059 | 0 | p.family = AF_INET; |
1060 | 0 | p.prefixlen = 0; |
1061 | 0 | p.prefix.s_addr = INADDR_ANY; |
1062 | | |
1063 | | |
1064 | | /* Get the default extenal info. */ |
1065 | 0 | default_ei = ospf_external_info_lookup(ospf, DEFAULT_ROUTE, |
1066 | 0 | ospf->instance, &p); |
1067 | 0 | if (!default_ei) { |
1068 | | /* Nothing to be done here. */ |
1069 | 0 | return false; |
1070 | 0 | } |
1071 | | |
1072 | 0 | if (IS_DEBUG_OSPF_DEFAULT_INFO) |
1073 | 0 | zlog_debug("Apply default originate routemap on ei: %pI4 cmd: %d", |
1074 | 0 | &ei->p.prefix, cmd); |
1075 | |
|
1076 | 0 | ret = ospf_external_info_apply_default_routemap(ospf, ei, default_ei); |
1077 | | |
1078 | | /* If deny then nothing to be done both in add and del case. */ |
1079 | 0 | if (!ret) { |
1080 | 0 | if (IS_DEBUG_OSPF_DEFAULT_INFO) |
1081 | 0 | zlog_debug("Default originte routemap deny for ei: %pI4", |
1082 | 0 | &ei->p.prefix); |
1083 | 0 | return false; |
1084 | 0 | } |
1085 | | |
1086 | | /* Get the default LSA. */ |
1087 | 0 | lsa = ospf_external_info_find_lsa(ospf, &p); |
1088 | | |
1089 | | /* If this is add route and permit then ooriginate default. */ |
1090 | 0 | if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD) { |
1091 | | /* If permit and default already advertise then return. */ |
1092 | 0 | if (lsa && !IS_LSA_MAXAGE(lsa)) { |
1093 | 0 | if (IS_DEBUG_OSPF_DEFAULT_INFO) |
1094 | 0 | zlog_debug("Default lsa already originated"); |
1095 | 0 | return true; |
1096 | 0 | } |
1097 | | |
1098 | 0 | if (IS_DEBUG_OSPF_DEFAULT_INFO) |
1099 | 0 | zlog_debug("Originating/Refreshing default lsa"); |
1100 | |
|
1101 | 0 | if (lsa && IS_LSA_MAXAGE(lsa)) |
1102 | | /* Refresh lsa.*/ |
1103 | 0 | ospf_external_lsa_refresh(ospf, lsa, default_ei, true, |
1104 | 0 | false); |
1105 | 0 | else |
1106 | | /* If permit and default not advertised then advertise. |
1107 | | */ |
1108 | 0 | ospf_external_lsa_originate(ospf, default_ei); |
1109 | |
|
1110 | 0 | } else if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_DEL) { |
1111 | | /* If deny and lsa is not originated then nothing to be done.*/ |
1112 | 0 | if (!lsa) { |
1113 | 0 | if (IS_DEBUG_OSPF_DEFAULT_INFO) |
1114 | 0 | zlog_debug( |
1115 | 0 | "Default lsa not originated, not flushing"); |
1116 | 0 | return true; |
1117 | 0 | } |
1118 | | |
1119 | 0 | if (IS_DEBUG_OSPF_DEFAULT_INFO) |
1120 | 0 | zlog_debug( |
1121 | 0 | "Running default route-map again as ei: %pI4 deleted", |
1122 | 0 | &ei->p.prefix); |
1123 | | /* |
1124 | | * if this route delete was permitted then we need to check |
1125 | | * there are any other external info which can still trigger |
1126 | | * default route origination else flush it. |
1127 | | */ |
1128 | 0 | event_add_event(master, |
1129 | 0 | ospf_external_lsa_default_routemap_timer, ospf, |
1130 | 0 | 0, &ospf->t_default_routemap_timer); |
1131 | 0 | } |
1132 | | |
1133 | 0 | return true; |
1134 | 0 | } |
1135 | | |
1136 | | /* return 1 if external LSA must be originated, 0 otherwise */ |
1137 | | int ospf_redistribute_check(struct ospf *ospf, struct external_info *ei, |
1138 | | int *changed) |
1139 | 0 | { |
1140 | 0 | struct route_map_set_values save_values; |
1141 | 0 | struct prefix_ipv4 *p = &ei->p; |
1142 | 0 | struct ospf_redist *red; |
1143 | 0 | uint8_t type = is_default_prefix4(&ei->p) ? DEFAULT_ROUTE : ei->type; |
1144 | 0 | unsigned short instance = is_default_prefix4(&ei->p) ? 0 : ei->instance; |
1145 | 0 | route_tag_t saved_tag = 0; |
1146 | | |
1147 | | /* Default is handled differently. */ |
1148 | 0 | if (type == DEFAULT_ROUTE) |
1149 | 0 | return 1; |
1150 | | |
1151 | 0 | if (changed) |
1152 | 0 | *changed = 0; |
1153 | |
|
1154 | 0 | if (!ospf_external_lsa_originate_check(ospf, ei)) |
1155 | 0 | return 0; |
1156 | | |
1157 | | /* Take care connected route. */ |
1158 | 0 | if (type == ZEBRA_ROUTE_CONNECT |
1159 | 0 | && !ospf_distribute_check_connected(ospf, ei)) |
1160 | 0 | return 0; |
1161 | | |
1162 | 0 | if (!DEFAULT_ROUTE_TYPE(type) && DISTRIBUTE_NAME(ospf, type)) |
1163 | | /* distirbute-list exists, but access-list may not? */ |
1164 | 0 | if (DISTRIBUTE_LIST(ospf, type)) |
1165 | 0 | if (access_list_apply(DISTRIBUTE_LIST(ospf, type), p) |
1166 | 0 | == FILTER_DENY) { |
1167 | 0 | if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) |
1168 | 0 | zlog_debug( |
1169 | 0 | "Redistribute[%s]: %pFX filtered by distribute-list.", |
1170 | 0 | ospf_redist_string(type), p); |
1171 | 0 | return 0; |
1172 | 0 | } |
1173 | | |
1174 | 0 | save_values = ei->route_map_set; |
1175 | 0 | ospf_reset_route_map_set_values(&ei->route_map_set); |
1176 | |
|
1177 | 0 | saved_tag = ei->tag; |
1178 | | /* Resetting with original route tag */ |
1179 | 0 | ei->tag = ei->orig_tag; |
1180 | | |
1181 | | /* apply route-map if needed */ |
1182 | 0 | red = ospf_redist_lookup(ospf, type, instance); |
1183 | 0 | if (red && ROUTEMAP_NAME(red)) { |
1184 | 0 | route_map_result_t ret; |
1185 | |
|
1186 | 0 | ret = route_map_apply(ROUTEMAP(red), (struct prefix *)p, ei); |
1187 | |
|
1188 | 0 | if (ret == RMAP_DENYMATCH) { |
1189 | 0 | ei->route_map_set = save_values; |
1190 | 0 | if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) |
1191 | 0 | zlog_debug( |
1192 | 0 | "Redistribute[%s]: %pFX filtered by route-map.", |
1193 | 0 | ospf_redist_string(type), p); |
1194 | 0 | return 0; |
1195 | 0 | } |
1196 | | |
1197 | | /* check if 'route-map set' changed something */ |
1198 | 0 | if (changed) { |
1199 | 0 | *changed = !ospf_route_map_set_compare( |
1200 | 0 | &ei->route_map_set, &save_values); |
1201 | | |
1202 | | /* check if tag is modified */ |
1203 | 0 | *changed |= (saved_tag != ei->tag); |
1204 | 0 | } |
1205 | 0 | } |
1206 | | |
1207 | 0 | return 1; |
1208 | 0 | } |
1209 | | |
1210 | | /* OSPF route-map set for redistribution */ |
1211 | | void ospf_routemap_set(struct ospf_redist *red, const char *name) |
1212 | 0 | { |
1213 | 0 | if (ROUTEMAP_NAME(red)) { |
1214 | 0 | route_map_counter_decrement(ROUTEMAP(red)); |
1215 | 0 | free(ROUTEMAP_NAME(red)); |
1216 | 0 | } |
1217 | |
|
1218 | 0 | ROUTEMAP_NAME(red) = strdup(name); |
1219 | 0 | ROUTEMAP(red) = route_map_lookup_by_name(name); |
1220 | 0 | route_map_counter_increment(ROUTEMAP(red)); |
1221 | 0 | } |
1222 | | |
1223 | | void ospf_routemap_unset(struct ospf_redist *red) |
1224 | 0 | { |
1225 | 0 | if (ROUTEMAP_NAME(red)) { |
1226 | 0 | route_map_counter_decrement(ROUTEMAP(red)); |
1227 | 0 | free(ROUTEMAP_NAME(red)); |
1228 | 0 | } |
1229 | |
|
1230 | 0 | ROUTEMAP_NAME(red) = NULL; |
1231 | 0 | ROUTEMAP(red) = NULL; |
1232 | 0 | } |
1233 | | |
1234 | | static int ospf_zebra_gr_update(struct ospf *ospf, int command, |
1235 | | uint32_t stale_time) |
1236 | 0 | { |
1237 | 0 | struct zapi_cap api; |
1238 | |
|
1239 | 0 | if (!zclient || zclient->sock < 0 || !ospf) |
1240 | 0 | return 1; |
1241 | | |
1242 | 0 | memset(&api, 0, sizeof(api)); |
1243 | 0 | api.cap = command; |
1244 | 0 | api.stale_removal_time = stale_time; |
1245 | 0 | api.vrf_id = ospf->vrf_id; |
1246 | |
|
1247 | 0 | (void)zclient_capabilities_send(ZEBRA_CLIENT_CAPABILITIES, zclient, |
1248 | 0 | &api); |
1249 | |
|
1250 | 0 | return 0; |
1251 | 0 | } |
1252 | | |
1253 | | int ospf_zebra_gr_enable(struct ospf *ospf, uint32_t stale_time) |
1254 | 0 | { |
1255 | 0 | if (IS_DEBUG_OSPF_GR) |
1256 | 0 | zlog_debug("Zebra enable GR [stale time %u]", stale_time); |
1257 | |
|
1258 | 0 | return ospf_zebra_gr_update(ospf, ZEBRA_CLIENT_GR_CAPABILITIES, |
1259 | 0 | stale_time); |
1260 | 0 | } |
1261 | | |
1262 | | int ospf_zebra_gr_disable(struct ospf *ospf) |
1263 | 0 | { |
1264 | 0 | if (IS_DEBUG_OSPF_GR) |
1265 | 0 | zlog_debug("Zebra disable GR"); |
1266 | |
|
1267 | 0 | return ospf_zebra_gr_update(ospf, ZEBRA_CLIENT_GR_DISABLE, 0); |
1268 | 0 | } |
1269 | | |
1270 | | /* Zebra route add and delete treatment. */ |
1271 | | static int ospf_zebra_read_route(ZAPI_CALLBACK_ARGS) |
1272 | 0 | { |
1273 | 0 | struct zapi_route api; |
1274 | 0 | struct prefix_ipv4 p; |
1275 | 0 | struct prefix pgen; |
1276 | 0 | unsigned long ifindex; |
1277 | 0 | struct in_addr nexthop; |
1278 | 0 | struct external_info *ei; |
1279 | 0 | struct ospf *ospf; |
1280 | 0 | int i; |
1281 | 0 | uint8_t rt_type; |
1282 | |
|
1283 | 0 | ospf = ospf_lookup_by_vrf_id(vrf_id); |
1284 | 0 | if (ospf == NULL) |
1285 | 0 | return 0; |
1286 | | |
1287 | 0 | if (zapi_route_decode(zclient->ibuf, &api) < 0) |
1288 | 0 | return -1; |
1289 | | |
1290 | 0 | ifindex = api.nexthops[0].ifindex; |
1291 | 0 | nexthop = api.nexthops[0].gate.ipv4; |
1292 | 0 | rt_type = api.type; |
1293 | |
|
1294 | 0 | memcpy(&p, &api.prefix, sizeof(p)); |
1295 | 0 | if (IPV4_NET127(ntohl(p.prefix.s_addr))) |
1296 | 0 | return 0; |
1297 | | |
1298 | 0 | pgen.family = p.family; |
1299 | 0 | pgen.prefixlen = p.prefixlen; |
1300 | 0 | pgen.u.prefix4 = p.prefix; |
1301 | | |
1302 | | /* Re-destributed route is default route. |
1303 | | * Here, route type is used as 'ZEBRA_ROUTE_KERNEL' for |
1304 | | * updating ex-info. But in resetting (no default-info |
1305 | | * originate)ZEBRA_ROUTE_MAX is used to delete the ex-info. |
1306 | | * Resolved this inconsistency by maintaining same route type. |
1307 | | */ |
1308 | 0 | if ((is_default_prefix(&pgen)) && (api.type != ZEBRA_ROUTE_OSPF)) |
1309 | 0 | rt_type = DEFAULT_ROUTE; |
1310 | |
|
1311 | 0 | if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) |
1312 | 0 | zlog_debug( |
1313 | 0 | "%s: cmd %s from client %s: vrf_id %d, p %pFX, metric %d", |
1314 | 0 | __func__, zserv_command_string(cmd), |
1315 | 0 | zebra_route_string(api.type), vrf_id, &api.prefix, |
1316 | 0 | api.metric); |
1317 | |
|
1318 | 0 | if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD) { |
1319 | | /* XXX|HACK|TODO|FIXME: |
1320 | | * Maybe we should ignore reject/blackhole routes? Testing |
1321 | | * shows that there is no problems though and this is only way |
1322 | | * to "summarize" routes in ASBR at the moment. Maybe we need |
1323 | | * just a better generalised solution for these types? |
1324 | | */ |
1325 | | |
1326 | | /* Protocol tag overwrites all other tag value sent by zebra */ |
1327 | 0 | if (ospf->dtag[rt_type] > 0) |
1328 | 0 | api.tag = ospf->dtag[rt_type]; |
1329 | | |
1330 | | /* |
1331 | | * Given zebra sends update for a prefix via ADD message, it |
1332 | | * should |
1333 | | * be considered as an implicit DEL for that prefix with other |
1334 | | * source |
1335 | | * types. |
1336 | | */ |
1337 | 0 | for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) |
1338 | 0 | if (i != rt_type) |
1339 | 0 | ospf_external_info_delete(ospf, i, api.instance, |
1340 | 0 | p); |
1341 | |
|
1342 | 0 | ei = ospf_external_info_add(ospf, rt_type, api.instance, p, |
1343 | 0 | ifindex, nexthop, api.tag, |
1344 | 0 | api.metric); |
1345 | 0 | if (ei == NULL) { |
1346 | | /* Nothing has changed, so nothing to do; return */ |
1347 | 0 | return 0; |
1348 | 0 | } |
1349 | 0 | if (ospf->router_id.s_addr != INADDR_ANY) { |
1350 | 0 | if (is_default_prefix4(&p)) |
1351 | 0 | ospf_external_lsa_refresh_default(ospf); |
1352 | 0 | else { |
1353 | 0 | struct ospf_external_aggr_rt *aggr; |
1354 | 0 | struct as_external_lsa *al; |
1355 | 0 | struct ospf_lsa *lsa = NULL; |
1356 | 0 | struct in_addr mask; |
1357 | |
|
1358 | 0 | aggr = ospf_external_aggr_match(ospf, &ei->p); |
1359 | |
|
1360 | 0 | if (aggr) { |
1361 | | /* Check the AS-external-LSA |
1362 | | * should be originated. |
1363 | | */ |
1364 | 0 | if (!ospf_redistribute_check(ospf, ei, |
1365 | 0 | NULL)) |
1366 | 0 | return 0; |
1367 | | |
1368 | 0 | if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR)) |
1369 | 0 | zlog_debug( |
1370 | 0 | "%s: Send Aggreate LSA (%pI4/%d)", |
1371 | 0 | __func__, |
1372 | 0 | &aggr->p.prefix, |
1373 | 0 | aggr->p.prefixlen); |
1374 | |
|
1375 | 0 | ospf_originate_summary_lsa(ospf, aggr, |
1376 | 0 | ei); |
1377 | | |
1378 | | /* Handling the case where the |
1379 | | * external route prefix |
1380 | | * and aggegate prefix is same |
1381 | | * If same don't flush the |
1382 | | * originated |
1383 | | * external LSA. |
1384 | | */ |
1385 | 0 | if (prefix_same( |
1386 | 0 | (struct prefix *)&aggr->p, |
1387 | 0 | (struct prefix *)&ei->p)) |
1388 | 0 | return 0; |
1389 | | |
1390 | 0 | lsa = ospf_external_info_find_lsa( |
1391 | 0 | ospf, &ei->p); |
1392 | |
|
1393 | 0 | if (lsa) { |
1394 | 0 | al = (struct as_external_lsa *) |
1395 | 0 | lsa->data; |
1396 | 0 | masklen2ip(ei->p.prefixlen, |
1397 | 0 | &mask); |
1398 | |
|
1399 | 0 | if (mask.s_addr |
1400 | 0 | != al->mask.s_addr) |
1401 | 0 | return 0; |
1402 | | |
1403 | 0 | ospf_external_lsa_flush( |
1404 | 0 | ospf, ei->type, &ei->p, |
1405 | 0 | 0); |
1406 | 0 | } |
1407 | 0 | } else { |
1408 | 0 | struct ospf_lsa *current; |
1409 | |
|
1410 | 0 | current = ospf_external_info_find_lsa( |
1411 | 0 | ospf, &ei->p); |
1412 | 0 | if (!current) { |
1413 | | /* Check the |
1414 | | * AS-external-LSA |
1415 | | * should be |
1416 | | * originated. |
1417 | | */ |
1418 | 0 | if (!ospf_redistribute_check( |
1419 | 0 | ospf, ei, NULL)) |
1420 | 0 | return 0; |
1421 | | |
1422 | 0 | ospf_external_lsa_originate( |
1423 | 0 | ospf, ei); |
1424 | 0 | } else { |
1425 | 0 | if (IS_DEBUG_OSPF( |
1426 | 0 | zebra, |
1427 | 0 | ZEBRA_REDISTRIBUTE)) |
1428 | 0 | zlog_debug( |
1429 | 0 | "%s: %pI4 refreshing LSA", |
1430 | 0 | __func__, |
1431 | 0 | &p.prefix); |
1432 | 0 | ospf_external_lsa_refresh( |
1433 | 0 | ospf, current, ei, |
1434 | 0 | LSA_REFRESH_FORCE, |
1435 | 0 | false); |
1436 | 0 | } |
1437 | 0 | } |
1438 | 0 | } |
1439 | 0 | } |
1440 | | |
1441 | | /* |
1442 | | * Check if default-information originate is |
1443 | | * with some routemap prefix/access list match. |
1444 | | */ |
1445 | 0 | ospf_external_lsa_default_routemap_apply(ospf, ei, cmd); |
1446 | |
|
1447 | 0 | } else { /* if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_DEL) */ |
1448 | 0 | struct ospf_external_aggr_rt *aggr; |
1449 | |
|
1450 | 0 | ei = ospf_external_info_lookup(ospf, rt_type, api.instance, &p); |
1451 | 0 | if (ei == NULL) |
1452 | 0 | return 0; |
1453 | | |
1454 | | /* |
1455 | | * Check if default-information originate i |
1456 | | * with some routemap prefix/access list match. |
1457 | | * Apply before ei is deleted. |
1458 | | */ |
1459 | 0 | ospf_external_lsa_default_routemap_apply(ospf, ei, cmd); |
1460 | |
|
1461 | 0 | aggr = ospf_external_aggr_match(ospf, &ei->p); |
1462 | |
|
1463 | 0 | if (aggr && (ei->aggr_route == aggr)) { |
1464 | 0 | ospf_unlink_ei_from_aggr(ospf, aggr, ei); |
1465 | |
|
1466 | 0 | ospf_external_info_delete(ospf, rt_type, api.instance, |
1467 | 0 | p); |
1468 | 0 | } else { |
1469 | 0 | ospf_external_info_delete(ospf, rt_type, api.instance, |
1470 | 0 | p); |
1471 | |
|
1472 | 0 | if (is_default_prefix4(&p)) |
1473 | 0 | ospf_external_lsa_refresh_default(ospf); |
1474 | 0 | else |
1475 | 0 | ospf_external_lsa_flush(ospf, rt_type, &p, |
1476 | 0 | ifindex /*, nexthop */); |
1477 | 0 | } |
1478 | 0 | } |
1479 | | |
1480 | 0 | return 0; |
1481 | 0 | } |
1482 | | |
1483 | | void ospf_zebra_import_default_route(struct ospf *ospf, bool unreg) |
1484 | 0 | { |
1485 | 0 | struct prefix prefix = {}; |
1486 | 0 | int command; |
1487 | |
|
1488 | 0 | if (zclient->sock < 0) { |
1489 | 0 | if (IS_DEBUG_OSPF(zebra, ZEBRA)) |
1490 | 0 | zlog_debug(" Not connected to Zebra"); |
1491 | 0 | return; |
1492 | 0 | } |
1493 | | |
1494 | 0 | prefix.family = AF_INET; |
1495 | 0 | prefix.prefixlen = 0; |
1496 | |
|
1497 | 0 | if (unreg) |
1498 | 0 | command = ZEBRA_NEXTHOP_UNREGISTER; |
1499 | 0 | else |
1500 | 0 | command = ZEBRA_NEXTHOP_REGISTER; |
1501 | |
|
1502 | 0 | if (IS_DEBUG_OSPF(zebra, ZEBRA)) |
1503 | 0 | zlog_debug("%s: sending cmd %s for %pFX (vrf %u)", __func__, |
1504 | 0 | zserv_command_string(command), &prefix, |
1505 | 0 | ospf->vrf_id); |
1506 | |
|
1507 | 0 | if (zclient_send_rnh(zclient, command, &prefix, SAFI_UNICAST, false, |
1508 | 0 | true, ospf->vrf_id) == ZCLIENT_SEND_FAILURE) |
1509 | 0 | flog_err(EC_LIB_ZAPI_SOCKET, "%s: zclient_send_rnh() failed", |
1510 | 0 | __func__); |
1511 | 0 | } |
1512 | | |
1513 | | static int ospf_zebra_import_check_update(ZAPI_CALLBACK_ARGS) |
1514 | 0 | { |
1515 | 0 | struct ospf *ospf; |
1516 | 0 | struct zapi_route nhr; |
1517 | 0 | struct prefix matched; |
1518 | |
|
1519 | 0 | ospf = ospf_lookup_by_vrf_id(vrf_id); |
1520 | 0 | if (ospf == NULL || !IS_OSPF_ASBR(ospf)) |
1521 | 0 | return 0; |
1522 | | |
1523 | 0 | if (!zapi_nexthop_update_decode(zclient->ibuf, &matched, &nhr)) { |
1524 | 0 | zlog_err("%s[%u]: Failure to decode route", __func__, |
1525 | 0 | ospf->vrf_id); |
1526 | 0 | return -1; |
1527 | 0 | } |
1528 | | |
1529 | 0 | if (matched.family != AF_INET || matched.prefixlen != 0 || |
1530 | 0 | nhr.type == ZEBRA_ROUTE_OSPF) |
1531 | 0 | return 0; |
1532 | | |
1533 | 0 | ospf->nssa_default_import_check.status = !!nhr.nexthop_num; |
1534 | 0 | ospf_abr_nssa_type7_defaults(ospf); |
1535 | |
|
1536 | 0 | return 0; |
1537 | 0 | } |
1538 | | |
1539 | | int ospf_distribute_list_out_set(struct ospf *ospf, int type, const char *name) |
1540 | 0 | { |
1541 | | /* Lookup access-list for distribute-list. */ |
1542 | 0 | DISTRIBUTE_LIST(ospf, type) = access_list_lookup(AFI_IP, name); |
1543 | | |
1544 | | /* Clear previous distribute-name. */ |
1545 | 0 | if (DISTRIBUTE_NAME(ospf, type)) |
1546 | 0 | free(DISTRIBUTE_NAME(ospf, type)); |
1547 | | |
1548 | | /* Set distribute-name. */ |
1549 | 0 | DISTRIBUTE_NAME(ospf, type) = strdup(name); |
1550 | | |
1551 | | /* If access-list have been set, schedule update timer. */ |
1552 | 0 | if (DISTRIBUTE_LIST(ospf, type)) |
1553 | 0 | ospf_distribute_list_update(ospf, type, 0); |
1554 | |
|
1555 | 0 | return CMD_SUCCESS; |
1556 | 0 | } |
1557 | | |
1558 | | int ospf_distribute_list_out_unset(struct ospf *ospf, int type, |
1559 | | const char *name) |
1560 | 0 | { |
1561 | | /* Schedule update timer. */ |
1562 | 0 | if (DISTRIBUTE_LIST(ospf, type)) |
1563 | 0 | ospf_distribute_list_update(ospf, type, 0); |
1564 | | |
1565 | | /* Unset distribute-list. */ |
1566 | 0 | DISTRIBUTE_LIST(ospf, type) = NULL; |
1567 | | |
1568 | | /* Clear distribute-name. */ |
1569 | 0 | if (DISTRIBUTE_NAME(ospf, type)) |
1570 | 0 | free(DISTRIBUTE_NAME(ospf, type)); |
1571 | |
|
1572 | 0 | DISTRIBUTE_NAME(ospf, type) = NULL; |
1573 | |
|
1574 | 0 | return CMD_SUCCESS; |
1575 | 0 | } |
1576 | | |
1577 | | /* distribute-list update timer. */ |
1578 | | static void ospf_distribute_list_update_timer(struct event *thread) |
1579 | 0 | { |
1580 | 0 | struct route_node *rn; |
1581 | 0 | struct external_info *ei; |
1582 | 0 | struct route_table *rt; |
1583 | 0 | struct ospf_lsa *lsa; |
1584 | 0 | int type, default_refresh = 0; |
1585 | 0 | struct ospf *ospf = EVENT_ARG(thread); |
1586 | 0 |
|
1587 | 0 | if (ospf == NULL) |
1588 | 0 | return; |
1589 | 0 |
|
1590 | 0 | ospf->t_distribute_update = NULL; |
1591 | 0 |
|
1592 | 0 | zlog_info("Zebra[Redistribute]: distribute-list update timer fired!"); |
1593 | 0 |
|
1594 | 0 | if (IS_DEBUG_OSPF_EVENT) { |
1595 | 0 | zlog_debug("%s: ospf distribute-list update vrf %s id %d", |
1596 | 0 | __func__, ospf_vrf_id_to_name(ospf->vrf_id), |
1597 | 0 | ospf->vrf_id); |
1598 | 0 | } |
1599 | 0 |
|
1600 | 0 | /* foreach all external info. */ |
1601 | 0 | for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) { |
1602 | 0 | struct list *ext_list; |
1603 | 0 | struct listnode *node; |
1604 | 0 | struct ospf_external *ext; |
1605 | 0 |
|
1606 | 0 | ext_list = ospf->external[type]; |
1607 | 0 | if (!ext_list) |
1608 | 0 | continue; |
1609 | 0 |
|
1610 | 0 | for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) { |
1611 | 0 | rt = ext->external_info; |
1612 | 0 | if (!rt) |
1613 | 0 | continue; |
1614 | 0 | for (rn = route_top(rt); rn; rn = route_next(rn)) { |
1615 | 0 | ei = rn->info; |
1616 | 0 | if (!ei) |
1617 | 0 | continue; |
1618 | 0 |
|
1619 | 0 | if (is_default_prefix4(&ei->p)) |
1620 | 0 | default_refresh = 1; |
1621 | 0 | else { |
1622 | 0 | struct ospf_external_aggr_rt *aggr; |
1623 | 0 |
|
1624 | 0 | aggr = ospf_external_aggr_match(ospf, |
1625 | 0 | &ei->p); |
1626 | 0 | if (aggr) { |
1627 | 0 | /* Check the |
1628 | 0 | * AS-external-LSA |
1629 | 0 | * should be originated. |
1630 | 0 | */ |
1631 | 0 | if (!ospf_redistribute_check( |
1632 | 0 | ospf, ei, NULL)) { |
1633 | 0 |
|
1634 | 0 | ospf_unlink_ei_from_aggr( |
1635 | 0 | ospf, aggr, ei); |
1636 | 0 | continue; |
1637 | 0 | } |
1638 | 0 |
|
1639 | 0 | if (IS_DEBUG_OSPF( |
1640 | 0 | lsa, |
1641 | 0 | EXTNL_LSA_AGGR)) |
1642 | 0 | zlog_debug( |
1643 | 0 | "%s: Send Aggregate LSA (%pI4/%d)", |
1644 | 0 | __func__, |
1645 | 0 | &aggr->p.prefix, |
1646 | 0 | aggr->p.prefixlen); |
1647 | 0 |
|
1648 | 0 | /* Originate Aggregate |
1649 | 0 | * LSA |
1650 | 0 | */ |
1651 | 0 | ospf_originate_summary_lsa( |
1652 | 0 | ospf, aggr, ei); |
1653 | 0 | } else if ( |
1654 | 0 | (lsa = ospf_external_info_find_lsa( |
1655 | 0 | ospf, &ei->p))) { |
1656 | 0 | int force = |
1657 | 0 | LSA_REFRESH_IF_CHANGED; |
1658 | 0 | /* If this is a MaxAge |
1659 | 0 | * LSA, we need to |
1660 | 0 | * force refresh it |
1661 | 0 | * because distribute |
1662 | 0 | * settings might have |
1663 | 0 | * changed and now, |
1664 | 0 | * this LSA needs to be |
1665 | 0 | * originated, not be |
1666 | 0 | * removed. |
1667 | 0 | * If we don't force |
1668 | 0 | * refresh it, it will |
1669 | 0 | * remain a MaxAge LSA |
1670 | 0 | * because it will look |
1671 | 0 | * like it hasn't |
1672 | 0 | * changed. Neighbors |
1673 | 0 | * will not receive |
1674 | 0 | * updates for this LSA. |
1675 | 0 | */ |
1676 | 0 | if (IS_LSA_MAXAGE(lsa)) |
1677 | 0 | force = LSA_REFRESH_FORCE; |
1678 | 0 |
|
1679 | 0 | ospf_external_lsa_refresh( |
1680 | 0 | ospf, lsa, ei, force, |
1681 | 0 | false); |
1682 | 0 | } else { |
1683 | 0 | if (!ospf_redistribute_check( |
1684 | 0 | ospf, ei, NULL)) |
1685 | 0 | continue; |
1686 | 0 | ospf_external_lsa_originate( |
1687 | 0 | ospf, ei); |
1688 | 0 | } |
1689 | 0 | } |
1690 | 0 | } |
1691 | 0 | } |
1692 | 0 | } |
1693 | 0 | if (default_refresh) |
1694 | 0 | ospf_external_lsa_refresh_default(ospf); |
1695 | 0 | } |
1696 | | |
1697 | | /* Update distribute-list and set timer to apply access-list. */ |
1698 | | void ospf_distribute_list_update(struct ospf *ospf, int type, |
1699 | | unsigned short instance) |
1700 | 0 | { |
1701 | 0 | struct ospf_external *ext; |
1702 | | |
1703 | | /* External info does not exist. */ |
1704 | 0 | ext = ospf_external_lookup(ospf, type, instance); |
1705 | 0 | if (!ext || !EXTERNAL_INFO(ext)) |
1706 | 0 | return; |
1707 | | |
1708 | | /* Set timer. If timer is already started, this call does nothing. */ |
1709 | 0 | event_add_timer_msec(master, ospf_distribute_list_update_timer, ospf, |
1710 | 0 | ospf->min_ls_interval, &ospf->t_distribute_update); |
1711 | 0 | } |
1712 | | |
1713 | | /* If access-list is updated, apply some check. */ |
1714 | | static void ospf_filter_update(struct access_list *access) |
1715 | 0 | { |
1716 | 0 | struct ospf *ospf; |
1717 | 0 | int type; |
1718 | 0 | int abr_inv = 0; |
1719 | 0 | struct ospf_area *area; |
1720 | 0 | struct listnode *node, *n1; |
1721 | | |
1722 | | /* If OSPF instance does not exist, return right now. */ |
1723 | 0 | if (listcount(om->ospf) == 0) |
1724 | 0 | return; |
1725 | | |
1726 | | /* Iterate all ospf [VRF] instances */ |
1727 | 0 | for (ALL_LIST_ELEMENTS_RO(om->ospf, n1, ospf)) { |
1728 | | /* Update distribute-list, and apply filter. */ |
1729 | 0 | for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) { |
1730 | 0 | struct list *red_list; |
1731 | 0 | struct ospf_redist *red; |
1732 | |
|
1733 | 0 | red_list = ospf->redist[type]; |
1734 | 0 | if (red_list) |
1735 | 0 | for (ALL_LIST_ELEMENTS_RO(red_list, node, |
1736 | 0 | red)) { |
1737 | 0 | if (ROUTEMAP(red)) { |
1738 | | /* if route-map is not NULL it |
1739 | | * may be |
1740 | | * using this access list */ |
1741 | 0 | ospf_distribute_list_update( |
1742 | 0 | ospf, type, |
1743 | 0 | red->instance); |
1744 | 0 | } |
1745 | 0 | } |
1746 | | |
1747 | | /* There is place for route-map for default-information |
1748 | | * (ZEBRA_ROUTE_MAX), |
1749 | | * but no distribute list. */ |
1750 | 0 | if (type == ZEBRA_ROUTE_MAX) |
1751 | 0 | break; |
1752 | | |
1753 | 0 | if (DISTRIBUTE_NAME(ospf, type)) { |
1754 | | /* Keep old access-list for distribute-list. */ |
1755 | 0 | struct access_list *old = |
1756 | 0 | DISTRIBUTE_LIST(ospf, type); |
1757 | | |
1758 | | /* Update access-list for distribute-list. */ |
1759 | 0 | DISTRIBUTE_LIST(ospf, type) = |
1760 | 0 | access_list_lookup( |
1761 | 0 | AFI_IP, |
1762 | 0 | DISTRIBUTE_NAME(ospf, type)); |
1763 | | |
1764 | | /* No update for this distribute type. */ |
1765 | 0 | if (old == NULL |
1766 | 0 | && DISTRIBUTE_LIST(ospf, type) == NULL) |
1767 | 0 | continue; |
1768 | | |
1769 | | /* Schedule distribute-list update timer. */ |
1770 | 0 | if (DISTRIBUTE_LIST(ospf, type) == NULL |
1771 | 0 | || strcmp(DISTRIBUTE_NAME(ospf, type), |
1772 | 0 | access->name) |
1773 | 0 | == 0) |
1774 | 0 | ospf_distribute_list_update(ospf, type, |
1775 | 0 | 0); |
1776 | 0 | } |
1777 | 0 | } |
1778 | | |
1779 | | /* Update Area access-list. */ |
1780 | 0 | for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { |
1781 | 0 | if (EXPORT_NAME(area)) { |
1782 | 0 | EXPORT_LIST(area) = NULL; |
1783 | 0 | abr_inv++; |
1784 | 0 | } |
1785 | |
|
1786 | 0 | if (IMPORT_NAME(area)) { |
1787 | 0 | IMPORT_LIST(area) = NULL; |
1788 | 0 | abr_inv++; |
1789 | 0 | } |
1790 | 0 | } |
1791 | | |
1792 | | /* Schedule ABR tasks -- this will be changed -- takada. */ |
1793 | 0 | if (IS_OSPF_ABR(ospf) && abr_inv) |
1794 | 0 | ospf_schedule_abr_task(ospf); |
1795 | 0 | } |
1796 | 0 | } |
1797 | | |
1798 | | /* If prefix-list is updated, do some updates. */ |
1799 | | static void ospf_prefix_list_update(struct prefix_list *plist) |
1800 | 0 | { |
1801 | 0 | struct ospf *ospf = NULL; |
1802 | 0 | int type; |
1803 | 0 | int abr_inv = 0; |
1804 | 0 | struct ospf_area *area; |
1805 | 0 | struct listnode *node, *n1; |
1806 | | |
1807 | | /* If OSPF instatnce does not exist, return right now. */ |
1808 | 0 | if (listcount(om->ospf) == 0) |
1809 | 0 | return; |
1810 | | |
1811 | | /* Iterate all ospf [VRF] instances */ |
1812 | 0 | for (ALL_LIST_ELEMENTS_RO(om->ospf, n1, ospf)) { |
1813 | | |
1814 | | /* Update all route-maps which are used |
1815 | | * as redistribution filters. |
1816 | | * They might use prefix-list. |
1817 | | */ |
1818 | 0 | for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) { |
1819 | 0 | struct list *red_list; |
1820 | 0 | struct ospf_redist *red; |
1821 | |
|
1822 | 0 | red_list = ospf->redist[type]; |
1823 | 0 | if (!red_list) |
1824 | 0 | continue; |
1825 | | |
1826 | 0 | for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) { |
1827 | 0 | if (ROUTEMAP(red)) { |
1828 | | /* if route-map is not NULL |
1829 | | * it may be using |
1830 | | * this prefix list */ |
1831 | 0 | ospf_distribute_list_update( |
1832 | 0 | ospf, type, red->instance); |
1833 | 0 | } |
1834 | 0 | } |
1835 | 0 | } |
1836 | | |
1837 | | /* Update area filter-lists. */ |
1838 | 0 | for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { |
1839 | | /* Update filter-list in. */ |
1840 | 0 | if (PREFIX_NAME_IN(area) |
1841 | 0 | && strcmp(PREFIX_NAME_IN(area), |
1842 | 0 | prefix_list_name(plist)) |
1843 | 0 | == 0) { |
1844 | 0 | PREFIX_LIST_IN(area) = prefix_list_lookup( |
1845 | 0 | AFI_IP, PREFIX_NAME_IN(area)); |
1846 | 0 | abr_inv++; |
1847 | 0 | } |
1848 | | |
1849 | | /* Update filter-list out. */ |
1850 | 0 | if (PREFIX_NAME_OUT(area) |
1851 | 0 | && strcmp(PREFIX_NAME_OUT(area), |
1852 | 0 | prefix_list_name(plist)) |
1853 | 0 | == 0) { |
1854 | 0 | PREFIX_LIST_OUT(area) = prefix_list_lookup( |
1855 | 0 | AFI_IP, PREFIX_NAME_OUT(area)); |
1856 | 0 | abr_inv++; |
1857 | 0 | } |
1858 | 0 | } |
1859 | | |
1860 | | /* Schedule ABR task. */ |
1861 | 0 | if (IS_OSPF_ABR(ospf) && abr_inv) |
1862 | 0 | ospf_schedule_abr_task(ospf); |
1863 | 0 | } |
1864 | 0 | } |
1865 | | |
1866 | | static struct ospf_distance *ospf_distance_new(void) |
1867 | 0 | { |
1868 | 0 | return XCALLOC(MTYPE_OSPF_DISTANCE, sizeof(struct ospf_distance)); |
1869 | 0 | } |
1870 | | |
1871 | | static void ospf_distance_free(struct ospf_distance *odistance) |
1872 | 0 | { |
1873 | 0 | XFREE(MTYPE_OSPF_DISTANCE, odistance); |
1874 | 0 | } |
1875 | | |
1876 | | int ospf_distance_set(struct vty *vty, struct ospf *ospf, |
1877 | | const char *distance_str, const char *ip_str, |
1878 | | const char *access_list_str) |
1879 | 0 | { |
1880 | 0 | int ret; |
1881 | 0 | struct prefix_ipv4 p; |
1882 | 0 | uint8_t distance; |
1883 | 0 | struct route_node *rn; |
1884 | 0 | struct ospf_distance *odistance; |
1885 | |
|
1886 | 0 | ret = str2prefix_ipv4(ip_str, &p); |
1887 | 0 | if (ret == 0) { |
1888 | 0 | vty_out(vty, "Malformed prefix\n"); |
1889 | 0 | return CMD_WARNING_CONFIG_FAILED; |
1890 | 0 | } |
1891 | | |
1892 | 0 | distance = atoi(distance_str); |
1893 | | |
1894 | | /* Get OSPF distance node. */ |
1895 | 0 | rn = route_node_get(ospf->distance_table, (struct prefix *)&p); |
1896 | 0 | if (rn->info) { |
1897 | 0 | odistance = rn->info; |
1898 | 0 | route_unlock_node(rn); |
1899 | 0 | } else { |
1900 | 0 | odistance = ospf_distance_new(); |
1901 | 0 | rn->info = odistance; |
1902 | 0 | } |
1903 | | |
1904 | | /* Set distance value. */ |
1905 | 0 | odistance->distance = distance; |
1906 | | |
1907 | | /* Reset access-list configuration. */ |
1908 | 0 | if (odistance->access_list) { |
1909 | 0 | free(odistance->access_list); |
1910 | 0 | odistance->access_list = NULL; |
1911 | 0 | } |
1912 | 0 | if (access_list_str) |
1913 | 0 | odistance->access_list = strdup(access_list_str); |
1914 | |
|
1915 | 0 | return CMD_SUCCESS; |
1916 | 0 | } |
1917 | | |
1918 | | int ospf_distance_unset(struct vty *vty, struct ospf *ospf, |
1919 | | const char *distance_str, const char *ip_str, |
1920 | | char const *access_list_str) |
1921 | 0 | { |
1922 | 0 | int ret; |
1923 | 0 | struct prefix_ipv4 p; |
1924 | 0 | struct route_node *rn; |
1925 | 0 | struct ospf_distance *odistance; |
1926 | |
|
1927 | 0 | ret = str2prefix_ipv4(ip_str, &p); |
1928 | 0 | if (ret == 0) { |
1929 | 0 | vty_out(vty, "Malformed prefix\n"); |
1930 | 0 | return CMD_WARNING_CONFIG_FAILED; |
1931 | 0 | } |
1932 | | |
1933 | 0 | rn = route_node_lookup(ospf->distance_table, (struct prefix *)&p); |
1934 | 0 | if (!rn) { |
1935 | 0 | vty_out(vty, "Can't find specified prefix\n"); |
1936 | 0 | return CMD_WARNING_CONFIG_FAILED; |
1937 | 0 | } |
1938 | | |
1939 | 0 | odistance = rn->info; |
1940 | |
|
1941 | 0 | if (odistance->access_list) |
1942 | 0 | free(odistance->access_list); |
1943 | 0 | ospf_distance_free(odistance); |
1944 | |
|
1945 | 0 | rn->info = NULL; |
1946 | 0 | route_unlock_node(rn); |
1947 | 0 | route_unlock_node(rn); |
1948 | |
|
1949 | 0 | return CMD_SUCCESS; |
1950 | 0 | } |
1951 | | |
1952 | | void ospf_distance_reset(struct ospf *ospf) |
1953 | 0 | { |
1954 | 0 | struct route_node *rn; |
1955 | 0 | struct ospf_distance *odistance; |
1956 | |
|
1957 | 0 | for (rn = route_top(ospf->distance_table); rn; rn = route_next(rn)) { |
1958 | 0 | odistance = rn->info; |
1959 | 0 | if (!odistance) |
1960 | 0 | continue; |
1961 | | |
1962 | 0 | if (odistance->access_list) |
1963 | 0 | free(odistance->access_list); |
1964 | 0 | ospf_distance_free(odistance); |
1965 | 0 | rn->info = NULL; |
1966 | 0 | route_unlock_node(rn); |
1967 | 0 | } |
1968 | 0 | } |
1969 | | |
1970 | | uint8_t ospf_distance_apply(struct ospf *ospf, struct prefix_ipv4 *p, |
1971 | | struct ospf_route * or) |
1972 | 0 | { |
1973 | |
|
1974 | 0 | if (ospf == NULL) |
1975 | 0 | return 0; |
1976 | | |
1977 | 0 | if (ospf->distance_intra && or->path_type == OSPF_PATH_INTRA_AREA) |
1978 | 0 | return ospf->distance_intra; |
1979 | | |
1980 | 0 | if (ospf->distance_inter && or->path_type == OSPF_PATH_INTER_AREA) |
1981 | 0 | return ospf->distance_inter; |
1982 | | |
1983 | 0 | if (ospf->distance_external |
1984 | 0 | && (or->path_type == OSPF_PATH_TYPE1_EXTERNAL || |
1985 | 0 | or->path_type == OSPF_PATH_TYPE2_EXTERNAL)) |
1986 | 0 | return ospf->distance_external; |
1987 | | |
1988 | 0 | if (ospf->distance_all) |
1989 | 0 | return ospf->distance_all; |
1990 | | |
1991 | 0 | return 0; |
1992 | 0 | } |
1993 | | |
1994 | | void ospf_zebra_vrf_register(struct ospf *ospf) |
1995 | 1 | { |
1996 | 1 | if (!zclient || zclient->sock < 0 || !ospf) |
1997 | 1 | return; |
1998 | | |
1999 | 0 | if (ospf->vrf_id != VRF_UNKNOWN) { |
2000 | 0 | if (IS_DEBUG_OSPF_EVENT) |
2001 | 0 | zlog_debug("%s: Register VRF %s id %u", __func__, |
2002 | 0 | ospf_vrf_id_to_name(ospf->vrf_id), |
2003 | 0 | ospf->vrf_id); |
2004 | 0 | zclient_send_reg_requests(zclient, ospf->vrf_id); |
2005 | 0 | } |
2006 | 0 | } |
2007 | | |
2008 | | void ospf_zebra_vrf_deregister(struct ospf *ospf) |
2009 | 0 | { |
2010 | 0 | if (!zclient || zclient->sock < 0 || !ospf) |
2011 | 0 | return; |
2012 | | |
2013 | 0 | if (ospf->vrf_id != VRF_DEFAULT && ospf->vrf_id != VRF_UNKNOWN) { |
2014 | 0 | if (IS_DEBUG_OSPF_EVENT) |
2015 | 0 | zlog_debug("%s: De-Register VRF %s id %u to Zebra.", |
2016 | 0 | __func__, ospf_vrf_id_to_name(ospf->vrf_id), |
2017 | 0 | ospf->vrf_id); |
2018 | | /* Deregister for router-id, interfaces, |
2019 | | * redistributed routes. */ |
2020 | 0 | zclient_send_dereg_requests(zclient, ospf->vrf_id); |
2021 | 0 | } |
2022 | 0 | } |
2023 | | |
2024 | | /* Label Manager Functions */ |
2025 | | |
2026 | | /** |
2027 | | * Check if Label Manager is Ready or not. |
2028 | | * |
2029 | | * @return True if Label Manager is ready, False otherwise |
2030 | | */ |
2031 | | bool ospf_zebra_label_manager_ready(void) |
2032 | 0 | { |
2033 | 0 | return (zclient_sync->sock > 0); |
2034 | 0 | } |
2035 | | |
2036 | | /** |
2037 | | * Request Label Range to the Label Manager. |
2038 | | * |
2039 | | * @param base base label of the label range to request |
2040 | | * @param chunk_size size of the label range to request |
2041 | | * |
2042 | | * @return 0 on success, -1 on failure |
2043 | | */ |
2044 | | int ospf_zebra_request_label_range(uint32_t base, uint32_t chunk_size) |
2045 | 0 | { |
2046 | 0 | int ret; |
2047 | 0 | uint32_t start, end; |
2048 | |
|
2049 | 0 | if (zclient_sync->sock < 0) |
2050 | 0 | return -1; |
2051 | | |
2052 | 0 | ret = lm_get_label_chunk(zclient_sync, 0, base, chunk_size, &start, |
2053 | 0 | &end); |
2054 | 0 | if (ret < 0) { |
2055 | 0 | zlog_warn("%s: error getting label range!", __func__); |
2056 | 0 | return -1; |
2057 | 0 | } |
2058 | | |
2059 | 0 | return 0; |
2060 | 0 | } |
2061 | | |
2062 | | /** |
2063 | | * Release Label Range to the Label Manager. |
2064 | | * |
2065 | | * @param start start of label range to release |
2066 | | * @param end end of label range to release |
2067 | | * |
2068 | | * @return 0 on success, -1 otherwise |
2069 | | */ |
2070 | | int ospf_zebra_release_label_range(uint32_t start, uint32_t end) |
2071 | 0 | { |
2072 | 0 | int ret; |
2073 | |
|
2074 | 0 | if (zclient_sync->sock < 0) |
2075 | 0 | return -1; |
2076 | | |
2077 | 0 | ret = lm_release_label_chunk(zclient_sync, start, end); |
2078 | 0 | if (ret < 0) { |
2079 | 0 | zlog_warn("%s: error releasing label range!", __func__); |
2080 | 0 | return -1; |
2081 | 0 | } |
2082 | | |
2083 | 0 | return 0; |
2084 | 0 | } |
2085 | | |
2086 | | /** |
2087 | | * Connect to the Label Manager. |
2088 | | * |
2089 | | * @return 0 on success, -1 otherwise |
2090 | | */ |
2091 | | int ospf_zebra_label_manager_connect(void) |
2092 | 0 | { |
2093 | | /* Connect to label manager. */ |
2094 | 0 | if (zclient_socket_connect(zclient_sync) < 0) { |
2095 | 0 | zlog_warn("%s: failed connecting synchronous zclient!", |
2096 | 0 | __func__); |
2097 | 0 | return -1; |
2098 | 0 | } |
2099 | | /* make socket non-blocking */ |
2100 | 0 | set_nonblocking(zclient_sync->sock); |
2101 | | |
2102 | | /* Send hello to notify zebra this is a synchronous client */ |
2103 | 0 | if (zclient_send_hello(zclient_sync) == ZCLIENT_SEND_FAILURE) { |
2104 | 0 | zlog_warn("%s: failed sending hello for synchronous zclient!", |
2105 | 0 | __func__); |
2106 | 0 | close(zclient_sync->sock); |
2107 | 0 | zclient_sync->sock = -1; |
2108 | 0 | return -1; |
2109 | 0 | } |
2110 | | |
2111 | | /* Connect to label manager */ |
2112 | 0 | if (lm_label_manager_connect(zclient_sync, 0) != 0) { |
2113 | 0 | zlog_warn("%s: failed connecting to label manager!", __func__); |
2114 | 0 | if (zclient_sync->sock > 0) { |
2115 | 0 | close(zclient_sync->sock); |
2116 | 0 | zclient_sync->sock = -1; |
2117 | 0 | } |
2118 | 0 | return -1; |
2119 | 0 | } |
2120 | | |
2121 | 0 | osr_debug("SR (%s): Successfully connected to the Label Manager", |
2122 | 0 | __func__); |
2123 | |
|
2124 | 0 | return 0; |
2125 | 0 | } |
2126 | | |
2127 | | static void ospf_zebra_connected(struct zclient *zclient) |
2128 | 0 | { |
2129 | 0 | struct ospf *ospf; |
2130 | 0 | struct listnode *node; |
2131 | | |
2132 | | /* Send the client registration */ |
2133 | 0 | bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, VRF_DEFAULT); |
2134 | |
|
2135 | 0 | zclient_send_reg_requests(zclient, VRF_DEFAULT); |
2136 | | |
2137 | | /* Activate graceful restart if configured. */ |
2138 | 0 | for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { |
2139 | 0 | if (!ospf->gr_info.restart_support) |
2140 | 0 | continue; |
2141 | 0 | (void)ospf_zebra_gr_enable(ospf, ospf->gr_info.grace_period); |
2142 | 0 | } |
2143 | 0 | } |
2144 | | |
2145 | | /* |
2146 | | * opaque messages between processes |
2147 | | */ |
2148 | | static int ospf_opaque_msg_handler(ZAPI_CALLBACK_ARGS) |
2149 | 0 | { |
2150 | 0 | struct stream *s; |
2151 | 0 | struct zapi_opaque_msg info; |
2152 | 0 | struct ldp_igp_sync_if_state state; |
2153 | 0 | struct ldp_igp_sync_announce announce; |
2154 | 0 | struct zapi_opaque_reg_info dst; |
2155 | 0 | int ret = 0; |
2156 | |
|
2157 | 0 | s = zclient->ibuf; |
2158 | |
|
2159 | 0 | if (zclient_opaque_decode(s, &info) != 0) |
2160 | 0 | return -1; |
2161 | | |
2162 | 0 | switch (info.type) { |
2163 | 0 | case LINK_STATE_SYNC: |
2164 | 0 | STREAM_GETC(s, dst.proto); |
2165 | 0 | STREAM_GETW(s, dst.instance); |
2166 | 0 | STREAM_GETL(s, dst.session_id); |
2167 | 0 | dst.type = LINK_STATE_SYNC; |
2168 | 0 | ret = ospf_te_sync_ted(dst); |
2169 | 0 | break; |
2170 | 0 | case LDP_IGP_SYNC_IF_STATE_UPDATE: |
2171 | 0 | STREAM_GET(&state, s, sizeof(state)); |
2172 | 0 | ret = ospf_ldp_sync_state_update(state); |
2173 | 0 | break; |
2174 | 0 | case LDP_IGP_SYNC_ANNOUNCE_UPDATE: |
2175 | 0 | STREAM_GET(&announce, s, sizeof(announce)); |
2176 | 0 | ret = ospf_ldp_sync_announce_update(announce); |
2177 | 0 | break; |
2178 | 0 | default: |
2179 | 0 | break; |
2180 | 0 | } |
2181 | | |
2182 | 0 | stream_failure: |
2183 | |
|
2184 | 0 | return ret; |
2185 | 0 | } |
2186 | | |
2187 | | static int ospf_zebra_client_close_notify(ZAPI_CALLBACK_ARGS) |
2188 | 0 | { |
2189 | 0 | int ret = 0; |
2190 | |
|
2191 | 0 | struct zapi_client_close_info info; |
2192 | |
|
2193 | 0 | if (zapi_client_close_notify_decode(zclient->ibuf, &info) < 0) |
2194 | 0 | return -1; |
2195 | | |
2196 | 0 | ospf_ldp_sync_handle_client_close(&info); |
2197 | |
|
2198 | 0 | return ret; |
2199 | 0 | } |
2200 | | |
2201 | | static zclient_handler *const ospf_handlers[] = { |
2202 | | [ZEBRA_ROUTER_ID_UPDATE] = ospf_router_id_update_zebra, |
2203 | | [ZEBRA_INTERFACE_ADDRESS_ADD] = ospf_interface_address_add, |
2204 | | [ZEBRA_INTERFACE_ADDRESS_DELETE] = ospf_interface_address_delete, |
2205 | | [ZEBRA_INTERFACE_LINK_PARAMS] = ospf_interface_link_params, |
2206 | | [ZEBRA_INTERFACE_VRF_UPDATE] = ospf_interface_vrf_update, |
2207 | | |
2208 | | [ZEBRA_REDISTRIBUTE_ROUTE_ADD] = ospf_zebra_read_route, |
2209 | | [ZEBRA_REDISTRIBUTE_ROUTE_DEL] = ospf_zebra_read_route, |
2210 | | [ZEBRA_NEXTHOP_UPDATE] = ospf_zebra_import_check_update, |
2211 | | |
2212 | | [ZEBRA_OPAQUE_MESSAGE] = ospf_opaque_msg_handler, |
2213 | | |
2214 | | [ZEBRA_CLIENT_CLOSE_NOTIFY] = ospf_zebra_client_close_notify, |
2215 | | }; |
2216 | | |
2217 | | void ospf_zebra_init(struct event_loop *master, unsigned short instance) |
2218 | 1 | { |
2219 | | /* Allocate zebra structure. */ |
2220 | 1 | zclient = zclient_new(master, &zclient_options_default, ospf_handlers, |
2221 | 1 | array_size(ospf_handlers)); |
2222 | 1 | zclient_init(zclient, ZEBRA_ROUTE_OSPF, instance, &ospfd_privs); |
2223 | 1 | zclient->zebra_connected = ospf_zebra_connected; |
2224 | | |
2225 | | /* Initialize special zclient for synchronous message exchanges. */ |
2226 | 1 | struct zclient_options options = zclient_options_default; |
2227 | 1 | options.synchronous = true; |
2228 | 1 | zclient_sync = zclient_new(master, &options, NULL, 0); |
2229 | 1 | zclient_sync->sock = -1; |
2230 | 1 | zclient_sync->redist_default = ZEBRA_ROUTE_OSPF; |
2231 | 1 | zclient_sync->instance = instance; |
2232 | | /* |
2233 | | * session_id must be different from default value (0) to distinguish |
2234 | | * the asynchronous socket from the synchronous one |
2235 | | */ |
2236 | 1 | zclient_sync->session_id = 1; |
2237 | 1 | zclient_sync->privs = &ospfd_privs; |
2238 | | |
2239 | 1 | access_list_add_hook(ospf_filter_update); |
2240 | 1 | access_list_delete_hook(ospf_filter_update); |
2241 | 1 | prefix_list_add_hook(ospf_prefix_list_update); |
2242 | 1 | prefix_list_delete_hook(ospf_prefix_list_update); |
2243 | 1 | } |
2244 | | |
2245 | | void ospf_zebra_send_arp(const struct interface *ifp, const struct prefix *p) |
2246 | 0 | { |
2247 | 0 | zclient_send_neigh_discovery_req(zclient, ifp, p); |
2248 | 0 | } |