]> git.proxmox.com Git - mirror_frr.git/blame - zebra/redistribute.c
zebra: Refactor 'struct rib' to be 'struct route_entry'
[mirror_frr.git] / zebra / redistribute.c
CommitLineData
718e3744 1/* Redistribution Handler
2 * Copyright (C) 1998 Kunihiro Ishiguro
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
896014f4
DL
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
718e3744 19 */
20
21#include <zebra.h>
22
23#include "vector.h"
24#include "vty.h"
25#include "command.h"
26#include "prefix.h"
27#include "table.h"
28#include "stream.h"
29#include "zclient.h"
30#include "linklist.h"
31#include "log.h"
b72ede27 32#include "vrf.h"
05737783 33#include "srcdest_table.h"
718e3744 34
35#include "zebra/rib.h"
36#include "zebra/zserv.h"
7c551956
DS
37#include "zebra/zebra_ns.h"
38#include "zebra/zebra_vrf.h"
8902474b 39#include "zebra/zebra_routemap.h"
718e3744 40#include "zebra/redistribute.h"
41#include "zebra/debug.h"
18a6dce6 42#include "zebra/router-id.h"
4a1ab8e4 43#include "zebra/zebra_memory.h"
718e3744 44
244c1cdc
DS
45#define ZEBRA_PTM_SUPPORT
46
7a4bb9c5
DS
47/* array holding redistribute info about table redistribution */
48/* bit AFI is set if that AFI is redistributing routes from this table */
032bfaaf 49static int zebra_import_table_used[AFI_MAX][ZEBRA_KERNEL_TABLE_MAX];
7a4bb9c5
DS
50static u_int32_t zebra_import_table_distance[AFI_MAX][ZEBRA_KERNEL_TABLE_MAX];
51
52int
53is_zebra_import_table_enabled(afi_t afi, u_int32_t table_id)
54{
55 if (is_zebra_valid_kernel_table(table_id))
032bfaaf 56 return zebra_import_table_used[afi][table_id];
7a4bb9c5
DS
57 return 0;
58}
59
7076bb2f 60int
718e3744 61is_default (struct prefix *p)
62{
63 if (p->family == AF_INET)
64 if (p->u.prefix4.s_addr == 0 && p->prefixlen == 0)
65 return 1;
718e3744 66#if 0 /* IPv6 default separation is now pending until protocol daemon
67 can handle that. */
68 if (p->family == AF_INET6)
69 if (IN6_IS_ADDR_UNSPECIFIED (&p->u.prefix6) && p->prefixlen == 0)
70 return 1;
71#endif /* 0 */
718e3744 72 return 0;
73}
74
27da3988 75static void
7076bb2f 76zebra_redistribute_default (struct zserv *client, vrf_id_t vrf_id)
718e3744 77{
9c6060d4
RW
78 int afi;
79 struct prefix p;
718e3744 80 struct route_table *table;
81 struct route_node *rn;
f0f77c9a 82 struct route_entry *newre;
718e3744 83
9c6060d4 84 for (afi = AFI_IP; afi <= AFI_IP6; afi++)
718e3744 85 {
9c6060d4
RW
86 /* Lookup table. */
87 table = zebra_vrf_table (afi, SAFI_UNICAST, vrf_id);
88 if (! table)
89 continue;
90
91 /* Lookup default route. */
92 memset (&p, 0, sizeof (p));
93 p.family = afi2family (afi);
94 rn = route_node_lookup (table, &p);
95 if (! rn)
96 continue;
718e3744 97
f0f77c9a
DS
98 RNODE_FOREACH_RE (rn, newre)
99 if (CHECK_FLAG (newre->flags, ZEBRA_FLAG_SELECTED)
100 && newre->distance != DISTANCE_INFINITY)
101 zsend_redistribute_route (1, client, &rn->p, NULL, newre);
718e3744 102
9c6060d4 103 route_unlock_node (rn);
718e3744 104 }
718e3744 105}
106
107/* Redistribute routes. */
27da3988 108static void
501be987 109zebra_redistribute (struct zserv *client, int type, u_short instance, vrf_id_t vrf_id, int afi)
718e3744 110{
f0f77c9a 111 struct route_entry *newre;
718e3744 112 struct route_table *table;
113 struct route_node *rn;
114
501be987
DW
115 table = zebra_vrf_table (afi, SAFI_UNICAST, vrf_id);
116 if (! table)
117 return;
9c6060d4 118
501be987 119 for (rn = route_top (table); rn; rn = route_next (rn))
f0f77c9a 120 RNODE_FOREACH_RE (rn, newre)
501be987 121 {
92eedda1
DL
122 struct prefix *dst_p, *src_p;
123 srcdest_rnode_prefixes(rn, &dst_p, &src_p);
124
501be987
DW
125 if (IS_ZEBRA_DEBUG_EVENT)
126 zlog_debug("%s: checking: selected=%d, type=%d, distance=%d, "
92eedda1 127 "zebra_check_addr=%d", __func__,
f0f77c9a
DS
128 CHECK_FLAG (newre->flags, ZEBRA_FLAG_SELECTED),
129 newre->type, newre->distance,
92eedda1 130 zebra_check_addr (dst_p));
501be987 131
f0f77c9a 132 if (! CHECK_FLAG (newre->flags, ZEBRA_FLAG_SELECTED))
501be987
DW
133 continue;
134 if ((type != ZEBRA_ROUTE_ALL &&
f0f77c9a 135 (newre->type != type || newre->instance != instance)))
501be987 136 continue;
f0f77c9a 137 if (newre->distance == DISTANCE_INFINITY)
501be987 138 continue;
92eedda1 139 if (! zebra_check_addr (dst_p))
501be987
DW
140 continue;
141
f0f77c9a 142 zsend_redistribute_route (1, client, dst_p, src_p, newre);
501be987 143 }
718e3744 144}
145
c41fc67b 146/* Either advertise a route for redistribution to registered clients or */
147/* withdraw redistribution if add cannot be done for client */
718e3744 148void
05737783 149redistribute_update (struct prefix *p, struct prefix *src_p,
f0f77c9a 150 struct route_entry *re, struct route_entry *prev_re)
718e3744 151{
1eb8ef25 152 struct listnode *node, *nnode;
718e3744 153 struct zserv *client;
c41fc67b 154 int send_redistribute;
155 int afi;
41ec9222 156 char buf[INET6_ADDRSTRLEN];
157
158 if (IS_ZEBRA_DEBUG_RIB)
159 {
160 inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN);
f0f77c9a
DS
161 zlog_debug ("%u:%s/%d: Redist update re %p (type %d), old %p (type %d)",
162 re->vrf_id, buf, p->prefixlen, re, re->type,
163 prev_re, prev_re ? prev_re->type : -1);
41ec9222 164 }
c41fc67b 165
166 afi = family2afi(p->family);
167 if (!afi)
168 {
169 zlog_warn("%s: Unknown AFI/SAFI prefix received\n", __FUNCTION__);
170 return;
171 }
718e3744 172
1eb8ef25 173 for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
174 {
c41fc67b 175 send_redistribute = 0;
176
f0f77c9a 177 if (is_default (p) && vrf_bitmap_check (client->redist_default, re->vrf_id))
9c6060d4 178 send_redistribute = 1;
f0f77c9a 179 else if (vrf_bitmap_check (client->redist[afi][ZEBRA_ROUTE_ALL], re->vrf_id))
9c6060d4 180 send_redistribute = 1;
f0f77c9a
DS
181 else if (re->instance && redist_check_instance (&client->mi_redist[afi][re->type],
182 re->instance))
9c6060d4 183 send_redistribute = 1;
f0f77c9a 184 else if (vrf_bitmap_check (client->redist[afi][re->type], re->vrf_id))
9c6060d4 185 send_redistribute = 1;
c41fc67b 186
187 if (send_redistribute)
188 {
f0f77c9a 189 zsend_redistribute_route (1, client, p, src_p, re);
c41fc67b 190 }
f0f77c9a
DS
191 else if (prev_re &&
192 ((re->instance &&
193 redist_check_instance(&client->mi_redist[afi][prev_re->type],
194 re->instance)) ||
195 vrf_bitmap_check (client->redist[afi][prev_re->type], re->vrf_id)))
c41fc67b 196 {
f0f77c9a 197 zsend_redistribute_route (0, client, p, src_p, prev_re);
c41fc67b 198 }
1eb8ef25 199 }
718e3744 200}
201
202void
f0f77c9a 203redistribute_delete (struct prefix *p, struct prefix *src_p, struct route_entry *re)
718e3744 204{
1eb8ef25 205 struct listnode *node, *nnode;
718e3744 206 struct zserv *client;
41ec9222 207 char buf[INET6_ADDRSTRLEN];
10ead5c8 208 int afi;
41ec9222 209
210 if (IS_ZEBRA_DEBUG_RIB)
211 {
212 inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN);
f0f77c9a
DS
213 zlog_debug ("%u:%s/%d: Redist delete re %p (type %d)",
214 re->vrf_id, buf, p->prefixlen, re, re->type);
41ec9222 215 }
718e3744 216
217 /* Add DISTANCE_INFINITY check. */
f0f77c9a 218 if (re->distance == DISTANCE_INFINITY)
718e3744 219 return;
220
10ead5c8
TT
221 afi = family2afi(p->family);
222 if (!afi)
223 {
224 zlog_warn("%s: Unknown AFI/SAFI prefix received\n", __FUNCTION__);
225 return;
226 }
227
1eb8ef25 228 for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
229 {
10ead5c8 230 if ((is_default (p) &&
f0f77c9a
DS
231 vrf_bitmap_check (client->redist_default, re->vrf_id)) ||
232 vrf_bitmap_check (client->redist[afi][ZEBRA_ROUTE_ALL], re->vrf_id) ||
233 (re->instance &&
234 redist_check_instance(&client->mi_redist[afi][re->type],
235 re->instance)) ||
236 vrf_bitmap_check (client->redist[afi][re->type], re->vrf_id))
1eb8ef25 237 {
f0f77c9a 238 zsend_redistribute_route (0, client, p, src_p, re);
1eb8ef25 239 }
240 }
718e3744 241}
242
243void
7076bb2f 244zebra_redistribute_add (int command, struct zserv *client, int length,
d651649e 245 struct zebra_vrf *zvrf)
718e3744 246{
8bb0831e 247 afi_t afi;
718e3744 248 int type;
7c8ff89e 249 u_short instance;
718e3744 250
8bb0831e 251 afi = stream_getc (client->ibuf);
718e3744 252 type = stream_getc (client->ibuf);
7c8ff89e 253 instance = stream_getw (client->ibuf);
718e3744 254
ebf08631
DL
255 if (type == 0 || type >= ZEBRA_ROUTE_MAX)
256 return;
257
4e1cadf0 258 if (instance)
718e3744 259 {
4e1cadf0
RW
260 if (! redist_check_instance (&client->mi_redist[afi][type], instance))
261 {
262 redist_add_instance (&client->mi_redist[afi][type], instance);
501be987 263 zebra_redistribute (client, type, instance, zvrf_id (zvrf), afi);
4e1cadf0
RW
264 }
265 } else {
661512bf 266 if (! vrf_bitmap_check (client->redist[afi][type], zvrf_id (zvrf)))
4e1cadf0 267 {
661512bf 268 vrf_bitmap_set (client->redist[afi][type], zvrf_id (zvrf));
501be987 269 zebra_redistribute (client, type, 0, zvrf_id (zvrf), afi);
4e1cadf0 270 }
9c6060d4 271 }
ebf08631 272}
718e3744 273
274void
7076bb2f 275zebra_redistribute_delete (int command, struct zserv *client, int length,
d651649e 276 struct zebra_vrf *zvrf)
718e3744 277{
8bb0831e 278 afi_t afi;
718e3744 279 int type;
7c8ff89e 280 u_short instance;
718e3744 281
8bb0831e 282 afi = stream_getc (client->ibuf);
718e3744 283 type = stream_getc (client->ibuf);
7c8ff89e 284 instance = stream_getw (client->ibuf);
718e3744 285
ebf08631
DL
286 if (type == 0 || type >= ZEBRA_ROUTE_MAX)
287 return;
288
4e1cadf0
RW
289 /*
290 * NOTE: no need to withdraw the previously advertised routes. The clients
291 * themselves should keep track of the received routes from zebra and
292 * withdraw them when necessary.
293 */
294 if (instance)
43e7c3b4 295 redist_del_instance (&client->mi_redist[afi][type], instance);
4e1cadf0 296 else
661512bf 297 vrf_bitmap_unset (client->redist[afi][type], zvrf_id (zvrf));
ebf08631 298}
718e3744 299
300void
7076bb2f 301zebra_redistribute_default_add (int command, struct zserv *client, int length,
d651649e 302 struct zebra_vrf *zvrf)
718e3744 303{
661512bf
RW
304 vrf_bitmap_set (client->redist_default, zvrf_id (zvrf));
305 zebra_redistribute_default (client, zvrf_id (zvrf));
718e3744 306}
307
308void
309zebra_redistribute_default_delete (int command, struct zserv *client,
d651649e 310 int length, struct zebra_vrf *zvrf)
718e3744 311{
661512bf 312 vrf_bitmap_unset (client->redist_default, zvrf_id (zvrf));
718e3744 313}
314
315/* Interface up information. */
316void
317zebra_interface_up_update (struct interface *ifp)
318{
1eb8ef25 319 struct listnode *node, *nnode;
718e3744 320 struct zserv *client;
321
322 if (IS_ZEBRA_DEBUG_EVENT)
b6178002 323 zlog_debug ("MESSAGE: ZEBRA_INTERFACE_UP %s", ifp->name);
718e3744 324
244c1cdc
DS
325 if (ifp->ptm_status || !ifp->ptm_enable) {
326 for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
16f1b9ee
OD
327 if (client->ifinfo)
328 {
329 zsend_interface_update (ZEBRA_INTERFACE_UP, client, ifp);
330 zsend_interface_link_params (client, ifp);
331 }
244c1cdc 332 }
718e3744 333}
334
335/* Interface down information. */
336void
337zebra_interface_down_update (struct interface *ifp)
338{
1eb8ef25 339 struct listnode *node, *nnode;
718e3744 340 struct zserv *client;
341
342 if (IS_ZEBRA_DEBUG_EVENT)
b6178002 343 zlog_debug ("MESSAGE: ZEBRA_INTERFACE_DOWN %s", ifp->name);
718e3744 344
1eb8ef25 345 for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
04b02fda
DS
346 {
347 zsend_interface_update (ZEBRA_INTERFACE_DOWN, client, ifp);
348 }
718e3744 349}
350
351/* Interface information update. */
352void
353zebra_interface_add_update (struct interface *ifp)
354{
1eb8ef25 355 struct listnode *node, *nnode;
718e3744 356 struct zserv *client;
357
358 if (IS_ZEBRA_DEBUG_EVENT)
4fe51714 359 zlog_debug ("MESSAGE: ZEBRA_INTERFACE_ADD %s[%d]", ifp->name, ifp->vrf_id);
718e3744 360
1eb8ef25 361 for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
16f1b9ee
OD
362 if (client->ifinfo)
363 {
364 client->ifadd_cnt++;
365 zsend_interface_add (client, ifp);
366 zsend_interface_link_params (client, ifp);
367 }
718e3744 368}
369
370void
371zebra_interface_delete_update (struct interface *ifp)
372{
1eb8ef25 373 struct listnode *node, *nnode;
718e3744 374 struct zserv *client;
375
376 if (IS_ZEBRA_DEBUG_EVENT)
b6178002 377 zlog_debug ("MESSAGE: ZEBRA_INTERFACE_DELETE %s", ifp->name);
718e3744 378
1eb8ef25 379 for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
4fe51714
DS
380 {
381 client->ifdel_cnt++;
382 zsend_interface_delete (client, ifp);
383 }
718e3744 384}
385
386/* Interface address addition. */
387void
388zebra_interface_address_add_update (struct interface *ifp,
389 struct connected *ifc)
390{
1eb8ef25 391 struct listnode *node, *nnode;
718e3744 392 struct zserv *client;
393 struct prefix *p;
718e3744 394
395 if (IS_ZEBRA_DEBUG_EVENT)
396 {
35d921cc 397 char buf[PREFIX_STRLEN];
81cce018 398
718e3744 399 p = ifc->address;
35d921cc
TT
400 zlog_debug ("MESSAGE: ZEBRA_INTERFACE_ADDRESS_ADD %s on %s",
401 prefix2str (p, buf, sizeof(buf)),
402 ifc->ifp->name);
718e3744 403 }
404
c7df92de
CF
405 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
406 zlog_warn("WARNING: advertising address to clients that is not yet usable.");
407
18a6dce6 408 router_id_add_address(ifc);
409
1eb8ef25 410 for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
4fe51714 411 if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
04b02fda
DS
412 {
413 client->connected_rt_add_cnt++;
414 zsend_interface_address (ZEBRA_INTERFACE_ADDRESS_ADD, client, ifp, ifc);
415 }
718e3744 416}
417
418/* Interface address deletion. */
419void
420zebra_interface_address_delete_update (struct interface *ifp,
421 struct connected *ifc)
422{
1eb8ef25 423 struct listnode *node, *nnode;
718e3744 424 struct zserv *client;
425 struct prefix *p;
718e3744 426
427 if (IS_ZEBRA_DEBUG_EVENT)
428 {
35d921cc 429 char buf[PREFIX_STRLEN];
81cce018 430
718e3744 431 p = ifc->address;
35d921cc
TT
432 zlog_debug ("MESSAGE: ZEBRA_INTERFACE_ADDRESS_DELETE %s on %s",
433 prefix2str (p, buf, sizeof(buf)),
434 ifc->ifp->name);
718e3744 435 }
436
18a6dce6 437 router_id_del_address(ifc);
438
1eb8ef25 439 for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
4fe51714 440 if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
04b02fda
DS
441 {
442 client->connected_rt_del_cnt++;
443 zsend_interface_address (ZEBRA_INTERFACE_ADDRESS_DELETE, client, ifp, ifc);
444 }
718e3744 445}
d5a5c8f0 446
c8e264b6 447/* Interface VRF change. May need to delete from clients not interested in
448 * the new VRF. Note that this function is invoked *prior* to the VRF change.
449 */
450void
451zebra_interface_vrf_update_del (struct interface *ifp, vrf_id_t new_vrf_id)
452{
453 struct listnode *node, *nnode;
454 struct zserv *client;
455
456 if (IS_ZEBRA_DEBUG_EVENT)
457 zlog_debug ("MESSAGE: ZEBRA_INTERFACE_VRF_UPDATE/DEL %s VRF Id %u -> %u",
458 ifp->name, ifp->vrf_id, new_vrf_id);
459
460 for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
461 {
4fe51714
DS
462 /* Need to delete if the client is not interested in the new VRF. */
463 zsend_interface_update (ZEBRA_INTERFACE_DOWN, client, ifp);
464 client->ifdel_cnt++;
465 zsend_interface_delete (client, ifp);
466 zsend_interface_vrf_update (client, ifp, new_vrf_id);
c8e264b6 467 }
468}
469
470/* Interface VRF change. This function is invoked *post* VRF change and sends an
471 * add to clients who are interested in the new VRF but not in the old VRF.
472 */
473void
474zebra_interface_vrf_update_add (struct interface *ifp, vrf_id_t old_vrf_id)
475{
476 struct listnode *node, *nnode;
477 struct zserv *client;
478
479 if (IS_ZEBRA_DEBUG_EVENT)
480 zlog_debug ("MESSAGE: ZEBRA_INTERFACE_VRF_UPDATE/ADD %s VRF Id %u -> %u",
481 ifp->name, old_vrf_id, ifp->vrf_id);
482
483 for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
484 {
c8e264b6 485 /* Need to add if the client is interested in the new VRF. */
486 client->ifadd_cnt++;
487 zsend_interface_add (client, ifp);
488 zsend_interface_addresses (client, ifp);
489 }
490}
491
7a4bb9c5 492int
f0f77c9a 493zebra_add_import_table_entry (struct route_node *rn, struct route_entry *re, const char *rmap_name)
7a4bb9c5 494{
f0f77c9a
DS
495 struct route_entry *newre;
496 struct route_entry *same;
3b1098be 497 struct prefix p;
7a4bb9c5 498 struct nexthop *nhop;
3b1098be 499 union g_addr *gate;
8902474b 500 route_map_result_t ret = RMAP_MATCH;
7a4bb9c5 501
8902474b 502 if (rmap_name)
f0f77c9a
DS
503 ret = zebra_import_table_route_map_check (AFI_IP, re->type, &rn->p, re->nexthop, re->vrf_id,
504 re->tag, rmap_name);
8902474b
DS
505
506 if (ret == RMAP_MATCH)
7a4bb9c5 507 {
8902474b
DS
508 if (rn->p.family == AF_INET)
509 {
3b1098be
DS
510 p.family = AF_INET;
511 p.prefixlen = rn->p.prefixlen;
512 p.u.prefix4 = rn->p.u.prefix4;
7a4bb9c5 513
f0f77c9a 514 RNODE_FOREACH_RE (rn, same)
47301614 515 {
f0f77c9a 516 if (CHECK_FLAG (same->status, ROUTE_ENTRY_REMOVED))
47301614
DS
517 continue;
518
f0f77c9a
DS
519 if (same->type == re->type && same->instance == re->instance
520 && same->table == re->table
47301614
DS
521 && same->type != ZEBRA_ROUTE_CONNECT)
522 break;
523 }
524
525 if (same)
526 zebra_del_import_table_entry (rn, same);
527
528
f0f77c9a 529 if (re->nexthop_num == 1)
8902474b 530 {
f0f77c9a 531 nhop = re->nexthop;
8902474b
DS
532 if (nhop->type == NEXTHOP_TYPE_IFINDEX)
533 gate = NULL;
534 else
3b1098be
DS
535 gate = (union g_addr *)&nhop->gate.ipv4;
536
f0f77c9a
DS
537 rib_add (AFI_IP, SAFI_UNICAST, re->vrf_id, ZEBRA_ROUTE_TABLE,
538 re->table, 0, &p, NULL, gate, (union g_addr *)&nhop->src.ipv4,
3b1098be 539 nhop->ifindex, zebrad.rtm_table_default,
f0f77c9a
DS
540 re->metric, re->mtu,
541 zebra_import_table_distance[AFI_IP][re->table]);
8902474b 542 }
f0f77c9a 543 else if (re->nexthop_num > 1)
8902474b 544 {
f0f77c9a
DS
545 newre = XCALLOC (MTYPE_RE, sizeof (struct route_entry));
546 newre->type = ZEBRA_ROUTE_TABLE;
547 newre->distance = zebra_import_table_distance[AFI_IP][re->table];
548 newre->flags = re->flags;
549 newre->metric = re->metric;
550 newre->mtu = re->mtu;
551 newre->table = zebrad.rtm_table_default;
552 newre->nexthop_num = 0;
553 newre->uptime = time(NULL);
554 newre->instance = re->table;
8902474b
DS
555
556 /* Assuming these routes are never recursive */
f0f77c9a
DS
557 for (nhop = re->nexthop; nhop; nhop = nhop->next)
558 route_entry_copy_nexthops(newre, nhop);
8902474b 559
f0f77c9a 560 rib_add_multipath(AFI_IP, SAFI_UNICAST, &p, NULL, newre);
8902474b
DS
561 }
562 }
563 }
564 else
565 {
f0f77c9a 566 zebra_del_import_table_entry (rn, re);
7a4bb9c5
DS
567 }
568 /* DD: Add IPv6 code */
569 return 0;
570}
571
572int
f0f77c9a 573zebra_del_import_table_entry (struct route_node *rn, struct route_entry *re)
7a4bb9c5 574{
616368ed 575 struct prefix p;
7a4bb9c5
DS
576
577 if (rn->p.family == AF_INET)
578 {
616368ed
DS
579 p.family = AF_INET;
580 p.prefixlen = rn->p.prefixlen;
581 p.u.prefix4 = rn->p.u.prefix4;
7a4bb9c5 582
f0f77c9a
DS
583 rib_delete (AFI_IP, SAFI_UNICAST, re->vrf_id, ZEBRA_ROUTE_TABLE,
584 re->table, re->flags, &p, NULL, NULL,
616368ed 585 0, zebrad.rtm_table_default);
7a4bb9c5
DS
586 }
587 /* DD: Add IPv6 code */
588
589 return 0;
590}
591
592/* Assuming no one calls this with the main routing table */
593int
8902474b 594zebra_import_table (afi_t afi, u_int32_t table_id, u_int32_t distance, const char *rmap_name, int add)
7a4bb9c5
DS
595{
596 struct route_table *table;
f0f77c9a 597 struct route_entry *re;
7a4bb9c5
DS
598 struct route_node *rn;
599
600 if (!is_zebra_valid_kernel_table(table_id) ||
601 ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default)))
602 return (-1);
603
604 if (afi >= AFI_MAX)
605 return (-1);
606
b72ede27 607 table = zebra_vrf_other_route_table(afi, table_id, VRF_DEFAULT);
7a4bb9c5
DS
608 if (table == NULL)
609 {
610 return 0;
611 }
612 else if (IS_ZEBRA_DEBUG_RIB)
613 {
614 zlog_debug ("%s routes from table %d",
615 add ? "Importing" : "Unimporting", table_id);
616 }
617
618 if (add)
619 {
8902474b
DS
620 if (rmap_name)
621 zebra_add_import_table_route_map (afi, rmap_name, table_id);
622 else
623 {
624 rmap_name = zebra_get_import_table_route_map (afi, table_id);
625 if (rmap_name)
626 zebra_del_import_table_route_map (afi, table_id);
627 }
628
032bfaaf 629 zebra_import_table_used[afi][table_id] = 1;
7a4bb9c5
DS
630 zebra_import_table_distance[afi][table_id] = distance;
631 }
632 else
633 {
032bfaaf 634 zebra_import_table_used[afi][table_id] = 0;
7a4bb9c5 635 zebra_import_table_distance[afi][table_id] = ZEBRA_TABLE_DISTANCE_DEFAULT;
8902474b
DS
636
637 rmap_name = zebra_get_import_table_route_map (afi, table_id);
638 if (rmap_name)
639 zebra_del_import_table_route_map (afi, table_id);
7a4bb9c5
DS
640 }
641
642 for (rn = route_top(table); rn; rn = route_next(rn))
643 {
644 /* For each entry in the non-default routing table,
645 * add the entry in the main table
646 */
647 if (!rn->info)
648 continue;
649
f0f77c9a 650 RNODE_FOREACH_RE (rn, re)
7a4bb9c5 651 {
f0f77c9a 652 if (CHECK_FLAG (re->status, ROUTE_ENTRY_REMOVED))
7a4bb9c5
DS
653 continue;
654 break;
655 }
656
f0f77c9a 657 if (!re)
7a4bb9c5
DS
658 continue;
659
4e3afb14
DS
660 if (((afi == AFI_IP) && (rn->p.family == AF_INET)) ||
661 ((afi == AFI_IP6) && (rn->p.family == AF_INET6)))
7a4bb9c5
DS
662 {
663 if (add)
f0f77c9a 664 zebra_add_import_table_entry (rn, re, rmap_name);
7a4bb9c5 665 else
f0f77c9a 666 zebra_del_import_table_entry (rn, re);
7a4bb9c5
DS
667 }
668 }
669 return 0;
670}
671
672int
673zebra_import_table_config (struct vty *vty)
674{
675 int i;
676 afi_t afi;
677 int write = 0;
032bfaaf 678 char afi_str[AFI_MAX][10] = {"", "ip", "ipv6", "ethernet"};
8902474b 679 const char *rmap_name;
7a4bb9c5
DS
680
681 for (afi = AFI_IP; afi < AFI_MAX; afi++)
682 {
683 for (i = 1; i < ZEBRA_KERNEL_TABLE_MAX; i++)
684 {
685 if (is_zebra_import_table_enabled(afi, i))
686 {
687 if (zebra_import_table_distance[afi][i] != ZEBRA_TABLE_DISTANCE_DEFAULT)
688 {
8902474b
DS
689 vty_out(vty, "%s import-table %d distance %d", afi_str[afi],
690 i, zebra_import_table_distance[afi][i]);
7a4bb9c5
DS
691 }
692 else
693 {
8902474b 694 vty_out(vty, "%s import-table %d", afi_str[afi], i);
7a4bb9c5 695 }
8902474b
DS
696
697 rmap_name = zebra_get_import_table_route_map (afi, i);
698 if (rmap_name)
699 vty_out(vty, " route-map %s", rmap_name);
700
701 vty_out(vty, "%s", VTY_NEWLINE);
7a4bb9c5
DS
702 write = 1;
703 }
704 }
705 }
706
707 return write;
708}
8902474b
DS
709
710void
711zebra_import_table_rm_update ()
712{
713 afi_t afi;
714 int i;
715 struct route_table *table;
f0f77c9a 716 struct route_entry *re;
8902474b
DS
717 struct route_node *rn;
718 const char *rmap_name;
719
720 for (afi = AFI_IP; afi < AFI_MAX; afi++)
721 {
722 for (i = 1; i < ZEBRA_KERNEL_TABLE_MAX; i++)
723 {
724 if (is_zebra_import_table_enabled(afi, i))
725 {
726 rmap_name = zebra_get_import_table_route_map (afi, i);
727 if (!rmap_name)
728 return;
729
730 table = zebra_vrf_other_route_table(afi, i, VRF_DEFAULT);
731 for (rn = route_top(table); rn; rn = route_next(rn))
732 {
733 /* For each entry in the non-default routing table,
734 * add the entry in the main table
735 */
736 if (!rn->info)
737 continue;
738
f0f77c9a 739 RNODE_FOREACH_RE (rn, re)
8902474b 740 {
f0f77c9a 741 if (CHECK_FLAG (re->status, ROUTE_ENTRY_REMOVED))
8902474b
DS
742 continue;
743 break;
744 }
745
f0f77c9a 746 if (!re)
8902474b
DS
747 continue;
748
749 if (((afi == AFI_IP) && (rn->p.family == AF_INET)) ||
750 ((afi == AFI_IP6) && (rn->p.family == AF_INET6)))
f0f77c9a 751 zebra_add_import_table_entry (rn, re, rmap_name);
8902474b
DS
752 }
753 }
754 }
755 }
756
757 return;
758}
16f1b9ee
OD
759
760/* Interface parameters update */
761void
762zebra_interface_parameters_update (struct interface *ifp)
763{
764 struct listnode *node, *nnode;
765 struct zserv *client;
766
767 if (IS_ZEBRA_DEBUG_EVENT)
768 zlog_debug ("MESSAGE: ZEBRA_INTERFACE_LINK_PARAMS %s", ifp->name);
769
770 for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
771 if (client->ifinfo)
772 zsend_interface_link_params (client, ifp);
773}