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