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