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