]>
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" |
718e3744 | 53 | |
dfac5d39 CS |
54 | DEFINE_MTYPE_STATIC(OSPFD, OSPF_EXTERNAL, "OSPF External route table") |
55 | DEFINE_MTYPE_STATIC(OSPFD, OSPF_REDISTRIBUTE, "OSPF Redistriute") | |
b5a8894d | 56 | DEFINE_MTYPE_STATIC(OSPFD, OSPF_DIST_ARGS, "OSPF Distribute arguments") |
dfac5d39 | 57 | |
d62a17ae | 58 | DEFINE_HOOK(ospf_if_update, (struct interface * ifp), (ifp)) |
59 | DEFINE_HOOK(ospf_if_delete, (struct interface * ifp), (ifp)) | |
3012671f | 60 | |
718e3744 | 61 | /* Zebra structure to hold current status. */ |
62 | struct zclient *zclient = NULL; | |
63 | ||
64 | /* For registering threads. */ | |
65 | extern struct thread_master *master; | |
18a6dce6 | 66 | struct in_addr router_id_zebra; |
67 | ||
68 | /* Router-id update message from zebra. */ | |
d62a17ae | 69 | static int ospf_router_id_update_zebra(int command, struct zclient *zclient, |
70 | zebra_size_t length, vrf_id_t vrf_id) | |
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 | ||
76 | if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE)) { | |
77 | char buf[PREFIX2STR_BUFFER]; | |
78 | prefix2str(&router_id, buf, sizeof(buf)); | |
b5a8894d CS |
79 | zlog_debug("Zebra rcvd: router id update %s vrf %s id %u", |
80 | buf, ospf_vrf_id_to_name(vrf_id), vrf_id); | |
d62a17ae | 81 | } |
82 | ||
83 | router_id_zebra = router_id.u.prefix4; | |
84 | ||
b5a8894d | 85 | ospf = ospf_lookup_by_vrf_id(vrf_id); |
d62a17ae | 86 | |
87 | if (ospf != NULL) | |
88 | ospf_router_id_update(ospf); | |
b5a8894d CS |
89 | else { |
90 | if (IS_DEBUG_OSPF_EVENT) { | |
91 | char buf[PREFIX2STR_BUFFER]; | |
92 | ||
93 | prefix2str(&router_id, buf, sizeof(buf)); | |
94 | zlog_debug("%s: ospf instance not found for vrf %s id %u router_id %s", | |
95 | __PRETTY_FUNCTION__, | |
96 | ospf_vrf_id_to_name(vrf_id), vrf_id, buf); | |
97 | } | |
98 | } | |
d62a17ae | 99 | return 0; |
18a6dce6 | 100 | } |
718e3744 | 101 | |
102 | /* Inteface addition message from zebra. */ | |
d62a17ae | 103 | static int ospf_interface_add(int command, struct zclient *zclient, |
104 | zebra_size_t length, vrf_id_t vrf_id) | |
718e3744 | 105 | { |
b5a8894d CS |
106 | struct interface *ifp = NULL; |
107 | struct ospf *ospf = NULL; | |
718e3744 | 108 | |
d62a17ae | 109 | ifp = zebra_interface_add_read(zclient->ibuf, vrf_id); |
43b8d1d8 CS |
110 | if (ifp == NULL) |
111 | return 0; | |
718e3744 | 112 | |
d62a17ae | 113 | if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE)) |
114 | zlog_debug( | |
b5a8894d CS |
115 | "Zebra: interface add %s vrf %s[%u] index %d flags %llx metric %d mtu %d", |
116 | ifp->name, ospf_vrf_id_to_name(ifp->vrf_id), | |
117 | ifp->vrf_id, ifp->ifindex, | |
d62a17ae | 118 | (unsigned long long)ifp->flags, ifp->metric, ifp->mtu); |
718e3744 | 119 | |
d62a17ae | 120 | assert(ifp->info); |
f2c80652 | 121 | |
d62a17ae | 122 | if (!OSPF_IF_PARAM_CONFIGURED(IF_DEF_PARAMS(ifp), type)) { |
123 | SET_IF_PARAM(IF_DEF_PARAMS(ifp), type); | |
124 | IF_DEF_PARAMS(ifp)->type = ospf_default_iftype(ifp); | |
125 | } | |
718e3744 | 126 | |
b5a8894d | 127 | ospf = ospf_lookup_by_vrf_id(vrf_id); |
43b8d1d8 CS |
128 | if (!ospf) |
129 | return 0; | |
b5a8894d CS |
130 | |
131 | ospf_if_update(ospf, ifp); | |
718e3744 | 132 | |
d62a17ae | 133 | hook_call(ospf_if_update, ifp); |
718e3744 | 134 | |
d62a17ae | 135 | return 0; |
718e3744 | 136 | } |
137 | ||
d62a17ae | 138 | static int ospf_interface_delete(int command, struct zclient *zclient, |
139 | zebra_size_t length, vrf_id_t vrf_id) | |
718e3744 | 140 | { |
d62a17ae | 141 | struct interface *ifp; |
142 | struct stream *s; | |
143 | struct route_node *rn; | |
718e3744 | 144 | |
d62a17ae | 145 | s = zclient->ibuf; |
146 | /* zebra_interface_state_read() updates interface structure in iflist */ | |
147 | ifp = zebra_interface_state_read(s, vrf_id); | |
718e3744 | 148 | |
d62a17ae | 149 | if (ifp == NULL) |
150 | return 0; | |
718e3744 | 151 | |
d62a17ae | 152 | if (if_is_up(ifp)) |
153 | zlog_warn("Zebra: got delete of %s, but interface is still up", | |
154 | ifp->name); | |
cf795c5d | 155 | |
d62a17ae | 156 | if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE)) |
157 | zlog_debug( | |
b5a8894d CS |
158 | "Zebra: interface delete %s vrf %s[%u] index %d flags %llx metric %d mtu %d", |
159 | ifp->name, ospf_vrf_id_to_name(ifp->vrf_id), | |
160 | ifp->vrf_id, ifp->ifindex, | |
d62a17ae | 161 | (unsigned long long)ifp->flags, ifp->metric, ifp->mtu); |
718e3744 | 162 | |
d62a17ae | 163 | hook_call(ospf_if_delete, ifp); |
718e3744 | 164 | |
d62a17ae | 165 | for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) |
166 | if (rn->info) | |
167 | ospf_if_free((struct ospf_interface *)rn->info); | |
718e3744 | 168 | |
d62a17ae | 169 | ifp->ifindex = IFINDEX_DELETED; |
170 | return 0; | |
718e3744 | 171 | } |
172 | ||
d62a17ae | 173 | static struct interface *zebra_interface_if_lookup(struct stream *s, |
174 | vrf_id_t vrf_id) | |
718e3744 | 175 | { |
d62a17ae | 176 | char ifname_tmp[INTERFACE_NAMSIZ]; |
718e3744 | 177 | |
d62a17ae | 178 | /* Read interface name. */ |
179 | stream_get(ifname_tmp, s, INTERFACE_NAMSIZ); | |
718e3744 | 180 | |
d62a17ae | 181 | /* And look it up. */ |
182 | return if_lookup_by_name_len( | |
b5a8894d | 183 | ifname_tmp, strnlen(ifname_tmp, INTERFACE_NAMSIZ), vrf_id); |
718e3744 | 184 | } |
185 | ||
d62a17ae | 186 | static int ospf_interface_state_up(int command, struct zclient *zclient, |
187 | zebra_size_t length, vrf_id_t vrf_id) | |
718e3744 | 188 | { |
d62a17ae | 189 | struct interface *ifp; |
190 | struct ospf_interface *oi; | |
191 | struct route_node *rn; | |
192 | ||
193 | ifp = zebra_interface_if_lookup(zclient->ibuf, vrf_id); | |
194 | ||
195 | if (ifp == NULL) | |
196 | return 0; | |
197 | ||
198 | /* Interface is already up. */ | |
199 | if (if_is_operative(ifp)) { | |
200 | /* Temporarily keep ifp values. */ | |
201 | struct interface if_tmp; | |
202 | memcpy(&if_tmp, ifp, sizeof(struct interface)); | |
203 | ||
204 | zebra_interface_if_set_value(zclient->ibuf, ifp); | |
205 | ||
206 | if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE)) | |
207 | zlog_debug( | |
208 | "Zebra: Interface[%s] state update speed %u -> %u, bw %d -> %d", | |
209 | ifp->name, if_tmp.speed, ifp->speed, | |
210 | if_tmp.bandwidth, ifp->bandwidth); | |
211 | ||
212 | ospf_if_recalculate_output_cost(ifp); | |
213 | ||
214 | if (if_tmp.mtu != ifp->mtu) { | |
215 | if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE)) | |
216 | zlog_debug( | |
217 | "Zebra: Interface[%s] MTU change %u -> %u.", | |
218 | ifp->name, if_tmp.mtu, ifp->mtu); | |
219 | ||
220 | /* Must reset the interface (simulate down/up) when MTU | |
221 | * changes. */ | |
222 | ospf_if_reset(ifp); | |
223 | } | |
224 | return 0; | |
a608bbf2 | 225 | } |
cf795c5d | 226 | |
d62a17ae | 227 | zebra_interface_if_set_value(zclient->ibuf, ifp); |
cf795c5d | 228 | |
d62a17ae | 229 | if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE)) |
230 | zlog_debug("Zebra: Interface[%s] state change to up.", | |
231 | ifp->name); | |
cf795c5d | 232 | |
d62a17ae | 233 | for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) { |
234 | if ((oi = rn->info) == NULL) | |
235 | continue; | |
cf795c5d | 236 | |
d62a17ae | 237 | ospf_if_up(oi); |
238 | } | |
cf795c5d | 239 | |
d62a17ae | 240 | return 0; |
718e3744 | 241 | } |
242 | ||
d62a17ae | 243 | static int ospf_interface_state_down(int command, struct zclient *zclient, |
244 | zebra_size_t length, vrf_id_t vrf_id) | |
718e3744 | 245 | { |
d62a17ae | 246 | struct interface *ifp; |
247 | struct ospf_interface *oi; | |
248 | struct route_node *node; | |
718e3744 | 249 | |
d62a17ae | 250 | ifp = zebra_interface_state_read(zclient->ibuf, vrf_id); |
718e3744 | 251 | |
d62a17ae | 252 | if (ifp == NULL) |
253 | return 0; | |
718e3744 | 254 | |
d62a17ae | 255 | if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE)) |
256 | zlog_debug("Zebra: Interface[%s] state change to down.", | |
257 | ifp->name); | |
718e3744 | 258 | |
d62a17ae | 259 | for (node = route_top(IF_OIFS(ifp)); node; node = route_next(node)) { |
260 | if ((oi = node->info) == NULL) | |
261 | continue; | |
262 | ospf_if_down(oi); | |
263 | } | |
718e3744 | 264 | |
d62a17ae | 265 | return 0; |
718e3744 | 266 | } |
267 | ||
d62a17ae | 268 | static int ospf_interface_address_add(int command, struct zclient *zclient, |
269 | zebra_size_t length, vrf_id_t vrf_id) | |
718e3744 | 270 | { |
d62a17ae | 271 | struct connected *c; |
b5a8894d CS |
272 | struct ospf *ospf = NULL; |
273 | ||
718e3744 | 274 | |
d62a17ae | 275 | c = zebra_interface_address_read(command, zclient->ibuf, vrf_id); |
718e3744 | 276 | |
d62a17ae | 277 | if (c == NULL) |
278 | return 0; | |
718e3744 | 279 | |
d62a17ae | 280 | if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE)) { |
281 | char buf[PREFIX2STR_BUFFER]; | |
282 | prefix2str(c->address, buf, sizeof(buf)); | |
b5a8894d CS |
283 | zlog_debug("Zebra: interface %s address add %s vrf %s id %u", |
284 | c->ifp->name, buf, ospf_vrf_id_to_name(vrf_id), | |
285 | vrf_id); | |
d62a17ae | 286 | } |
7f643ebf | 287 | |
b5a8894d | 288 | ospf = ospf_lookup_by_vrf_id(vrf_id); |
43b8d1d8 CS |
289 | if (!ospf) |
290 | return 0; | |
b5a8894d CS |
291 | |
292 | ospf_if_update(ospf, c->ifp); | |
718e3744 | 293 | |
d62a17ae | 294 | hook_call(ospf_if_update, c->ifp); |
718e3744 | 295 | |
d62a17ae | 296 | return 0; |
718e3744 | 297 | } |
298 | ||
d62a17ae | 299 | static int ospf_interface_address_delete(int command, struct zclient *zclient, |
300 | zebra_size_t length, vrf_id_t vrf_id) | |
718e3744 | 301 | { |
d62a17ae | 302 | struct connected *c; |
303 | struct interface *ifp; | |
304 | struct ospf_interface *oi; | |
305 | struct route_node *rn; | |
306 | struct prefix p; | |
307 | ||
308 | c = zebra_interface_address_read(command, zclient->ibuf, vrf_id); | |
309 | ||
310 | if (c == NULL) | |
311 | return 0; | |
312 | ||
313 | if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE)) { | |
314 | char buf[PREFIX2STR_BUFFER]; | |
315 | prefix2str(c->address, buf, sizeof(buf)); | |
316 | zlog_debug("Zebra: interface %s address delete %s", | |
317 | c->ifp->name, buf); | |
318 | } | |
7f643ebf | 319 | |
d62a17ae | 320 | ifp = c->ifp; |
321 | p = *c->address; | |
322 | p.prefixlen = IPV4_MAX_PREFIXLEN; | |
718e3744 | 323 | |
d62a17ae | 324 | rn = route_node_lookup(IF_OIFS(ifp), &p); |
325 | if (!rn) { | |
326 | connected_free(c); | |
327 | return 0; | |
328 | } | |
718e3744 | 329 | |
d62a17ae | 330 | assert(rn->info); |
331 | oi = rn->info; | |
332 | route_unlock_node(rn); | |
cf795c5d | 333 | |
d62a17ae | 334 | /* Call interface hook functions to clean up */ |
335 | ospf_if_free(oi); | |
cf795c5d | 336 | |
d62a17ae | 337 | hook_call(ospf_if_update, c->ifp); |
718e3744 | 338 | |
d62a17ae | 339 | connected_free(c); |
718e3744 | 340 | |
d62a17ae | 341 | return 0; |
718e3744 | 342 | } |
72357f2b | 343 | |
d62a17ae | 344 | static int ospf_interface_link_params(int command, struct zclient *zclient, |
345 | zebra_size_t length) | |
16f1b9ee | 346 | { |
d62a17ae | 347 | struct interface *ifp; |
16f1b9ee | 348 | |
d62a17ae | 349 | ifp = zebra_interface_link_params_read(zclient->ibuf); |
16f1b9ee | 350 | |
d62a17ae | 351 | if (ifp == NULL) |
352 | return 0; | |
16f1b9ee | 353 | |
d62a17ae | 354 | /* Update TE TLV */ |
355 | ospf_mpls_te_update_if(ifp); | |
16f1b9ee | 356 | |
d62a17ae | 357 | return 0; |
16f1b9ee OD |
358 | } |
359 | ||
b5a8894d CS |
360 | /* VRF update for an interface. */ |
361 | static int ospf_interface_vrf_update(int command, struct zclient *zclient, | |
362 | zebra_size_t length, vrf_id_t vrf_id) | |
363 | { | |
364 | struct interface *ifp = NULL; | |
365 | vrf_id_t new_vrf_id; | |
16f1b9ee | 366 | |
b5a8894d CS |
367 | ifp = zebra_interface_vrf_update_read(zclient->ibuf, vrf_id, |
368 | &new_vrf_id); | |
369 | if (!ifp) | |
370 | return 0; | |
371 | ||
372 | if (IS_DEBUG_OSPF_EVENT) | |
373 | zlog_debug("%s: Rx Interface %s VRF change vrf_id %u New vrf %s id %u", | |
374 | __PRETTY_FUNCTION__, ifp->name, vrf_id, | |
375 | ospf_vrf_id_to_name(new_vrf_id), new_vrf_id); | |
376 | ||
377 | /*if_update(ifp, ifp->name, strlen(ifp->name), new_vrf_id);*/ | |
378 | if_update_to_new_vrf(ifp, new_vrf_id); | |
379 | ||
380 | return 0; | |
381 | } | |
382 | ||
383 | void ospf_zebra_add(struct ospf *ospf, struct prefix_ipv4 *p, | |
384 | struct ospf_route *or) | |
718e3744 | 385 | { |
5fef910e RW |
386 | struct zapi_route api; |
387 | struct zapi_nexthop *api_nh; | |
d62a17ae | 388 | u_char distance; |
d62a17ae | 389 | struct ospf_path *path; |
390 | struct listnode *node; | |
5fef910e | 391 | int count = 0; |
d62a17ae | 392 | |
5fef910e | 393 | memset(&api, 0, sizeof(api)); |
b5a8894d | 394 | api.vrf_id = ospf->vrf_id; |
5fef910e RW |
395 | api.type = ZEBRA_ROUTE_OSPF; |
396 | api.instance = ospf->instance; | |
397 | api.safi = SAFI_UNICAST; | |
d00061ea | 398 | |
5fef910e RW |
399 | memcpy(&api.prefix, p, sizeof(*p)); |
400 | SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); | |
d00061ea | 401 | |
5fef910e RW |
402 | /* Metric value. */ |
403 | SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); | |
404 | if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL) | |
405 | api.metric = or->cost + or->u.ext.type2_cost; | |
406 | else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL) | |
407 | api.metric = or->u.ext.type2_cost; | |
408 | else | |
409 | api.metric = or->cost; | |
d00061ea RW |
410 | |
411 | /* Check if path type is ASE */ | |
412 | if (((or->path_type == OSPF_PATH_TYPE1_EXTERNAL) | |
413 | || (or->path_type == OSPF_PATH_TYPE2_EXTERNAL)) | |
5fef910e RW |
414 | && (or->u.ext.tag > 0) && (or->u.ext.tag <= ROUTE_TAG_MAX)) { |
415 | SET_FLAG(api.message, ZAPI_MESSAGE_TAG); | |
416 | api.tag = or->u.ext.tag; | |
417 | } | |
d00061ea | 418 | |
5fef910e | 419 | /* Distance value. */ |
b5a8894d | 420 | distance = ospf_distance_apply(ospf, p, or); |
5fef910e RW |
421 | if (distance) { |
422 | SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); | |
423 | api.distance = distance; | |
424 | } | |
d00061ea RW |
425 | |
426 | /* Nexthop, ifindex, distance and metric information. */ | |
427 | for (ALL_LIST_ELEMENTS_RO(or->paths, node, path)) { | |
a74e593b RW |
428 | if (count >= MULTIPATH_NUM) |
429 | break; | |
5fef910e | 430 | api_nh = &api.nexthops[count]; |
525c1839 | 431 | #ifdef HAVE_NETLINK |
d00061ea RW |
432 | if (path->unnumbered || (path->nexthop.s_addr != INADDR_ANY |
433 | && path->ifindex != 0)) { | |
525c1839 | 434 | #else /* HAVE_NETLINK */ |
d00061ea | 435 | if (path->nexthop.s_addr != INADDR_ANY && path->ifindex != 0) { |
5fef910e RW |
436 | #endif /* HAVE_NETLINK */ |
437 | api_nh->gate.ipv4 = path->nexthop; | |
438 | api_nh->ifindex = path->ifindex; | |
439 | api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX; | |
d00061ea | 440 | } else if (path->nexthop.s_addr != INADDR_ANY) { |
5fef910e RW |
441 | api_nh->gate.ipv4 = path->nexthop; |
442 | api_nh->type = NEXTHOP_TYPE_IPV4; | |
d00061ea | 443 | } else { |
5fef910e RW |
444 | api_nh->ifindex = path->ifindex; |
445 | api_nh->type = NEXTHOP_TYPE_IFINDEX; | |
d00061ea | 446 | } |
5fef910e | 447 | count++; |
72357f2b | 448 | |
d00061ea RW |
449 | if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) { |
450 | char buf[2][INET_ADDRSTRLEN]; | |
451 | zlog_debug( | |
452 | "Zebra: Route add %s/%d nexthop %s, ifindex=%d", | |
453 | inet_ntop(AF_INET, &p->prefix, buf[0], | |
454 | sizeof(buf[0])), | |
455 | p->prefixlen, inet_ntop(AF_INET, &path->nexthop, | |
456 | buf[1], sizeof(buf[1])), | |
457 | path->ifindex); | |
d62a17ae | 458 | } |
d00061ea | 459 | } |
a74e593b | 460 | api.nexthop_num = count; |
d62a17ae | 461 | |
5fef910e | 462 | zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api); |
718e3744 | 463 | } |
464 | ||
b5a8894d CS |
465 | void ospf_zebra_delete(struct ospf *ospf, struct prefix_ipv4 *p, |
466 | struct ospf_route *or) | |
718e3744 | 467 | { |
5fef910e | 468 | struct zapi_route api; |
d62a17ae | 469 | |
5fef910e | 470 | memset(&api, 0, sizeof(api)); |
b5a8894d | 471 | api.vrf_id = ospf->vrf_id; |
5fef910e RW |
472 | api.type = ZEBRA_ROUTE_OSPF; |
473 | api.instance = ospf->instance; | |
474 | api.safi = SAFI_UNICAST; | |
475 | memcpy(&api.prefix, p, sizeof(*p)); | |
d62a17ae | 476 | |
5fef910e RW |
477 | if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) { |
478 | char buf[INET_ADDRSTRLEN]; | |
479 | zlog_debug("Zebra: Route delete %s/%d", | |
480 | inet_ntop(AF_INET, &p->prefix, buf, sizeof(buf[0])), | |
481 | p->prefixlen); | |
ba281d3d | 482 | } |
d00061ea | 483 | |
5fef910e | 484 | zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api); |
718e3744 | 485 | } |
486 | ||
b5a8894d | 487 | void ospf_zebra_add_discard(struct ospf *ospf, struct prefix_ipv4 *p) |
718e3744 | 488 | { |
5fef910e | 489 | struct zapi_route api; |
d62a17ae | 490 | |
5fef910e | 491 | memset(&api, 0, sizeof(api)); |
b5a8894d | 492 | api.vrf_id = ospf->vrf_id; |
d00061ea RW |
493 | api.type = ZEBRA_ROUTE_OSPF; |
494 | api.instance = ospf->instance; | |
d00061ea | 495 | api.safi = SAFI_UNICAST; |
5fef910e | 496 | memcpy(&api.prefix, p, sizeof(*p)); |
09a484dd | 497 | zapi_route_set_blackhole(&api, BLACKHOLE_NULL); |
d00061ea | 498 | |
5fef910e | 499 | zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api); |
d00061ea RW |
500 | |
501 | if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) | |
502 | zlog_debug("Zebra: Route add discard %s/%d", | |
503 | inet_ntoa(p->prefix), p->prefixlen); | |
718e3744 | 504 | } |
505 | ||
b5a8894d | 506 | void ospf_zebra_delete_discard(struct ospf *ospf, struct prefix_ipv4 *p) |
718e3744 | 507 | { |
5fef910e | 508 | struct zapi_route api; |
d62a17ae | 509 | |
5fef910e | 510 | memset(&api, 0, sizeof(api)); |
b5a8894d | 511 | api.vrf_id = ospf->vrf_id; |
d00061ea RW |
512 | api.type = ZEBRA_ROUTE_OSPF; |
513 | api.instance = ospf->instance; | |
d00061ea | 514 | api.safi = SAFI_UNICAST; |
5fef910e | 515 | memcpy(&api.prefix, p, sizeof(*p)); |
09a484dd | 516 | zapi_route_set_blackhole(&api, BLACKHOLE_NULL); |
d00061ea | 517 | |
5fef910e | 518 | zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api); |
d00061ea RW |
519 | |
520 | if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) | |
521 | zlog_debug("Zebra: Route delete discard %s/%d", | |
522 | inet_ntoa(p->prefix), p->prefixlen); | |
718e3744 | 523 | } |
524 | ||
d62a17ae | 525 | struct ospf_external *ospf_external_lookup(u_char type, u_short instance) |
7c8ff89e | 526 | { |
d62a17ae | 527 | struct list *ext_list; |
528 | struct listnode *node; | |
529 | struct ospf_external *ext; | |
7c8ff89e | 530 | |
d62a17ae | 531 | ext_list = om->external[type]; |
532 | if (!ext_list) | |
533 | return (NULL); | |
7c8ff89e | 534 | |
d62a17ae | 535 | for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) |
536 | if (ext->instance == instance) | |
537 | return ext; | |
7c8ff89e | 538 | |
d62a17ae | 539 | return NULL; |
7c8ff89e DS |
540 | } |
541 | ||
d62a17ae | 542 | struct ospf_external *ospf_external_add(u_char type, u_short instance) |
7c8ff89e | 543 | { |
d62a17ae | 544 | struct list *ext_list; |
545 | struct ospf_external *ext; | |
7c8ff89e | 546 | |
d62a17ae | 547 | ext = ospf_external_lookup(type, instance); |
548 | if (ext) | |
549 | return ext; | |
7c8ff89e | 550 | |
d62a17ae | 551 | if (!om->external[type]) |
552 | om->external[type] = list_new(); | |
7c8ff89e | 553 | |
d62a17ae | 554 | ext_list = om->external[type]; |
7f586094 CS |
555 | ext = (struct ospf_external *)XCALLOC(MTYPE_OSPF_EXTERNAL, |
556 | sizeof(struct ospf_external)); | |
d62a17ae | 557 | ext->instance = instance; |
558 | EXTERNAL_INFO(ext) = route_table_init(); | |
7c8ff89e | 559 | |
d62a17ae | 560 | listnode_add(ext_list, ext); |
7c8ff89e | 561 | |
d62a17ae | 562 | return ext; |
7c8ff89e DS |
563 | } |
564 | ||
d62a17ae | 565 | void ospf_external_del(u_char type, u_short instance) |
7c8ff89e | 566 | { |
d62a17ae | 567 | struct ospf_external *ext; |
568 | ||
569 | ext = ospf_external_lookup(type, instance); | |
570 | ||
571 | if (ext) { | |
572 | if (EXTERNAL_INFO(ext)) | |
573 | route_table_finish(EXTERNAL_INFO(ext)); | |
574 | ||
575 | listnode_delete(om->external[type], ext); | |
576 | if (!om->external[type]->count) { | |
acdf5e25 | 577 | list_delete_and_null(&om->external[type]); |
d62a17ae | 578 | } |
7f586094 | 579 | XFREE(MTYPE_OSPF_EXTERNAL, ext); |
d62a17ae | 580 | } |
7c8ff89e DS |
581 | } |
582 | ||
d62a17ae | 583 | struct ospf_redist *ospf_redist_lookup(struct ospf *ospf, u_char type, |
584 | u_short instance) | |
7c8ff89e | 585 | { |
d62a17ae | 586 | struct list *red_list; |
587 | struct listnode *node; | |
588 | struct ospf_redist *red; | |
7c8ff89e | 589 | |
d62a17ae | 590 | red_list = ospf->redist[type]; |
591 | if (!red_list) | |
592 | return (NULL); | |
7c8ff89e | 593 | |
d62a17ae | 594 | for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) |
595 | if (red->instance == instance) | |
596 | return red; | |
7c8ff89e | 597 | |
d62a17ae | 598 | return NULL; |
7c8ff89e DS |
599 | } |
600 | ||
d62a17ae | 601 | struct ospf_redist *ospf_redist_add(struct ospf *ospf, u_char type, |
602 | u_short instance) | |
7c8ff89e | 603 | { |
d62a17ae | 604 | struct list *red_list; |
605 | struct ospf_redist *red; | |
7c8ff89e | 606 | |
d62a17ae | 607 | red = ospf_redist_lookup(ospf, type, instance); |
608 | if (red) | |
609 | return red; | |
7c8ff89e | 610 | |
d62a17ae | 611 | if (!ospf->redist[type]) |
612 | ospf->redist[type] = list_new(); | |
7c8ff89e | 613 | |
d62a17ae | 614 | red_list = ospf->redist[type]; |
7f586094 CS |
615 | red = (struct ospf_redist *)XCALLOC(MTYPE_OSPF_REDISTRIBUTE, |
616 | sizeof(struct ospf_redist)); | |
d62a17ae | 617 | red->instance = instance; |
618 | red->dmetric.type = -1; | |
619 | red->dmetric.value = -1; | |
7c8ff89e | 620 | |
d62a17ae | 621 | listnode_add(red_list, red); |
7c8ff89e | 622 | |
d62a17ae | 623 | return red; |
7c8ff89e DS |
624 | } |
625 | ||
d62a17ae | 626 | void ospf_redist_del(struct ospf *ospf, u_char type, u_short instance) |
7c8ff89e | 627 | { |
d62a17ae | 628 | struct ospf_redist *red; |
629 | ||
630 | red = ospf_redist_lookup(ospf, type, instance); | |
631 | ||
632 | if (red) { | |
633 | listnode_delete(ospf->redist[type], red); | |
634 | if (!ospf->redist[type]->count) { | |
acdf5e25 | 635 | list_delete_and_null(&ospf->redist[type]); |
d62a17ae | 636 | } |
97a69b31 | 637 | ospf_routemap_unset(red); |
7f586094 | 638 | XFREE(MTYPE_OSPF_REDISTRIBUTE, red); |
d62a17ae | 639 | } |
7c8ff89e DS |
640 | } |
641 | ||
642 | ||
b5a8894d | 643 | int ospf_is_type_redistributed(struct ospf *ospf, int type, u_short instance) |
718e3744 | 644 | { |
d62a17ae | 645 | return (DEFAULT_ROUTE_TYPE(type) |
646 | ? vrf_bitmap_check(zclient->default_information, | |
b5a8894d | 647 | ospf->vrf_id) |
d62a17ae | 648 | : ((instance |
649 | && redist_check_instance( | |
650 | &zclient->mi_redist[AFI_IP][type], | |
651 | instance)) | |
652 | || (!instance | |
653 | && vrf_bitmap_check( | |
654 | zclient->redist[AFI_IP][type], | |
b5a8894d | 655 | ospf->vrf_id)))); |
718e3744 | 656 | } |
657 | ||
d62a17ae | 658 | int ospf_redistribute_set(struct ospf *ospf, int type, u_short instance, |
659 | int mtype, int mvalue) | |
718e3744 | 660 | { |
d62a17ae | 661 | int force = 0; |
662 | struct ospf_redist *red; | |
663 | ||
664 | red = ospf_redist_lookup(ospf, type, instance); | |
b5a8894d | 665 | if (ospf_is_type_redistributed(ospf, type, instance)) { |
d62a17ae | 666 | if (mtype != red->dmetric.type) { |
667 | red->dmetric.type = mtype; | |
668 | force = LSA_REFRESH_FORCE; | |
669 | } | |
670 | if (mvalue != red->dmetric.value) { | |
671 | red->dmetric.value = mvalue; | |
672 | force = LSA_REFRESH_FORCE; | |
673 | } | |
674 | ||
675 | ospf_external_lsa_refresh_type(ospf, type, instance, force); | |
676 | ||
677 | if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) | |
678 | zlog_debug( | |
679 | "Redistribute[%s][%d]: Refresh Type[%d], Metric[%d]", | |
680 | ospf_redist_string(type), instance, | |
681 | metric_type(ospf, type, instance), | |
682 | metric_value(ospf, type, instance)); | |
683 | ||
684 | return CMD_SUCCESS; | |
685 | } | |
686 | ||
687 | red->dmetric.type = mtype; | |
688 | red->dmetric.value = mvalue; | |
689 | ||
690 | ospf_external_add(type, instance); | |
691 | ||
692 | zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, type, | |
b5a8894d | 693 | instance, ospf->vrf_id); |
d62a17ae | 694 | |
695 | if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) | |
b5a8894d CS |
696 | zlog_debug("Redistribute[%s][%d] vrf id %u: Start Type[%d], Metric[%d]", |
697 | ospf_redist_string(type), instance, ospf->vrf_id, | |
d62a17ae | 698 | metric_type(ospf, type, instance), |
699 | metric_value(ospf, type, instance)); | |
700 | ||
701 | ospf_asbr_status_update(ospf, ++ospf->redistribute); | |
702 | ||
703 | return CMD_SUCCESS; | |
718e3744 | 704 | } |
705 | ||
d62a17ae | 706 | int ospf_redistribute_unset(struct ospf *ospf, int type, u_short instance) |
718e3744 | 707 | { |
d62a17ae | 708 | if (type == zclient->redist_default && instance == zclient->instance) |
709 | return CMD_SUCCESS; | |
718e3744 | 710 | |
b5a8894d | 711 | if (!ospf_is_type_redistributed(ospf, type, instance)) |
d62a17ae | 712 | return CMD_SUCCESS; |
718e3744 | 713 | |
d62a17ae | 714 | zclient_redistribute(ZEBRA_REDISTRIBUTE_DELETE, zclient, AFI_IP, type, |
b5a8894d | 715 | instance, ospf->vrf_id); |
cf795c5d | 716 | |
d62a17ae | 717 | if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) |
b5a8894d CS |
718 | zlog_debug("Redistribute[%s][%d] vrf id %u: Stop", |
719 | ospf_redist_string(type), instance, ospf->vrf_id); | |
718e3744 | 720 | |
d62a17ae | 721 | ospf_redist_del(ospf, type, instance); |
718e3744 | 722 | |
d62a17ae | 723 | /* Remove the routes from OSPF table. */ |
724 | ospf_redistribute_withdraw(ospf, type, instance); | |
7c8ff89e | 725 | |
d62a17ae | 726 | ospf_external_del(type, instance); |
718e3744 | 727 | |
d62a17ae | 728 | ospf_asbr_status_update(ospf, --ospf->redistribute); |
718e3744 | 729 | |
d62a17ae | 730 | return CMD_SUCCESS; |
718e3744 | 731 | } |
732 | ||
d62a17ae | 733 | int ospf_redistribute_default_set(struct ospf *ospf, int originate, int mtype, |
734 | int mvalue) | |
718e3744 | 735 | { |
d62a17ae | 736 | struct ospf_redist *red; |
7c8ff89e | 737 | |
d62a17ae | 738 | ospf->default_originate = originate; |
020709f9 | 739 | |
d62a17ae | 740 | red = ospf_redist_add(ospf, DEFAULT_ROUTE, 0); |
741 | red->dmetric.type = mtype; | |
742 | red->dmetric.value = mvalue; | |
7c8ff89e | 743 | |
d62a17ae | 744 | ospf_external_add(DEFAULT_ROUTE, 0); |
7c8ff89e | 745 | |
b5a8894d | 746 | if (ospf_is_type_redistributed(ospf, DEFAULT_ROUTE, 0)) { |
d62a17ae | 747 | /* if ospf->default_originate changes value, is calling |
748 | ospf_external_lsa_refresh_default sufficient to implement | |
749 | the change? */ | |
750 | ospf_external_lsa_refresh_default(ospf); | |
cf795c5d | 751 | |
d62a17ae | 752 | if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) |
753 | zlog_debug( | |
754 | "Redistribute[%s]: Refresh Type[%d], Metric[%d]", | |
755 | ospf_redist_string(DEFAULT_ROUTE), | |
756 | metric_type(ospf, DEFAULT_ROUTE, 0), | |
757 | metric_value(ospf, DEFAULT_ROUTE, 0)); | |
758 | return CMD_SUCCESS; | |
759 | } | |
718e3744 | 760 | |
d62a17ae | 761 | zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD, zclient, |
b5a8894d | 762 | ospf->vrf_id); |
cf795c5d | 763 | |
d62a17ae | 764 | if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) |
765 | zlog_debug("Redistribute[DEFAULT]: Start Type[%d], Metric[%d]", | |
766 | metric_type(ospf, DEFAULT_ROUTE, 0), | |
767 | metric_value(ospf, DEFAULT_ROUTE, 0)); | |
718e3744 | 768 | |
d62a17ae | 769 | if (ospf->router_id.s_addr == 0) |
770 | ospf->external_origin |= (1 << DEFAULT_ROUTE); | |
771 | else | |
772 | thread_add_timer(master, ospf_default_originate_timer, ospf, 1, | |
773 | NULL); | |
718e3744 | 774 | |
d62a17ae | 775 | ospf_asbr_status_update(ospf, ++ospf->redistribute); |
718e3744 | 776 | |
d62a17ae | 777 | return CMD_SUCCESS; |
718e3744 | 778 | } |
779 | ||
d62a17ae | 780 | int ospf_redistribute_default_unset(struct ospf *ospf) |
718e3744 | 781 | { |
b5a8894d | 782 | if (!ospf_is_type_redistributed(ospf, DEFAULT_ROUTE, 0)) |
d62a17ae | 783 | return CMD_SUCCESS; |
718e3744 | 784 | |
d62a17ae | 785 | ospf->default_originate = DEFAULT_ORIGINATE_NONE; |
786 | ospf_redist_del(ospf, DEFAULT_ROUTE, 0); | |
718e3744 | 787 | |
d62a17ae | 788 | zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, zclient, |
b5a8894d | 789 | ospf->vrf_id); |
718e3744 | 790 | |
d62a17ae | 791 | if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) |
792 | zlog_debug("Redistribute[DEFAULT]: Stop"); | |
cf795c5d | 793 | |
d62a17ae | 794 | // Pending: how does the external_info cleanup work in this case? |
7c8ff89e | 795 | |
d62a17ae | 796 | ospf_asbr_status_update(ospf, --ospf->redistribute); |
718e3744 | 797 | |
d62a17ae | 798 | return CMD_SUCCESS; |
718e3744 | 799 | } |
800 | ||
d62a17ae | 801 | static int ospf_external_lsa_originate_check(struct ospf *ospf, |
802 | struct external_info *ei) | |
718e3744 | 803 | { |
d62a17ae | 804 | /* If prefix is multicast, then do not originate LSA. */ |
805 | if (IN_MULTICAST(htonl(ei->p.prefix.s_addr))) { | |
806 | zlog_info( | |
807 | "LSA[Type5:%s]: Not originate AS-external-LSA, " | |
808 | "Prefix belongs multicast", | |
809 | inet_ntoa(ei->p.prefix)); | |
810 | return 0; | |
811 | } | |
812 | ||
813 | /* Take care of default-originate. */ | |
814 | if (is_prefix_default(&ei->p)) | |
815 | if (ospf->default_originate == DEFAULT_ORIGINATE_NONE) { | |
816 | zlog_info( | |
817 | "LSA[Type5:0.0.0.0]: Not originate AS-external-LSA " | |
818 | "for default"); | |
819 | return 0; | |
820 | } | |
821 | ||
822 | return 1; | |
718e3744 | 823 | } |
824 | ||
825 | /* If connected prefix is OSPF enable interface, then do not announce. */ | |
d62a17ae | 826 | int ospf_distribute_check_connected(struct ospf *ospf, struct external_info *ei) |
718e3744 | 827 | { |
d62a17ae | 828 | struct listnode *node; |
829 | struct ospf_interface *oi; | |
718e3744 | 830 | |
718e3744 | 831 | |
d62a17ae | 832 | for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) |
833 | if (prefix_match(oi->address, (struct prefix *)&ei->p)) | |
834 | return 0; | |
835 | return 1; | |
718e3744 | 836 | } |
837 | ||
838 | /* return 1 if external LSA must be originated, 0 otherwise */ | |
d62a17ae | 839 | int ospf_redistribute_check(struct ospf *ospf, struct external_info *ei, |
840 | int *changed) | |
718e3744 | 841 | { |
d62a17ae | 842 | struct route_map_set_values save_values; |
843 | struct prefix_ipv4 *p = &ei->p; | |
844 | struct ospf_redist *red; | |
845 | u_char type = is_prefix_default(&ei->p) ? DEFAULT_ROUTE : ei->type; | |
846 | u_short instance = is_prefix_default(&ei->p) ? 0 : ei->instance; | |
847 | ||
848 | if (changed) | |
849 | *changed = 0; | |
850 | ||
851 | if (!ospf_external_lsa_originate_check(ospf, ei)) | |
852 | return 0; | |
853 | ||
854 | /* Take care connected route. */ | |
855 | if (type == ZEBRA_ROUTE_CONNECT | |
856 | && !ospf_distribute_check_connected(ospf, ei)) | |
857 | return 0; | |
858 | ||
859 | if (!DEFAULT_ROUTE_TYPE(type) && DISTRIBUTE_NAME(ospf, type)) | |
860 | /* distirbute-list exists, but access-list may not? */ | |
861 | if (DISTRIBUTE_LIST(ospf, type)) | |
862 | if (access_list_apply(DISTRIBUTE_LIST(ospf, type), p) | |
863 | == FILTER_DENY) { | |
864 | if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) | |
865 | zlog_debug( | |
866 | "Redistribute[%s]: %s/%d filtered by ditribute-list.", | |
867 | ospf_redist_string(type), | |
868 | inet_ntoa(p->prefix), | |
869 | p->prefixlen); | |
870 | return 0; | |
871 | } | |
872 | ||
873 | save_values = ei->route_map_set; | |
874 | ospf_reset_route_map_set_values(&ei->route_map_set); | |
875 | ||
876 | /* apply route-map if needed */ | |
877 | red = ospf_redist_lookup(ospf, type, instance); | |
878 | if (red && ROUTEMAP_NAME(red)) { | |
879 | int ret; | |
880 | ||
881 | ret = route_map_apply(ROUTEMAP(red), (struct prefix *)p, | |
882 | RMAP_OSPF, ei); | |
883 | ||
884 | if (ret == RMAP_DENYMATCH) { | |
885 | ei->route_map_set = save_values; | |
886 | if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) | |
887 | zlog_debug( | |
888 | "Redistribute[%s]: %s/%d filtered by route-map.", | |
889 | ospf_redist_string(type), | |
890 | inet_ntoa(p->prefix), p->prefixlen); | |
891 | return 0; | |
892 | } | |
893 | ||
894 | /* check if 'route-map set' changed something */ | |
895 | if (changed) | |
896 | *changed = !ospf_route_map_set_compare( | |
897 | &ei->route_map_set, &save_values); | |
898 | } | |
899 | ||
900 | return 1; | |
718e3744 | 901 | } |
902 | ||
903 | /* OSPF route-map set for redistribution */ | |
d62a17ae | 904 | void ospf_routemap_set(struct ospf_redist *red, const char *name) |
718e3744 | 905 | { |
d62a17ae | 906 | if (ROUTEMAP_NAME(red)) |
907 | free(ROUTEMAP_NAME(red)); | |
718e3744 | 908 | |
d62a17ae | 909 | ROUTEMAP_NAME(red) = strdup(name); |
910 | ROUTEMAP(red) = route_map_lookup_by_name(name); | |
718e3744 | 911 | } |
912 | ||
d62a17ae | 913 | void ospf_routemap_unset(struct ospf_redist *red) |
718e3744 | 914 | { |
d62a17ae | 915 | if (ROUTEMAP_NAME(red)) |
916 | free(ROUTEMAP_NAME(red)); | |
718e3744 | 917 | |
d62a17ae | 918 | ROUTEMAP_NAME(red) = NULL; |
919 | ROUTEMAP(red) = NULL; | |
718e3744 | 920 | } |
921 | ||
922 | /* Zebra route add and delete treatment. */ | |
74489921 RW |
923 | static int ospf_zebra_read_route(int command, struct zclient *zclient, |
924 | zebra_size_t length, vrf_id_t vrf_id) | |
718e3744 | 925 | { |
74489921 RW |
926 | struct zapi_route api; |
927 | struct prefix_ipv4 p; | |
d62a17ae | 928 | unsigned long ifindex; |
929 | struct in_addr nexthop; | |
d62a17ae | 930 | struct external_info *ei; |
931 | struct ospf *ospf; | |
932 | int i; | |
933 | ||
b5a8894d | 934 | ospf = ospf_lookup_by_vrf_id(vrf_id); |
74489921 RW |
935 | if (ospf == NULL) |
936 | return 0; | |
d62a17ae | 937 | |
74489921 RW |
938 | if (zapi_route_decode(zclient->ibuf, &api) < 0) |
939 | return -1; | |
d62a17ae | 940 | |
74489921 RW |
941 | ifindex = api.nexthops[0].ifindex; |
942 | nexthop = api.nexthops[0].gate.ipv4; | |
d62a17ae | 943 | |
74489921 | 944 | memcpy(&p, &api.prefix, sizeof(p)); |
d62a17ae | 945 | if (IPV4_NET127(ntohl(p.prefix.s_addr))) |
946 | return 0; | |
947 | ||
74489921 | 948 | if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD) { |
d62a17ae | 949 | /* XXX|HACK|TODO|FIXME: |
09a484dd DL |
950 | * Maybe we should ignore reject/blackhole routes? Testing |
951 | * shows that there is no problems though and this is only way | |
952 | * to "summarize" routes in ASBR at the moment. Maybe we need | |
953 | * just a better generalised solution for these types? | |
d62a17ae | 954 | */ |
955 | ||
74489921 | 956 | /* Protocol tag overwrites all other tag value sent by zebra */ |
d62a17ae | 957 | if (ospf->dtag[api.type] > 0) |
958 | api.tag = ospf->dtag[api.type]; | |
959 | ||
960 | /* | |
961 | * Given zebra sends update for a prefix via ADD message, it | |
962 | * should | |
963 | * be considered as an implicit DEL for that prefix with other | |
964 | * source | |
965 | * types. | |
966 | */ | |
967 | for (i = 0; i < ZEBRA_ROUTE_MAX; i++) | |
968 | if (i != api.type) | |
969 | ospf_external_info_delete(i, api.instance, p); | |
970 | ||
971 | ei = ospf_external_info_add(api.type, api.instance, p, ifindex, | |
972 | nexthop, api.tag); | |
973 | if (ei == NULL) { | |
974 | /* Nothing has changed, so nothing to do; return */ | |
975 | return 0; | |
976 | } | |
977 | if (ospf->router_id.s_addr == 0) | |
978 | /* Set flags to generate AS-external-LSA originate event | |
979 | for each redistributed protocols later. */ | |
980 | ospf->external_origin |= (1 << api.type); | |
981 | else { | |
982 | if (ei) { | |
983 | if (is_prefix_default(&p)) | |
984 | ospf_external_lsa_refresh_default(ospf); | |
985 | else { | |
986 | struct ospf_lsa *current; | |
987 | ||
988 | current = ospf_external_info_find_lsa( | |
989 | ospf, &ei->p); | |
990 | if (!current) | |
991 | ospf_external_lsa_originate( | |
992 | ospf, ei); | |
993 | else { | |
994 | if (IS_DEBUG_OSPF( | |
995 | zebra, | |
996 | ZEBRA_REDISTRIBUTE)) | |
997 | zlog_debug( | |
74489921 | 998 | "ospf_zebra_read_route() : %s refreshing LSA", |
d62a17ae | 999 | inet_ntoa( |
1000 | p.prefix)); | |
1001 | ospf_external_lsa_refresh( | |
1002 | ospf, current, ei, | |
1003 | LSA_REFRESH_FORCE); | |
1004 | } | |
1005 | } | |
1006 | } | |
1007 | } | |
74489921 | 1008 | } else /* if (command == ZEBRA_REDISTRIBUTE_ROUTE_DEL) */ |
5048fe14 | 1009 | { |
d62a17ae | 1010 | ospf_external_info_delete(api.type, api.instance, p); |
1011 | if (is_prefix_default(&p)) | |
1012 | ospf_external_lsa_refresh_default(ospf); | |
1013 | else | |
1014 | ospf_external_lsa_flush(ospf, api.type, &p, | |
1015 | ifindex /*, nexthop */); | |
5048fe14 | 1016 | } |
d62a17ae | 1017 | |
1018 | return 0; | |
718e3744 | 1019 | } |
6b0655a2 | 1020 | |
cf795c5d | 1021 | |
d62a17ae | 1022 | int ospf_distribute_list_out_set(struct ospf *ospf, int type, const char *name) |
718e3744 | 1023 | { |
d62a17ae | 1024 | /* Lookup access-list for distribute-list. */ |
1025 | DISTRIBUTE_LIST(ospf, type) = access_list_lookup(AFI_IP, name); | |
718e3744 | 1026 | |
d62a17ae | 1027 | /* Clear previous distribute-name. */ |
1028 | if (DISTRIBUTE_NAME(ospf, type)) | |
1029 | free(DISTRIBUTE_NAME(ospf, type)); | |
718e3744 | 1030 | |
d62a17ae | 1031 | /* Set distribute-name. */ |
1032 | DISTRIBUTE_NAME(ospf, type) = strdup(name); | |
718e3744 | 1033 | |
d62a17ae | 1034 | /* If access-list have been set, schedule update timer. */ |
1035 | if (DISTRIBUTE_LIST(ospf, type)) | |
1036 | ospf_distribute_list_update(ospf, type, 0); | |
718e3744 | 1037 | |
d62a17ae | 1038 | return CMD_SUCCESS; |
718e3744 | 1039 | } |
1040 | ||
d62a17ae | 1041 | int ospf_distribute_list_out_unset(struct ospf *ospf, int type, |
1042 | const char *name) | |
718e3744 | 1043 | { |
d62a17ae | 1044 | /* Schedule update timer. */ |
1045 | if (DISTRIBUTE_LIST(ospf, type)) | |
1046 | ospf_distribute_list_update(ospf, type, 0); | |
718e3744 | 1047 | |
d62a17ae | 1048 | /* Unset distribute-list. */ |
1049 | DISTRIBUTE_LIST(ospf, type) = NULL; | |
718e3744 | 1050 | |
d62a17ae | 1051 | /* Clear distribute-name. */ |
1052 | if (DISTRIBUTE_NAME(ospf, type)) | |
1053 | free(DISTRIBUTE_NAME(ospf, type)); | |
cf795c5d | 1054 | |
d62a17ae | 1055 | DISTRIBUTE_NAME(ospf, type) = NULL; |
718e3744 | 1056 | |
d62a17ae | 1057 | return CMD_SUCCESS; |
718e3744 | 1058 | } |
1059 | ||
1060 | /* distribute-list update timer. */ | |
d62a17ae | 1061 | static int ospf_distribute_list_update_timer(struct thread *thread) |
718e3744 | 1062 | { |
d62a17ae | 1063 | struct route_node *rn; |
1064 | struct external_info *ei; | |
1065 | struct route_table *rt; | |
1066 | struct ospf_lsa *lsa; | |
b5a8894d CS |
1067 | int type, default_refresh = 0, arg_type; |
1068 | struct ospf *ospf = NULL; | |
1069 | void **arg = THREAD_ARG (thread); | |
1070 | ||
1071 | ospf = (struct ospf *)arg[0]; | |
1072 | arg_type = (int)(intptr_t)arg[1]; | |
d62a17ae | 1073 | |
d62a17ae | 1074 | if (ospf == NULL) |
1075 | return 0; | |
1076 | ||
1077 | ospf->t_distribute_update = NULL; | |
1078 | ||
1079 | zlog_info("Zebra[Redistribute]: distribute-list update timer fired!"); | |
1080 | ||
b5a8894d CS |
1081 | if (IS_DEBUG_OSPF_EVENT) { |
1082 | zlog_debug("%s: ospf distribute-list update arg_type %d vrf %s id %d", | |
1083 | __PRETTY_FUNCTION__, arg_type, | |
1084 | ospf_vrf_id_to_name(ospf->vrf_id), ospf->vrf_id); | |
1085 | } | |
1086 | ||
d62a17ae | 1087 | /* foreach all external info. */ |
1088 | for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) { | |
1089 | struct list *ext_list; | |
1090 | struct listnode *node; | |
1091 | struct ospf_external *ext; | |
1092 | ||
1093 | ext_list = om->external[type]; | |
1094 | if (!ext_list) | |
1095 | continue; | |
1096 | ||
1097 | for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) { | |
1098 | rt = ext->external_info; | |
1099 | if (!rt) | |
1100 | continue; | |
1101 | for (rn = route_top(rt); rn; rn = route_next(rn)) | |
1102 | if ((ei = rn->info) != NULL) { | |
1103 | if (is_prefix_default(&ei->p)) | |
1104 | default_refresh = 1; | |
1105 | else if ( | |
1106 | (lsa = ospf_external_info_find_lsa( | |
1107 | ospf, &ei->p))) | |
1108 | ospf_external_lsa_refresh( | |
1109 | ospf, lsa, ei, | |
1110 | LSA_REFRESH_IF_CHANGED); | |
1111 | else | |
1112 | ospf_external_lsa_originate( | |
1113 | ospf, ei); | |
1114 | } | |
1115 | } | |
1116 | } | |
1117 | if (default_refresh) | |
1118 | ospf_external_lsa_refresh_default(ospf); | |
b5a8894d CS |
1119 | |
1120 | XFREE(MTYPE_OSPF_DIST_ARGS, arg); | |
d62a17ae | 1121 | return 0; |
718e3744 | 1122 | } |
1123 | ||
718e3744 | 1124 | /* Update distribute-list and set timer to apply access-list. */ |
b5a8894d | 1125 | void ospf_distribute_list_update(struct ospf *ospf, int type, |
d62a17ae | 1126 | u_short instance) |
718e3744 | 1127 | { |
d62a17ae | 1128 | struct route_table *rt; |
1129 | struct ospf_external *ext; | |
43b8d1d8 | 1130 | void **args = XCALLOC(MTYPE_OSPF_DIST_ARGS, sizeof(void *)*2); |
d62a17ae | 1131 | |
b5a8894d CS |
1132 | args[0] = ospf; |
1133 | args[1] = (void *)((ptrdiff_t) type); | |
1134 | ||
d62a17ae | 1135 | /* External info does not exist. */ |
1136 | ext = ospf_external_lookup(type, instance); | |
a68730c6 DS |
1137 | if (!ext || !(rt = EXTERNAL_INFO(ext))) { |
1138 | XFREE(MTYPE_OSPF_DIST_ARGS, args); | |
d62a17ae | 1139 | return; |
a68730c6 | 1140 | } |
d62a17ae | 1141 | |
1142 | /* If exists previously invoked thread, then let it continue. */ | |
a68730c6 DS |
1143 | if (ospf->t_distribute_update) { |
1144 | XFREE(MTYPE_OSPF_DIST_ARGS, args); | |
d62a17ae | 1145 | return; |
a68730c6 | 1146 | } |
d62a17ae | 1147 | |
1148 | /* Set timer. */ | |
1149 | ospf->t_distribute_update = NULL; | |
1150 | thread_add_timer_msec(master, ospf_distribute_list_update_timer, | |
b5a8894d | 1151 | (void **)args, ospf->min_ls_interval, |
d62a17ae | 1152 | &ospf->t_distribute_update); |
718e3744 | 1153 | } |
1154 | ||
1155 | /* If access-list is updated, apply some check. */ | |
d62a17ae | 1156 | static void ospf_filter_update(struct access_list *access) |
718e3744 | 1157 | { |
d62a17ae | 1158 | struct ospf *ospf; |
1159 | int type; | |
1160 | int abr_inv = 0; | |
1161 | struct ospf_area *area; | |
b5a8894d | 1162 | struct listnode *node, *n1; |
d62a17ae | 1163 | |
1164 | /* If OSPF instance does not exist, return right now. */ | |
b5a8894d | 1165 | if (listcount(om->ospf) == 0) |
d62a17ae | 1166 | return; |
1167 | ||
b5a8894d | 1168 | /* Iterate all ospf [VRF] instances */ |
43b8d1d8 | 1169 | for (ALL_LIST_ELEMENTS_RO(om->ospf, n1, ospf)) { |
b5a8894d CS |
1170 | /* Update distribute-list, and apply filter. */ |
1171 | for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) { | |
1172 | struct list *red_list; | |
1173 | struct listnode *node; | |
1174 | struct ospf_redist *red; | |
1175 | ||
1176 | red_list = ospf->redist[type]; | |
1177 | if (red_list) | |
1178 | for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) { | |
1179 | if (ROUTEMAP(red)) { | |
1180 | /* if route-map is not NULL it may be | |
1181 | * using this access list */ | |
1182 | ospf_distribute_list_update( | |
1183 | ospf, | |
1184 | type, red->instance); | |
1185 | } | |
d62a17ae | 1186 | } |
d62a17ae | 1187 | |
b5a8894d CS |
1188 | /* There is place for route-map for default-information |
1189 | * (ZEBRA_ROUTE_MAX), | |
1190 | * but no distribute list. */ | |
1191 | if (type == ZEBRA_ROUTE_MAX) | |
1192 | break; | |
1193 | ||
1194 | if (DISTRIBUTE_NAME(ospf, type)) { | |
1195 | /* Keep old access-list for distribute-list. */ | |
1196 | struct access_list *old = DISTRIBUTE_LIST(ospf, | |
1197 | type); | |
1198 | ||
1199 | /* Update access-list for distribute-list. */ | |
1200 | DISTRIBUTE_LIST(ospf, type) = access_list_lookup( | |
1201 | AFI_IP, DISTRIBUTE_NAME(ospf, type)); | |
1202 | ||
1203 | /* No update for this distribute type. */ | |
1204 | if (old == NULL && DISTRIBUTE_LIST(ospf, type) == NULL) | |
1205 | continue; | |
1206 | ||
1207 | /* Schedule distribute-list update timer. */ | |
1208 | if (DISTRIBUTE_LIST(ospf, type) == NULL | |
1209 | || strcmp(DISTRIBUTE_NAME(ospf, type), access->name) | |
1210 | == 0) | |
1211 | ospf_distribute_list_update(ospf, type, 0); | |
1212 | } | |
d62a17ae | 1213 | } |
d62a17ae | 1214 | |
b5a8894d CS |
1215 | /* Update Area access-list. */ |
1216 | for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { | |
1217 | if (EXPORT_NAME(area)) { | |
1218 | EXPORT_LIST(area) = NULL; | |
1219 | abr_inv++; | |
1220 | } | |
d62a17ae | 1221 | |
b5a8894d CS |
1222 | if (IMPORT_NAME(area)) { |
1223 | IMPORT_LIST(area) = NULL; | |
1224 | abr_inv++; | |
1225 | } | |
d62a17ae | 1226 | } |
d62a17ae | 1227 | |
b5a8894d CS |
1228 | /* Schedule ABR tasks -- this will be changed -- takada. */ |
1229 | if (IS_OSPF_ABR(ospf) && abr_inv) | |
1230 | ospf_schedule_abr_task(ospf); | |
1231 | } | |
718e3744 | 1232 | } |
dd669bb0 | 1233 | |
1234 | /* If prefix-list is updated, do some updates. */ | |
d62a17ae | 1235 | void ospf_prefix_list_update(struct prefix_list *plist) |
dd669bb0 | 1236 | { |
b5a8894d | 1237 | struct ospf *ospf = NULL; |
d62a17ae | 1238 | int type; |
1239 | int abr_inv = 0; | |
1240 | struct ospf_area *area; | |
b5a8894d | 1241 | struct listnode *node, *n1; |
d62a17ae | 1242 | |
1243 | /* If OSPF instatnce does not exist, return right now. */ | |
b5a8894d | 1244 | if (listcount(om->ospf) == 0) |
d62a17ae | 1245 | return; |
1246 | ||
b5a8894d CS |
1247 | /* Iterate all ospf [VRF] instances */ |
1248 | for (ALL_LIST_ELEMENTS_RO(om->ospf, n1, ospf)) { | |
1249 | ||
1250 | /* Update all route-maps which are used | |
1251 | * as redistribution filters. | |
1252 | * They might use prefix-list. | |
1253 | */ | |
1254 | for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) { | |
1255 | struct list *red_list; | |
1256 | struct listnode *node; | |
1257 | struct ospf_redist *red; | |
1258 | ||
1259 | red_list = ospf->redist[type]; | |
1260 | if (red_list) { | |
1261 | for (ALL_LIST_ELEMENTS_RO(red_list, | |
1262 | node, red)) { | |
1263 | if (ROUTEMAP(red)) { | |
1264 | /* if route-map is not NULL | |
1265 | * it may be using | |
1266 | * this prefix list */ | |
1267 | ospf_distribute_list_update( | |
1268 | ospf, type, | |
1269 | red->instance); | |
1270 | } | |
d62a17ae | 1271 | } |
1272 | } | |
b5a8894d | 1273 | } |
d62a17ae | 1274 | |
b5a8894d CS |
1275 | /* Update area filter-lists. */ |
1276 | for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { | |
1277 | /* Update filter-list in. */ | |
1278 | if (PREFIX_NAME_IN(area)) | |
1279 | if (strcmp(PREFIX_NAME_IN(area), | |
1280 | prefix_list_name(plist)) == 0) { | |
1281 | PREFIX_LIST_IN(area) = | |
1282 | prefix_list_lookup( | |
1283 | AFI_IP, | |
1284 | PREFIX_NAME_IN(area)); | |
1285 | abr_inv++; | |
1286 | } | |
d62a17ae | 1287 | |
b5a8894d CS |
1288 | /* Update filter-list out. */ |
1289 | if (PREFIX_NAME_OUT(area)) | |
1290 | if (strcmp(PREFIX_NAME_OUT(area), | |
1291 | prefix_list_name(plist)) == 0) { | |
1292 | PREFIX_LIST_IN(area) = | |
1293 | prefix_list_lookup( | |
1294 | AFI_IP, | |
1295 | PREFIX_NAME_OUT(area)); | |
1296 | abr_inv++; | |
1297 | } | |
1298 | } | |
d62a17ae | 1299 | |
b5a8894d CS |
1300 | /* Schedule ABR task. */ |
1301 | if (IS_OSPF_ABR(ospf) && abr_inv) | |
1302 | ospf_schedule_abr_task(ospf); | |
1303 | } | |
dd669bb0 | 1304 | } |
cf795c5d | 1305 | |
d62a17ae | 1306 | static struct ospf_distance *ospf_distance_new(void) |
718e3744 | 1307 | { |
d62a17ae | 1308 | return XCALLOC(MTYPE_OSPF_DISTANCE, sizeof(struct ospf_distance)); |
718e3744 | 1309 | } |
1310 | ||
d62a17ae | 1311 | static void ospf_distance_free(struct ospf_distance *odistance) |
718e3744 | 1312 | { |
d62a17ae | 1313 | XFREE(MTYPE_OSPF_DISTANCE, odistance); |
718e3744 | 1314 | } |
1315 | ||
d62a17ae | 1316 | int ospf_distance_set(struct vty *vty, struct ospf *ospf, |
1317 | const char *distance_str, const char *ip_str, | |
1318 | const char *access_list_str) | |
718e3744 | 1319 | { |
d62a17ae | 1320 | int ret; |
1321 | struct prefix_ipv4 p; | |
1322 | u_char distance; | |
1323 | struct route_node *rn; | |
1324 | struct ospf_distance *odistance; | |
1325 | ||
1326 | ret = str2prefix_ipv4(ip_str, &p); | |
1327 | if (ret == 0) { | |
1328 | vty_out(vty, "Malformed prefix\n"); | |
1329 | return CMD_WARNING_CONFIG_FAILED; | |
1330 | } | |
1331 | ||
1332 | distance = atoi(distance_str); | |
1333 | ||
1334 | /* Get OSPF distance node. */ | |
1335 | rn = route_node_get(ospf->distance_table, (struct prefix *)&p); | |
1336 | if (rn->info) { | |
1337 | odistance = rn->info; | |
1338 | route_unlock_node(rn); | |
1339 | } else { | |
1340 | odistance = ospf_distance_new(); | |
1341 | rn->info = odistance; | |
1342 | } | |
1343 | ||
1344 | /* Set distance value. */ | |
1345 | odistance->distance = distance; | |
1346 | ||
1347 | /* Reset access-list configuration. */ | |
1348 | if (odistance->access_list) { | |
1349 | free(odistance->access_list); | |
1350 | odistance->access_list = NULL; | |
1351 | } | |
1352 | if (access_list_str) | |
1353 | odistance->access_list = strdup(access_list_str); | |
1354 | ||
1355 | return CMD_SUCCESS; | |
718e3744 | 1356 | } |
1357 | ||
d62a17ae | 1358 | int ospf_distance_unset(struct vty *vty, struct ospf *ospf, |
1359 | const char *distance_str, const char *ip_str, | |
1360 | char const *access_list_str) | |
718e3744 | 1361 | { |
d62a17ae | 1362 | int ret; |
1363 | struct prefix_ipv4 p; | |
1364 | struct route_node *rn; | |
1365 | struct ospf_distance *odistance; | |
1366 | ||
1367 | ret = str2prefix_ipv4(ip_str, &p); | |
1368 | if (ret == 0) { | |
1369 | vty_out(vty, "Malformed prefix\n"); | |
1370 | return CMD_WARNING_CONFIG_FAILED; | |
1371 | } | |
1372 | ||
1373 | rn = route_node_lookup(ospf->distance_table, (struct prefix *)&p); | |
1374 | if (!rn) { | |
1375 | vty_out(vty, "Can't find specified prefix\n"); | |
1376 | return CMD_WARNING_CONFIG_FAILED; | |
1377 | } | |
1378 | ||
1379 | odistance = rn->info; | |
1380 | ||
1381 | if (odistance->access_list) | |
1382 | free(odistance->access_list); | |
1383 | ospf_distance_free(odistance); | |
1384 | ||
1385 | rn->info = NULL; | |
1386 | route_unlock_node(rn); | |
1387 | route_unlock_node(rn); | |
1388 | ||
1389 | return CMD_SUCCESS; | |
718e3744 | 1390 | } |
1391 | ||
d62a17ae | 1392 | void ospf_distance_reset(struct ospf *ospf) |
718e3744 | 1393 | { |
d62a17ae | 1394 | struct route_node *rn; |
1395 | struct ospf_distance *odistance; | |
1396 | ||
1397 | for (rn = route_top(ospf->distance_table); rn; rn = route_next(rn)) | |
1398 | if ((odistance = rn->info) != NULL) { | |
1399 | if (odistance->access_list) | |
1400 | free(odistance->access_list); | |
1401 | ospf_distance_free(odistance); | |
1402 | rn->info = NULL; | |
1403 | route_unlock_node(rn); | |
1404 | } | |
718e3744 | 1405 | } |
1406 | ||
b5a8894d CS |
1407 | u_char ospf_distance_apply(struct ospf *ospf, struct prefix_ipv4 *p, |
1408 | struct ospf_route *or) | |
718e3744 | 1409 | { |
718e3744 | 1410 | |
d62a17ae | 1411 | if (ospf == NULL) |
1412 | return 0; | |
718e3744 | 1413 | |
d62a17ae | 1414 | if (ospf->distance_intra) |
1415 | if (or->path_type == OSPF_PATH_INTRA_AREA) | |
1416 | return ospf->distance_intra; | |
718e3744 | 1417 | |
d62a17ae | 1418 | if (ospf->distance_inter) |
1419 | if (or->path_type == OSPF_PATH_INTER_AREA) | |
1420 | return ospf->distance_inter; | |
718e3744 | 1421 | |
d62a17ae | 1422 | if (ospf->distance_external) |
1423 | if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL || | |
1424 | or->path_type == OSPF_PATH_TYPE2_EXTERNAL) | |
1425 | return ospf->distance_external; | |
cf795c5d | 1426 | |
d62a17ae | 1427 | if (ospf->distance_all) |
1428 | return ospf->distance_all; | |
718e3744 | 1429 | |
d62a17ae | 1430 | return 0; |
718e3744 | 1431 | } |
1432 | ||
b5a8894d CS |
1433 | void ospf_zebra_vrf_register(struct ospf *ospf) |
1434 | { | |
1435 | if (!zclient || zclient->sock < 0 || !ospf) | |
1436 | return; | |
1437 | ||
1438 | if (ospf->vrf_id != VRF_DEFAULT && ospf->vrf_id != VRF_UNKNOWN) { | |
1439 | if (IS_DEBUG_OSPF_EVENT) | |
1440 | zlog_debug("%s: Register VRF %s id %u", | |
1441 | __PRETTY_FUNCTION__, | |
1442 | ospf_vrf_id_to_name(ospf->vrf_id), | |
1443 | ospf->vrf_id); | |
1444 | zclient_send_reg_requests(zclient, ospf->vrf_id); | |
1445 | } | |
1446 | } | |
1447 | ||
1448 | void ospf_zebra_vrf_deregister(struct ospf *ospf) | |
1449 | { | |
1450 | if (!zclient || zclient->sock < 0 || !ospf) | |
1451 | return; | |
1452 | ||
1453 | if (ospf->vrf_id != VRF_DEFAULT && ospf->vrf_id != VRF_UNKNOWN) { | |
1454 | if (IS_DEBUG_OSPF_EVENT) | |
1455 | zlog_debug("%s: De-Register VRF %s id %u", | |
1456 | __PRETTY_FUNCTION__, | |
1457 | ospf_vrf_id_to_name(ospf->vrf_id), | |
1458 | ospf->vrf_id); | |
1459 | /* Deregister for router-id, interfaces, | |
1460 | * redistributed routes. */ | |
1461 | zclient_send_dereg_requests(zclient, ospf->vrf_id); | |
1462 | } | |
1463 | } | |
d62a17ae | 1464 | static void ospf_zebra_connected(struct zclient *zclient) |
7076bb2f | 1465 | { |
d62a17ae | 1466 | /* Send the client registration */ |
1467 | bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER); | |
2376c3f2 | 1468 | |
d62a17ae | 1469 | zclient_send_reg_requests(zclient, VRF_DEFAULT); |
7076bb2f FL |
1470 | } |
1471 | ||
d62a17ae | 1472 | void ospf_zebra_init(struct thread_master *master, u_short instance) |
718e3744 | 1473 | { |
d62a17ae | 1474 | /* Allocate zebra structure. */ |
1475 | zclient = zclient_new(master); | |
1476 | zclient_init(zclient, ZEBRA_ROUTE_OSPF, instance); | |
1477 | zclient->zebra_connected = ospf_zebra_connected; | |
1478 | zclient->router_id_update = ospf_router_id_update_zebra; | |
1479 | zclient->interface_add = ospf_interface_add; | |
1480 | zclient->interface_delete = ospf_interface_delete; | |
1481 | zclient->interface_up = ospf_interface_state_up; | |
1482 | zclient->interface_down = ospf_interface_state_down; | |
1483 | zclient->interface_address_add = ospf_interface_address_add; | |
1484 | zclient->interface_address_delete = ospf_interface_address_delete; | |
1485 | zclient->interface_link_params = ospf_interface_link_params; | |
b5a8894d | 1486 | zclient->interface_vrf_update = ospf_interface_vrf_update; |
d62a17ae | 1487 | |
74489921 RW |
1488 | zclient->redistribute_route_add = ospf_zebra_read_route; |
1489 | zclient->redistribute_route_del = ospf_zebra_read_route; | |
d62a17ae | 1490 | |
1491 | access_list_add_hook(ospf_filter_update); | |
1492 | access_list_delete_hook(ospf_filter_update); | |
1493 | prefix_list_add_hook(ospf_prefix_list_update); | |
1494 | prefix_list_delete_hook(ospf_prefix_list_update); | |
718e3744 | 1495 | } |