]>
Commit | Line | Data |
---|---|---|
eb5d44eb | 1 | /* |
d62a17ae | 2 | * IS-IS Rout(e)ing protocol - isis_zebra.c |
eb5d44eb | 3 | * |
4 | * Copyright (C) 2001,2002 Sampo Saaristo | |
d62a17ae | 5 | * Tampere University of Technology |
eb5d44eb | 6 | * Institute of Communications Engineering |
f3ccedaa | 7 | * Copyright (C) 2013-2015 Christian Franke <chris@opensourcerouting.org> |
eb5d44eb | 8 | * |
d62a17ae | 9 | * This program is free software; you can redistribute it and/or modify it |
10 | * under the terms of the GNU General Public Licenseas published by the Free | |
11 | * Software Foundation; either version 2 of the License, or (at your option) | |
eb5d44eb | 12 | * any later version. |
13 | * | |
d62a17ae | 14 | * This program is distributed in the hope that it will be useful,but WITHOUT |
15 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
16 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
eb5d44eb | 17 | * more details. |
896014f4 DL |
18 | * |
19 | * You should have received a copy of the GNU General Public License along | |
20 | * with this program; see the file COPYING; if not, write to the Free Software | |
21 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
eb5d44eb | 22 | */ |
23 | ||
24 | #include <zebra.h> | |
eb5d44eb | 25 | |
26 | #include "thread.h" | |
27 | #include "command.h" | |
28 | #include "memory.h" | |
29 | #include "log.h" | |
30 | #include "if.h" | |
31 | #include "network.h" | |
32 | #include "prefix.h" | |
33 | #include "zclient.h" | |
34 | #include "stream.h" | |
35 | #include "linklist.h" | |
f3ccedaa | 36 | #include "nexthop.h" |
7076bb2f | 37 | #include "vrf.h" |
eb5d44eb | 38 | |
c89c05dd | 39 | #include "isisd/dict.h" |
eb5d44eb | 40 | #include "isisd/isis_constants.h" |
41 | #include "isisd/isis_common.h" | |
3f045a08 JB |
42 | #include "isisd/isis_flags.h" |
43 | #include "isisd/isis_misc.h" | |
44 | #include "isisd/isis_circuit.h" | |
c89c05dd | 45 | #include "isisd/isisd.h" |
eb5d44eb | 46 | #include "isisd/isis_circuit.h" |
47 | #include "isisd/isis_csm.h" | |
3f045a08 | 48 | #include "isisd/isis_lsp.h" |
eb5d44eb | 49 | #include "isisd/isis_route.h" |
50 | #include "isisd/isis_zebra.h" | |
f8c06e2c | 51 | #include "isisd/isis_te.h" |
eb5d44eb | 52 | |
53 | struct zclient *zclient = NULL; | |
54 | ||
18a6dce6 | 55 | /* Router-id update message from zebra. */ |
d62a17ae | 56 | static int isis_router_id_update_zebra(int command, struct zclient *zclient, |
57 | zebra_size_t length, vrf_id_t vrf_id) | |
18a6dce6 | 58 | { |
d62a17ae | 59 | struct isis_area *area; |
60 | struct listnode *node; | |
61 | struct prefix router_id; | |
62 | ||
63 | /* | |
64 | * If ISIS TE is enable, TE Router ID is set through specific command. | |
65 | * See mpls_te_router_addr() command in isis_te.c | |
66 | */ | |
67 | if (IS_MPLS_TE(isisMplsTE)) | |
68 | return 0; | |
69 | ||
70 | zebra_router_id_update_read(zclient->ibuf, &router_id); | |
71 | if (isis->router_id == router_id.u.prefix4.s_addr) | |
72 | return 0; | |
73 | ||
74 | isis->router_id = router_id.u.prefix4.s_addr; | |
75 | for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) | |
76 | if (listcount(area->area_addrs) > 0) | |
77 | lsp_regenerate_schedule(area, area->is_type, 0); | |
78 | ||
79 | return 0; | |
18a6dce6 | 80 | } |
eb5d44eb | 81 | |
d62a17ae | 82 | static int isis_zebra_if_add(int command, struct zclient *zclient, |
83 | zebra_size_t length, vrf_id_t vrf_id) | |
eb5d44eb | 84 | { |
d62a17ae | 85 | struct interface *ifp; |
eb5d44eb | 86 | |
d62a17ae | 87 | ifp = zebra_interface_add_read(zclient->ibuf, vrf_id); |
f390d2c7 | 88 | |
d62a17ae | 89 | if (isis->debugs & DEBUG_ZEBRA) |
90 | zlog_debug( | |
91 | "Zebra I/F add: %s index %d flags %ld metric %d mtu %d", | |
92 | ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, | |
93 | ifp->mtu); | |
f390d2c7 | 94 | |
d62a17ae | 95 | if (if_is_operative(ifp)) |
96 | isis_csm_state_change(IF_UP_FROM_Z, circuit_scan_by_ifp(ifp), | |
97 | ifp); | |
f390d2c7 | 98 | |
d62a17ae | 99 | return 0; |
eb5d44eb | 100 | } |
101 | ||
d62a17ae | 102 | static int isis_zebra_if_del(int command, struct zclient *zclient, |
103 | zebra_size_t length, vrf_id_t vrf_id) | |
eb5d44eb | 104 | { |
d62a17ae | 105 | struct interface *ifp; |
106 | struct stream *s; | |
eb5d44eb | 107 | |
d62a17ae | 108 | s = zclient->ibuf; |
109 | ifp = zebra_interface_state_read(s, vrf_id); | |
f390d2c7 | 110 | |
d62a17ae | 111 | if (!ifp) |
112 | return 0; | |
eb5d44eb | 113 | |
d62a17ae | 114 | if (if_is_operative(ifp)) |
115 | zlog_warn("Zebra: got delete of %s, but interface is still up", | |
116 | ifp->name); | |
eb5d44eb | 117 | |
d62a17ae | 118 | if (isis->debugs & DEBUG_ZEBRA) |
119 | zlog_debug( | |
120 | "Zebra I/F delete: %s index %d flags %ld metric %d mtu %d", | |
121 | ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, | |
122 | ifp->mtu); | |
eb5d44eb | 123 | |
d62a17ae | 124 | isis_csm_state_change(IF_DOWN_FROM_Z, circuit_scan_by_ifp(ifp), ifp); |
d2fc8896 | 125 | |
d62a17ae | 126 | /* Cannot call if_delete because we should retain the pseudo interface |
127 | in case there is configuration info attached to it. */ | |
128 | if_delete_retain(ifp); | |
f390d2c7 | 129 | |
d62a17ae | 130 | ifp->ifindex = IFINDEX_DELETED; |
d2fc8896 | 131 | |
d62a17ae | 132 | return 0; |
eb5d44eb | 133 | } |
134 | ||
d62a17ae | 135 | static int isis_zebra_if_state_up(int command, struct zclient *zclient, |
136 | zebra_size_t length, vrf_id_t vrf_id) | |
eb5d44eb | 137 | { |
d62a17ae | 138 | struct interface *ifp; |
f390d2c7 | 139 | |
d62a17ae | 140 | ifp = zebra_interface_state_read(zclient->ibuf, vrf_id); |
f390d2c7 | 141 | |
d62a17ae | 142 | if (ifp == NULL) |
143 | return 0; | |
f390d2c7 | 144 | |
d62a17ae | 145 | isis_csm_state_change(IF_UP_FROM_Z, circuit_scan_by_ifp(ifp), ifp); |
f390d2c7 | 146 | |
d62a17ae | 147 | return 0; |
eb5d44eb | 148 | } |
149 | ||
d62a17ae | 150 | static int isis_zebra_if_state_down(int command, struct zclient *zclient, |
151 | zebra_size_t length, vrf_id_t vrf_id) | |
eb5d44eb | 152 | { |
d62a17ae | 153 | struct interface *ifp; |
154 | struct isis_circuit *circuit; | |
f390d2c7 | 155 | |
d62a17ae | 156 | ifp = zebra_interface_state_read(zclient->ibuf, vrf_id); |
f390d2c7 | 157 | |
d62a17ae | 158 | if (ifp == NULL) |
159 | return 0; | |
f390d2c7 | 160 | |
d62a17ae | 161 | circuit = isis_csm_state_change(IF_DOWN_FROM_Z, |
162 | circuit_scan_by_ifp(ifp), ifp); | |
163 | if (circuit) | |
164 | SET_FLAG(circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF); | |
f390d2c7 | 165 | |
d62a17ae | 166 | return 0; |
eb5d44eb | 167 | } |
168 | ||
d62a17ae | 169 | static int isis_zebra_if_address_add(int command, struct zclient *zclient, |
170 | zebra_size_t length, vrf_id_t vrf_id) | |
eb5d44eb | 171 | { |
d62a17ae | 172 | struct connected *c; |
173 | struct prefix *p; | |
174 | char buf[PREFIX2STR_BUFFER]; | |
eb5d44eb | 175 | |
d62a17ae | 176 | c = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, |
177 | zclient->ibuf, vrf_id); | |
f390d2c7 | 178 | |
d62a17ae | 179 | if (c == NULL) |
180 | return 0; | |
f390d2c7 | 181 | |
d62a17ae | 182 | p = c->address; |
f390d2c7 | 183 | |
d62a17ae | 184 | prefix2str(p, buf, sizeof(buf)); |
eb5d44eb | 185 | #ifdef EXTREME_DEBUG |
d62a17ae | 186 | if (p->family == AF_INET) |
187 | zlog_debug("connected IP address %s", buf); | |
188 | if (p->family == AF_INET6) | |
189 | zlog_debug("connected IPv6 address %s", buf); | |
eb5d44eb | 190 | #endif /* EXTREME_DEBUG */ |
d62a17ae | 191 | if (if_is_operative(c->ifp)) |
192 | isis_circuit_add_addr(circuit_scan_by_ifp(c->ifp), c); | |
eb5d44eb | 193 | |
d62a17ae | 194 | return 0; |
eb5d44eb | 195 | } |
196 | ||
d62a17ae | 197 | static int isis_zebra_if_address_del(int command, struct zclient *client, |
198 | zebra_size_t length, vrf_id_t vrf_id) | |
eb5d44eb | 199 | { |
d62a17ae | 200 | struct connected *c; |
201 | struct interface *ifp; | |
1cd80845 | 202 | #ifdef EXTREME_DEBUG |
d62a17ae | 203 | struct prefix *p; |
204 | char buf[PREFIX2STR_BUFFER]; | |
1cd80845 | 205 | #endif /* EXTREME_DEBUG */ |
eb5d44eb | 206 | |
d62a17ae | 207 | c = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, |
208 | zclient->ibuf, vrf_id); | |
f390d2c7 | 209 | |
d62a17ae | 210 | if (c == NULL) |
211 | return 0; | |
f390d2c7 | 212 | |
d62a17ae | 213 | ifp = c->ifp; |
f390d2c7 | 214 | |
f891f443 | 215 | #ifdef EXTREME_DEBUG |
d62a17ae | 216 | p = c->address; |
217 | prefix2str(p, buf, sizeof(buf)); | |
f891f443 | 218 | |
d62a17ae | 219 | if (p->family == AF_INET) |
220 | zlog_debug("disconnected IP address %s", buf); | |
221 | if (p->family == AF_INET6) | |
222 | zlog_debug("disconnected IPv6 address %s", buf); | |
f891f443 | 223 | #endif /* EXTREME_DEBUG */ |
f390d2c7 | 224 | |
d62a17ae | 225 | if (if_is_operative(ifp)) |
226 | isis_circuit_del_addr(circuit_scan_by_ifp(ifp), c); | |
227 | connected_free(c); | |
f390d2c7 | 228 | |
d62a17ae | 229 | return 0; |
eb5d44eb | 230 | } |
231 | ||
d62a17ae | 232 | static int isis_zebra_link_params(int command, struct zclient *zclient, |
233 | zebra_size_t length) | |
f8c06e2c | 234 | { |
d62a17ae | 235 | struct interface *ifp; |
f8c06e2c | 236 | |
d62a17ae | 237 | ifp = zebra_interface_link_params_read(zclient->ibuf); |
f8c06e2c | 238 | |
d62a17ae | 239 | if (ifp == NULL) |
240 | return 0; | |
f8c06e2c | 241 | |
d62a17ae | 242 | /* Update TE TLV */ |
243 | isis_mpls_te_update(ifp); | |
f8c06e2c | 244 | |
d62a17ae | 245 | return 0; |
f8c06e2c OD |
246 | } |
247 | ||
d62a17ae | 248 | static void isis_zebra_route_add_ipv4(struct prefix *prefix, |
249 | struct isis_route_info *route_info) | |
eb5d44eb | 250 | { |
c0721de4 RW |
251 | struct zapi_route api; |
252 | struct zapi_nexthop *api_nh; | |
d62a17ae | 253 | struct isis_nexthop *nexthop; |
254 | struct listnode *node; | |
c0721de4 | 255 | int count = 0; |
d62a17ae | 256 | |
257 | if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED)) | |
258 | return; | |
259 | ||
c0721de4 RW |
260 | memset(&api, 0, sizeof(api)); |
261 | api.vrf_id = VRF_DEFAULT; | |
262 | api.type = ZEBRA_ROUTE_ISIS; | |
263 | api.safi = SAFI_UNICAST; | |
264 | api.prefix = *prefix; | |
265 | SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); | |
266 | SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); | |
267 | api.metric = route_info->cost; | |
2097cd8a | 268 | #if 0 |
c0721de4 RW |
269 | SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); |
270 | api.distance = route_info->depth; | |
2097cd8a | 271 | #endif |
f390d2c7 | 272 | |
d00061ea RW |
273 | /* Nexthop, ifindex, distance and metric information */ |
274 | for (ALL_LIST_ELEMENTS_RO(route_info->nexthops, node, nexthop)) { | |
c0721de4 | 275 | api_nh = &api.nexthops[count]; |
d00061ea RW |
276 | /* FIXME: can it be ? */ |
277 | if (nexthop->ip.s_addr != INADDR_ANY) { | |
c0721de4 RW |
278 | api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX; |
279 | api_nh->gate.ipv4 = nexthop->ip; | |
d00061ea | 280 | } else { |
c0721de4 | 281 | api_nh->type = NEXTHOP_TYPE_IFINDEX; |
d62a17ae | 282 | } |
c0721de4 RW |
283 | api_nh->ifindex = nexthop->ifindex; |
284 | count++; | |
d00061ea | 285 | } |
c0721de4 RW |
286 | if (!count) |
287 | return; | |
288 | ||
289 | api.nexthop_num = count; | |
d62a17ae | 290 | |
c0721de4 | 291 | zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api); |
d00061ea RW |
292 | SET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED); |
293 | UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC); | |
eb5d44eb | 294 | } |
295 | ||
d62a17ae | 296 | static void isis_zebra_route_del_ipv4(struct prefix *prefix, |
297 | struct isis_route_info *route_info) | |
eb5d44eb | 298 | { |
c0721de4 | 299 | struct zapi_route api; |
d62a17ae | 300 | |
d62a17ae | 301 | UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED); |
302 | ||
c0721de4 | 303 | memset(&api, 0, sizeof(api)); |
d00061ea RW |
304 | api.vrf_id = VRF_DEFAULT; |
305 | api.type = ZEBRA_ROUTE_ISIS; | |
d00061ea | 306 | api.safi = SAFI_UNICAST; |
c0721de4 RW |
307 | api.prefix = *prefix; |
308 | ||
309 | zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api); | |
eb5d44eb | 310 | } |
311 | ||
d62a17ae | 312 | static void isis_zebra_route_add_ipv6(struct prefix *prefix, |
313 | struct isis_route_info *route_info) | |
eb5d44eb | 314 | { |
c0721de4 RW |
315 | struct zapi_route api; |
316 | struct zapi_nexthop *api_nh; | |
d62a17ae | 317 | struct isis_nexthop6 *nexthop6; |
d62a17ae | 318 | struct listnode *node; |
c0721de4 | 319 | int count = 0; |
d62a17ae | 320 | |
321 | if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED)) | |
322 | return; | |
323 | ||
c0721de4 | 324 | memset(&api, 0, sizeof(api)); |
d62a17ae | 325 | api.vrf_id = VRF_DEFAULT; |
326 | api.type = ZEBRA_ROUTE_ISIS; | |
d62a17ae | 327 | api.safi = SAFI_UNICAST; |
328 | SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); | |
d62a17ae | 329 | SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); |
330 | api.metric = route_info->cost; | |
eb5d44eb | 331 | #if 0 |
c0721de4 | 332 | SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); |
d00061ea | 333 | api.distance = route_info->depth; |
eb5d44eb | 334 | #endif |
c0721de4 | 335 | api.prefix = *prefix; |
f390d2c7 | 336 | |
d62a17ae | 337 | /* for each nexthop */ |
d62a17ae | 338 | for (ALL_LIST_ELEMENTS_RO(route_info->nexthops6, node, nexthop6)) { |
339 | if (!IN6_IS_ADDR_LINKLOCAL(&nexthop6->ip6) | |
340 | && !IN6_IS_ADDR_UNSPECIFIED(&nexthop6->ip6)) { | |
d62a17ae | 341 | continue; |
342 | } | |
343 | ||
c0721de4 RW |
344 | api_nh = &api.nexthops[count]; |
345 | api_nh->gate.ipv6 = nexthop6->ip6; | |
346 | api_nh->ifindex = nexthop6->ifindex; | |
347 | api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX; | |
348 | count++; | |
d62a17ae | 349 | } |
c0721de4 RW |
350 | if (!count) |
351 | return; | |
f390d2c7 | 352 | |
c0721de4 | 353 | api.nexthop_num = count; |
f390d2c7 | 354 | |
c0721de4 RW |
355 | zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api); |
356 | SET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED); | |
357 | UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC); | |
eb5d44eb | 358 | } |
359 | ||
d62a17ae | 360 | static void isis_zebra_route_del_ipv6(struct prefix *prefix, |
361 | struct isis_route_info *route_info) | |
eb5d44eb | 362 | { |
c0721de4 | 363 | struct zapi_route api; |
d62a17ae | 364 | |
365 | if (!CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED)) | |
366 | return; | |
367 | ||
c0721de4 | 368 | memset(&api, 0, sizeof(api)); |
d62a17ae | 369 | api.vrf_id = VRF_DEFAULT; |
370 | api.type = ZEBRA_ROUTE_ISIS; | |
d62a17ae | 371 | api.safi = SAFI_UNICAST; |
c0721de4 | 372 | api.prefix = *prefix; |
f390d2c7 | 373 | |
c0721de4 RW |
374 | zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api); |
375 | UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED); | |
eb5d44eb | 376 | } |
377 | ||
d62a17ae | 378 | void isis_zebra_route_update(struct prefix *prefix, |
379 | struct isis_route_info *route_info) | |
eb5d44eb | 380 | { |
d62a17ae | 381 | if (zclient->sock < 0) |
382 | return; | |
383 | ||
d62a17ae | 384 | if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ACTIVE)) { |
385 | if (prefix->family == AF_INET) | |
386 | isis_zebra_route_add_ipv4(prefix, route_info); | |
387 | else if (prefix->family == AF_INET6) | |
388 | isis_zebra_route_add_ipv6(prefix, route_info); | |
389 | } else { | |
390 | if (prefix->family == AF_INET) | |
391 | isis_zebra_route_del_ipv4(prefix, route_info); | |
392 | else if (prefix->family == AF_INET6) | |
393 | isis_zebra_route_del_ipv6(prefix, route_info); | |
394 | } | |
395 | return; | |
eb5d44eb | 396 | } |
397 | ||
d62a17ae | 398 | static int isis_zebra_read_ipv4(int command, struct zclient *zclient, |
399 | zebra_size_t length, vrf_id_t vrf_id) | |
eb5d44eb | 400 | { |
d62a17ae | 401 | struct stream *stream; |
402 | struct zapi_ipv4 api; | |
403 | struct prefix_ipv4 p; | |
404 | struct prefix *p_generic = (struct prefix *)&p; | |
405 | ||
406 | stream = zclient->ibuf; | |
407 | memset(&api, 0, sizeof(api)); | |
408 | memset(&p, 0, sizeof(struct prefix_ipv4)); | |
409 | ||
410 | api.type = stream_getc(stream); | |
411 | api.instance = stream_getw(stream); | |
412 | api.flags = stream_getl(stream); | |
413 | api.message = stream_getc(stream); | |
414 | ||
415 | p.family = AF_INET; | |
416 | p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc(stream)); | |
417 | stream_get(&p.prefix, stream, PSIZE(p.prefixlen)); | |
418 | ||
419 | if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { | |
420 | api.nexthop_num = stream_getc(stream); | |
421 | (void)stream_get_ipv4(stream); | |
422 | } | |
423 | if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) { | |
424 | api.ifindex_num = stream_getc(stream); | |
425 | stream_getl(stream); | |
426 | } | |
427 | if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) | |
428 | api.distance = stream_getc(stream); | |
429 | if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) | |
430 | api.metric = stream_getl(stream); | |
431 | ||
432 | /* | |
433 | * Avoid advertising a false default reachability. (A default | |
434 | * route installed by IS-IS gets redistributed from zebra back | |
435 | * into IS-IS causing us to start advertising default reachabity | |
436 | * without this check) | |
437 | */ | |
438 | if (p.prefixlen == 0 && api.type == ZEBRA_ROUTE_ISIS) | |
89a8b5ca | 439 | command = ZEBRA_REDISTRIBUTE_IPV4_DEL; |
d62a17ae | 440 | |
441 | if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) | |
442 | isis_redist_add(api.type, p_generic, api.distance, api.metric); | |
443 | else | |
444 | isis_redist_delete(api.type, p_generic); | |
445 | ||
446 | return 0; | |
eb5d44eb | 447 | } |
448 | ||
d62a17ae | 449 | static int isis_zebra_read_ipv6(int command, struct zclient *zclient, |
450 | zebra_size_t length, vrf_id_t vrf_id) | |
eb5d44eb | 451 | { |
d62a17ae | 452 | struct stream *stream; |
453 | struct zapi_ipv6 api; | |
454 | struct prefix_ipv6 p; | |
455 | struct prefix src_p; | |
456 | struct prefix *p_generic = (struct prefix *)&p; | |
457 | struct in6_addr nexthop; | |
458 | unsigned long ifindex __attribute__((unused)); | |
459 | ||
460 | stream = zclient->ibuf; | |
461 | memset(&api, 0, sizeof(api)); | |
462 | memset(&p, 0, sizeof(struct prefix_ipv6)); | |
463 | memset(&nexthop, 0, sizeof(nexthop)); | |
464 | ifindex = 0; | |
465 | ||
466 | api.type = stream_getc(stream); | |
467 | api.instance = stream_getw(stream); | |
468 | api.flags = stream_getl(stream); | |
469 | api.message = stream_getc(stream); | |
470 | ||
471 | p.family = AF_INET6; | |
472 | p.prefixlen = stream_getc(stream); | |
473 | stream_get(&p.prefix, stream, PSIZE(p.prefixlen)); | |
474 | ||
475 | memset(&src_p, 0, sizeof(struct prefix)); | |
476 | src_p.family = AF_INET6; | |
477 | if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) { | |
478 | src_p.prefixlen = stream_getc(stream); | |
479 | stream_get(&src_p.u.prefix6, stream, PSIZE(src_p.prefixlen)); | |
480 | } | |
481 | ||
482 | if (src_p.prefixlen) | |
483 | /* we completely ignore srcdest routes for now. */ | |
484 | return 0; | |
485 | ||
486 | if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { | |
487 | api.nexthop_num = stream_getc(stream); /* this is always 1 */ | |
488 | stream_get(&nexthop, stream, sizeof(nexthop)); | |
489 | } | |
490 | if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) { | |
491 | api.ifindex_num = stream_getc(stream); | |
492 | ifindex = stream_getl(stream); | |
493 | } | |
494 | if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) | |
495 | api.distance = stream_getc(stream); | |
496 | if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) | |
497 | api.metric = stream_getl(stream); | |
498 | if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG)) | |
499 | api.tag = stream_getl(stream); | |
500 | ||
501 | /* | |
502 | * Avoid advertising a false default reachability. (A default | |
503 | * route installed by IS-IS gets redistributed from zebra back | |
504 | * into IS-IS causing us to start advertising default reachabity | |
505 | * without this check) | |
506 | */ | |
507 | if (p.prefixlen == 0 && api.type == ZEBRA_ROUTE_ISIS) | |
89a8b5ca | 508 | command = ZEBRA_REDISTRIBUTE_IPV6_DEL; |
d62a17ae | 509 | |
510 | if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD) | |
511 | isis_redist_add(api.type, p_generic, api.distance, api.metric); | |
512 | else | |
513 | isis_redist_delete(api.type, p_generic); | |
514 | ||
515 | return 0; | |
eb5d44eb | 516 | } |
eb5d44eb | 517 | |
d62a17ae | 518 | int isis_distribute_list_update(int routetype) |
eb5d44eb | 519 | { |
d62a17ae | 520 | return 0; |
eb5d44eb | 521 | } |
522 | ||
d62a17ae | 523 | void isis_zebra_redistribute_set(afi_t afi, int type) |
eb5d44eb | 524 | { |
d62a17ae | 525 | if (type == DEFAULT_ROUTE) |
526 | zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD, | |
527 | zclient, VRF_DEFAULT); | |
528 | else | |
529 | zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, afi, type, | |
530 | 0, VRF_DEFAULT); | |
f3ccedaa CF |
531 | } |
532 | ||
d62a17ae | 533 | void isis_zebra_redistribute_unset(afi_t afi, int type) |
f3ccedaa | 534 | { |
d62a17ae | 535 | if (type == DEFAULT_ROUTE) |
536 | zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, | |
537 | zclient, VRF_DEFAULT); | |
538 | else | |
539 | zclient_redistribute(ZEBRA_REDISTRIBUTE_DELETE, zclient, afi, | |
540 | type, 0, VRF_DEFAULT); | |
eb5d44eb | 541 | } |
542 | ||
d62a17ae | 543 | static void isis_zebra_connected(struct zclient *zclient) |
7076bb2f | 544 | { |
d62a17ae | 545 | zclient_send_reg_requests(zclient, VRF_DEFAULT); |
7076bb2f FL |
546 | } |
547 | ||
d62a17ae | 548 | void isis_zebra_init(struct thread_master *master) |
eb5d44eb | 549 | { |
d62a17ae | 550 | zclient = zclient_new(master); |
551 | zclient_init(zclient, ZEBRA_ROUTE_ISIS, 0); | |
552 | zclient->zebra_connected = isis_zebra_connected; | |
553 | zclient->router_id_update = isis_router_id_update_zebra; | |
554 | zclient->interface_add = isis_zebra_if_add; | |
555 | zclient->interface_delete = isis_zebra_if_del; | |
556 | zclient->interface_up = isis_zebra_if_state_up; | |
557 | zclient->interface_down = isis_zebra_if_state_down; | |
558 | zclient->interface_address_add = isis_zebra_if_address_add; | |
559 | zclient->interface_address_delete = isis_zebra_if_address_del; | |
560 | zclient->interface_link_params = isis_zebra_link_params; | |
561 | zclient->redistribute_route_ipv4_add = isis_zebra_read_ipv4; | |
562 | zclient->redistribute_route_ipv4_del = isis_zebra_read_ipv4; | |
563 | zclient->redistribute_route_ipv6_add = isis_zebra_read_ipv6; | |
564 | zclient->redistribute_route_ipv6_del = isis_zebra_read_ipv6; | |
565 | ||
566 | return; | |
eb5d44eb | 567 | } |
8d429559 | 568 | |
d62a17ae | 569 | void isis_zebra_stop(void) |
8d429559 | 570 | { |
d62a17ae | 571 | zclient_stop(zclient); |
572 | zclient_free(zclient); | |
8d429559 | 573 | } |