]>
Commit | Line | Data |
---|---|---|
7f57883e DS |
1 | /* |
2 | * Zebra connect library for EIGRP. | |
3 | * Copyright (C) 2013-2014 | |
4 | * Authors: | |
5 | * Donnie Savage | |
6 | * Jan Janovic | |
7 | * Matej Perina | |
8 | * Peter Orsag | |
9 | * Peter Paluch | |
10 | * | |
11 | * This file is part of GNU Zebra. | |
12 | * | |
13 | * GNU Zebra is free software; you can redistribute it and/or modify it | |
14 | * under the terms of the GNU General Public License as published by the | |
15 | * Free Software Foundation; either version 2, or (at your option) any | |
16 | * later version. | |
17 | * | |
18 | * GNU Zebra is distributed in the hope that it will be useful, but | |
19 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
21 | * General Public License for more details. | |
22 | * | |
23 | * You should have received a copy of the GNU General Public License | |
24 | * along with GNU Zebra; see the file COPYING. If not, write to the Free | |
25 | * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | |
26 | * 02111-1307, USA. | |
27 | */ | |
28 | ||
29 | #include <zebra.h> | |
30 | ||
31 | #include "thread.h" | |
32 | #include "command.h" | |
33 | #include "network.h" | |
34 | #include "prefix.h" | |
35 | #include "routemap.h" | |
36 | #include "table.h" | |
37 | #include "stream.h" | |
38 | #include "memory.h" | |
39 | #include "zclient.h" | |
40 | #include "filter.h" | |
41 | #include "plist.h" | |
42 | #include "log.h" | |
43 | #include "nexthop.h" | |
44 | ||
45 | #include "eigrpd/eigrp_structs.h" | |
46 | #include "eigrpd/eigrpd.h" | |
47 | #include "eigrpd/eigrp_interface.h" | |
48 | #include "eigrpd/eigrp_neighbor.h" | |
49 | #include "eigrpd/eigrp_packet.h" | |
50 | #include "eigrpd/eigrp_zebra.h" | |
51 | #include "eigrpd/eigrp_vty.h" | |
52 | #include "eigrpd/eigrp_dump.h" | |
53 | #include "eigrpd/eigrp_network.h" | |
54 | #include "eigrpd/eigrp_topology.h" | |
55 | #include "eigrpd/eigrp_fsm.h" | |
56 | ||
57 | static int eigrp_interface_add (int , struct zclient *, zebra_size_t, vrf_id_t); | |
58 | static int eigrp_interface_delete (int , struct zclient *, | |
59 | zebra_size_t, vrf_id_t); | |
60 | static int eigrp_interface_address_add (int, struct zclient *, | |
61 | zebra_size_t, vrf_id_t vrf_id); | |
62 | static int eigrp_interface_address_delete (int, struct zclient *, | |
63 | zebra_size_t, vrf_id_t vrf_id); | |
64 | static int eigrp_interface_state_up (int, struct zclient *, | |
65 | zebra_size_t, vrf_id_t vrf_id); | |
66 | static int eigrp_interface_state_down (int, struct zclient *, | |
67 | zebra_size_t, vrf_id_t vrf_id); | |
68 | static struct interface * zebra_interface_if_lookup (struct stream *); | |
69 | ||
70 | static int eigrp_zebra_read_ipv4 (int , struct zclient *, | |
71 | zebra_size_t, vrf_id_t vrf_id); | |
72 | ||
73 | /* Zebra structure to hold current status. */ | |
74 | struct zclient *zclient = NULL; | |
75 | ||
76 | /* For registering threads. */ | |
77 | extern struct thread_master *master; | |
78 | struct in_addr router_id_zebra; | |
79 | ||
80 | /* Router-id update message from zebra. */ | |
81 | static int | |
82 | eigrp_router_id_update_zebra (int command, struct zclient *zclient, | |
83 | zebra_size_t length, vrf_id_t vrf_id) | |
84 | { | |
85 | struct eigrp *eigrp; | |
86 | struct prefix router_id; | |
87 | zebra_router_id_update_read (zclient->ibuf,&router_id); | |
88 | ||
89 | router_id_zebra = router_id.u.prefix4; | |
90 | ||
91 | eigrp = eigrp_lookup (); | |
92 | ||
93 | if (eigrp != NULL) | |
94 | eigrp_router_id_update (eigrp); | |
95 | ||
96 | return 0; | |
97 | } | |
98 | ||
99 | ||
100 | void | |
101 | eigrp_zebra_init (void) | |
102 | { | |
103 | zclient = zclient_new (master); | |
104 | ||
105 | zclient_init (zclient, ZEBRA_ROUTE_EIGRP, 0); | |
106 | zclient->router_id_update = eigrp_router_id_update_zebra; | |
107 | zclient->interface_add = eigrp_interface_add; | |
108 | zclient->interface_delete = eigrp_interface_delete; | |
109 | zclient->interface_up = eigrp_interface_state_up; | |
110 | zclient->interface_down = eigrp_interface_state_down; | |
111 | zclient->interface_address_add = eigrp_interface_address_add; | |
112 | zclient->interface_address_delete = eigrp_interface_address_delete; | |
113 | zclient->redistribute_route_ipv4_add = eigrp_zebra_read_ipv4; | |
114 | zclient->redistribute_route_ipv4_del = eigrp_zebra_read_ipv4; | |
115 | } | |
116 | ||
117 | ||
118 | /* Zebra route add and delete treatment. */ | |
119 | static int | |
120 | eigrp_zebra_read_ipv4 (int command, struct zclient *zclient, | |
121 | zebra_size_t length, vrf_id_t vrf_id) | |
122 | { | |
123 | struct stream *s; | |
124 | struct zapi_ipv4 api; | |
125 | struct prefix_ipv4 p; | |
126 | struct eigrp *eigrp; | |
127 | ||
128 | s = zclient->ibuf; | |
129 | ||
130 | /* Type, flags, message. */ | |
131 | api.type = stream_getc (s); | |
132 | api.instance = stream_getw (s); | |
133 | api.flags = stream_getc (s); | |
134 | api.message = stream_getc (s); | |
135 | ||
136 | /* IPv4 prefix. */ | |
137 | memset (&p, 0, sizeof (struct prefix_ipv4)); | |
138 | p.family = AF_INET; | |
139 | p.prefixlen = stream_getc (s); | |
140 | stream_get (&p.prefix, s, PSIZE (p.prefixlen)); | |
141 | ||
142 | if (IPV4_NET127(ntohl(p.prefix.s_addr))) | |
143 | return 0; | |
144 | ||
145 | /* Nexthop, ifindex, distance, metric. */ | |
146 | if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) | |
147 | { | |
148 | api.nexthop_num = stream_getc (s); | |
149 | stream_get_ipv4 (s); | |
150 | } | |
151 | if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) | |
152 | { | |
153 | api.ifindex_num = stream_getc (s); | |
154 | /* XXX assert(api.ifindex_num == 1); */ | |
155 | stream_getl (s); /* ifindex, unused */ | |
156 | } | |
157 | if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) | |
158 | api.distance = stream_getc (s); | |
159 | if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) | |
160 | api.metric = stream_getl (s); | |
161 | ||
162 | eigrp = eigrp_lookup (); | |
163 | if (eigrp == NULL) | |
164 | return 0; | |
165 | ||
166 | if (command == ZEBRA_IPV4_ROUTE_ADD) | |
167 | { | |
168 | ||
169 | } | |
170 | else /* if (command == ZEBRA_IPV4_ROUTE_DELETE) */ | |
171 | { | |
172 | ||
173 | } | |
174 | ||
175 | return 0; | |
176 | } | |
177 | ||
178 | /* Inteface addition message from zebra. */ | |
179 | static int | |
180 | eigrp_interface_add (int command, struct zclient *zclient, zebra_size_t length, | |
181 | vrf_id_t vrf_id) | |
182 | { | |
183 | struct interface *ifp; | |
184 | ||
185 | ifp = zebra_interface_add_read (zclient->ibuf, vrf_id); | |
186 | ||
187 | assert (ifp->info); | |
188 | ||
189 | if (!EIGRP_IF_PARAM_CONFIGURED (IF_DEF_PARAMS (ifp), type)) | |
190 | { | |
191 | SET_IF_PARAM (IF_DEF_PARAMS (ifp), type); | |
192 | IF_DEF_PARAMS (ifp)->type = eigrp_default_iftype (ifp); | |
193 | } | |
194 | ||
195 | eigrp_if_update (ifp); | |
196 | ||
197 | return 0; | |
198 | } | |
199 | ||
200 | static int | |
201 | eigrp_interface_delete (int command, struct zclient *zclient, | |
202 | zebra_size_t length, vrf_id_t vrf_id) | |
203 | { | |
204 | struct interface *ifp; | |
205 | struct stream *s; | |
206 | struct route_node *rn; | |
207 | ||
208 | s = zclient->ibuf; | |
209 | /* zebra_interface_state_read () updates interface structure in iflist */ | |
210 | ifp = zebra_interface_state_read (s, vrf_id); | |
211 | ||
212 | if (ifp == NULL) | |
213 | return 0; | |
214 | ||
215 | if (if_is_up (ifp)) | |
216 | zlog_warn ("Zebra: got delete of %s, but interface is still up", | |
217 | ifp->name); | |
218 | ||
219 | if (IS_DEBUG_EIGRP (zebra, ZEBRA_INTERFACE)) | |
220 | zlog_debug("Zebra: interface delete %s index %d flags %llx metric %d mtu %d", | |
221 | ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, ifp->metric, ifp->mtu); | |
222 | ||
223 | for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn)) | |
224 | if (rn->info) | |
225 | eigrp_if_free ((struct eigrp_interface *) rn->info, INTERFACE_DOWN_BY_ZEBRA); | |
226 | ||
227 | ifp->ifindex = IFINDEX_INTERNAL; | |
228 | return 0; | |
229 | } | |
230 | ||
231 | static int | |
232 | eigrp_interface_address_add (int command, struct zclient *zclient, | |
233 | zebra_size_t length, vrf_id_t vrf_id) | |
234 | { | |
235 | struct connected *c; | |
236 | ||
237 | c = zebra_interface_address_read (command, zclient->ibuf, vrf_id); | |
238 | ||
239 | if (c == NULL) | |
240 | return 0; | |
241 | ||
242 | if (IS_DEBUG_EIGRP (zebra, ZEBRA_INTERFACE)) | |
243 | { | |
244 | char buf[128]; | |
245 | prefix2str (c->address, buf, sizeof (buf)); | |
246 | zlog_debug ("Zebra: interface %s address add %s", c->ifp->name, buf); | |
247 | } | |
248 | ||
249 | eigrp_if_update (c->ifp); | |
250 | ||
251 | return 0; | |
252 | } | |
253 | ||
254 | static int | |
255 | eigrp_interface_address_delete (int command, struct zclient *zclient, | |
256 | zebra_size_t length, vrf_id_t vrf_id) | |
257 | { | |
258 | struct connected *c; | |
259 | struct interface *ifp; | |
260 | struct eigrp_interface *ei; | |
261 | struct route_node *rn; | |
262 | struct prefix p; | |
263 | ||
264 | c = zebra_interface_address_read (command, zclient->ibuf, vrf_id); | |
265 | ||
266 | if (c == NULL) | |
267 | return 0; | |
268 | ||
269 | if (IS_DEBUG_EIGRP (zebra, ZEBRA_INTERFACE)) | |
270 | { | |
271 | char buf[128]; | |
272 | prefix2str (c->address, buf, sizeof (buf)); | |
273 | zlog_debug ("Zebra: interface %s address delete %s", c->ifp->name, buf); | |
274 | } | |
275 | ||
276 | ifp = c->ifp; | |
277 | p = *c->address; | |
278 | p.prefixlen = IPV4_MAX_PREFIXLEN; | |
279 | ||
280 | rn = route_node_lookup (IF_OIFS (ifp), &p); | |
281 | if (!rn) | |
282 | { | |
283 | connected_free (c); | |
284 | return 0; | |
285 | } | |
286 | ||
287 | assert (rn->info); | |
288 | ei = rn->info; | |
289 | ||
290 | /* Call interface hook functions to clean up */ | |
291 | eigrp_if_free (ei, INTERFACE_DOWN_BY_ZEBRA); | |
292 | ||
293 | connected_free (c); | |
294 | ||
295 | return 0; | |
296 | } | |
297 | ||
298 | static int | |
299 | eigrp_interface_state_up (int command, struct zclient *zclient, | |
300 | zebra_size_t length, vrf_id_t vrf_id) | |
301 | { | |
302 | struct interface *ifp; | |
303 | struct eigrp_interface *ei; | |
304 | struct route_node *rn; | |
305 | ||
306 | ifp = zebra_interface_if_lookup (zclient->ibuf); | |
307 | ||
308 | if (ifp == NULL) | |
309 | return 0; | |
310 | ||
311 | /* Interface is already up. */ | |
312 | if (if_is_operative (ifp)) | |
313 | { | |
314 | /* Temporarily keep ifp values. */ | |
315 | struct interface if_tmp; | |
316 | memcpy (&if_tmp, ifp, sizeof (struct interface)); | |
317 | ||
318 | zebra_interface_if_set_value (zclient->ibuf, ifp); | |
319 | ||
320 | if (IS_DEBUG_EIGRP (zebra, ZEBRA_INTERFACE)) | |
321 | zlog_debug ("Zebra: Interface[%s] state update.", ifp->name); | |
322 | ||
323 | if (if_tmp.bandwidth != ifp->bandwidth) | |
324 | { | |
325 | if (IS_DEBUG_EIGRP (zebra, ZEBRA_INTERFACE)) | |
326 | zlog_debug ("Zebra: Interface[%s] bandwidth change %d -> %d.", | |
327 | ifp->name, if_tmp.bandwidth, ifp->bandwidth); | |
328 | ||
329 | // eigrp_if_recalculate_output_cost (ifp); | |
330 | } | |
331 | ||
332 | if (if_tmp.mtu != ifp->mtu) | |
333 | { | |
334 | if (IS_DEBUG_EIGRP (zebra, ZEBRA_INTERFACE)) | |
335 | zlog_debug ("Zebra: Interface[%s] MTU change %u -> %u.", | |
336 | ifp->name, if_tmp.mtu, ifp->mtu); | |
337 | ||
338 | /* Must reset the interface (simulate down/up) when MTU changes. */ | |
339 | eigrp_if_reset (ifp); | |
340 | } | |
341 | return 0; | |
342 | } | |
343 | ||
344 | zebra_interface_if_set_value (zclient->ibuf, ifp); | |
345 | ||
346 | if (IS_DEBUG_EIGRP (zebra, ZEBRA_INTERFACE)) | |
347 | zlog_debug ("Zebra: Interface[%s] state change to up.", ifp->name); | |
348 | ||
349 | for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn)) | |
350 | { | |
351 | if ((ei = rn->info) == NULL) | |
352 | continue; | |
353 | ||
354 | eigrp_if_up (ei); | |
355 | } | |
356 | ||
357 | return 0; | |
358 | } | |
359 | ||
360 | static int | |
361 | eigrp_interface_state_down (int command, struct zclient *zclient, | |
362 | zebra_size_t length, vrf_id_t vrf_id) | |
363 | { | |
364 | struct interface *ifp; | |
365 | struct eigrp_interface *ei; | |
366 | struct route_node *node; | |
367 | ||
368 | ifp = zebra_interface_state_read (zclient->ibuf, vrf_id); | |
369 | ||
370 | if (ifp == NULL) | |
371 | return 0; | |
372 | ||
373 | if (IS_DEBUG_EIGRP (zebra, ZEBRA_INTERFACE)) | |
374 | zlog_debug ("Zebra: Interface[%s] state change to down.", ifp->name); | |
375 | ||
376 | for (node = route_top (IF_OIFS (ifp)); node; node = route_next (node)) | |
377 | { | |
378 | if ((ei = node->info) == NULL) | |
379 | continue; | |
380 | eigrp_if_down (ei); | |
381 | } | |
382 | ||
383 | return 0; | |
384 | } | |
385 | ||
386 | static struct interface * | |
387 | zebra_interface_if_lookup (struct stream *s) | |
388 | { | |
389 | char ifname_tmp[INTERFACE_NAMSIZ]; | |
390 | ||
391 | /* Read interface name. */ | |
392 | stream_get (ifname_tmp, s, INTERFACE_NAMSIZ); | |
393 | ||
394 | /* And look it up. */ | |
395 | return if_lookup_by_name_len (ifname_tmp, | |
396 | strnlen (ifname_tmp, INTERFACE_NAMSIZ)); | |
397 | } | |
398 | ||
399 | void | |
400 | eigrp_zebra_route_add (struct prefix_ipv4 *p, struct eigrp_neighbor_entry *te) | |
401 | { | |
402 | u_char message; | |
403 | u_char flags; | |
404 | int psize; | |
405 | struct stream *s; | |
406 | ||
407 | if (zclient->redist[AFI_IP][ZEBRA_ROUTE_EIGRP]) | |
408 | { | |
409 | message = 0; | |
410 | flags = 0; | |
411 | ||
412 | /* EIGRP pass nexthop and metric */ | |
413 | SET_FLAG (message, ZAPI_MESSAGE_NEXTHOP); | |
414 | SET_FLAG (message, ZAPI_MESSAGE_METRIC); | |
415 | ||
416 | /* Distance value. */ | |
417 | // distance = eigrp_distance_apply (p, er); | |
418 | // if (distance) | |
419 | // SET_FLAG (message, ZAPI_MESSAGE_DISTANCE); | |
420 | ||
421 | /* Make packet. */ | |
422 | s = zclient->obuf; | |
423 | stream_reset (s); | |
424 | ||
425 | /* Put command, type, flags, message. */ | |
426 | zclient_create_header (s, ZEBRA_IPV4_ROUTE_ADD, VRF_DEFAULT); | |
427 | stream_putc (s, ZEBRA_ROUTE_EIGRP); | |
428 | stream_putc (s, flags); | |
429 | stream_putc (s, message); | |
430 | stream_putw (s, SAFI_UNICAST); | |
431 | ||
432 | /* Put prefix information. */ | |
433 | psize = PSIZE (p->prefixlen); | |
434 | stream_putc (s, p->prefixlen); | |
435 | stream_write (s, (u_char *) & p->prefix, psize); | |
436 | ||
437 | /* Nexthop count. */ | |
438 | stream_putc (s, 1); | |
439 | ||
440 | /* Nexthop, ifindex, distance and metric information. */ | |
441 | stream_putc (s, NEXTHOP_TYPE_IPV4_IFINDEX); | |
442 | stream_put_in_addr (s, &te->adv_router->src); | |
443 | stream_putl (s, te->ei->ifp->ifindex); | |
444 | ||
445 | if (IS_DEBUG_EIGRP (zebra, ZEBRA_REDISTRIBUTE)) | |
446 | { | |
447 | char buf[2][INET_ADDRSTRLEN]; | |
448 | zlog_debug ("Zebra: Route add %s/%d nexthop %s", | |
449 | inet_ntop(AF_INET, &p->prefix, buf[0], sizeof (buf[0])), | |
450 | p->prefixlen, | |
451 | inet_ntop(AF_INET, 0 /*&p->nexthop*/, buf[1], sizeof (buf[1]))); | |
452 | } | |
453 | ||
454 | stream_putl (s, te->distance); | |
455 | stream_putw_at (s, 0, stream_get_endp (s)); | |
456 | ||
457 | zclient_send_message (zclient); | |
458 | } | |
459 | } | |
460 | ||
461 | void | |
462 | eigrp_zebra_route_delete (struct prefix_ipv4 *p, struct eigrp_neighbor_entry *te) | |
463 | { | |
464 | u_char message; | |
465 | u_char flags; | |
466 | int psize; | |
467 | struct stream *s; | |
468 | ||
469 | if (zclient->redist[AFI_IP][ZEBRA_ROUTE_EIGRP]) | |
470 | { | |
471 | message = 0; | |
472 | flags = 0; | |
473 | /* Make packet. */ | |
474 | s = zclient->obuf; | |
475 | stream_reset (s); | |
476 | ||
477 | /* Put command, type, flags, message. */ | |
478 | zclient_create_header (s, ZEBRA_IPV4_ROUTE_DELETE, VRF_DEFAULT); | |
479 | stream_putc (s, ZEBRA_ROUTE_EIGRP); | |
480 | stream_putc (s, flags); | |
481 | stream_putc (s, message); | |
482 | stream_putw (s, SAFI_UNICAST); | |
483 | ||
484 | /* Put prefix information. */ | |
485 | psize = PSIZE (p->prefixlen); | |
486 | stream_putc (s, p->prefixlen); | |
487 | stream_write (s, (u_char *) & p->prefix, psize); | |
488 | ||
489 | /* Nexthop count. */ | |
490 | stream_putc (s, 1); | |
491 | ||
492 | /* Nexthop, ifindex, distance and metric information. */ | |
493 | stream_putc (s, NEXTHOP_TYPE_IPV4_IFINDEX); | |
494 | stream_put_in_addr (s, &te->adv_router->src); | |
495 | stream_putl (s, te->ei->ifp->ifindex); | |
496 | ||
497 | if (IS_DEBUG_EIGRP (zebra, ZEBRA_REDISTRIBUTE)) | |
498 | { | |
499 | char buf[2][INET_ADDRSTRLEN]; | |
500 | zlog_debug ("Zebra: Route del %s/%d nexthop %s", | |
501 | inet_ntop (AF_INET, &p->prefix, buf[0], sizeof (buf[0])), | |
502 | p->prefixlen, | |
503 | inet_ntop (AF_INET, 0 /*&p->nexthop*/, buf[1], sizeof (buf[1]))); | |
504 | } | |
505 | ||
506 | ||
507 | if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC)) | |
508 | { | |
509 | stream_putl (s, te->distance); | |
510 | } | |
511 | ||
512 | stream_putw_at (s, 0, stream_get_endp (s)); | |
513 | ||
514 | zclient_send_message (zclient); | |
515 | } | |
516 | } | |
517 | ||
518 | vrf_bitmap_t | |
519 | eigrp_is_type_redistributed (int type) | |
520 | { | |
521 | return (DEFAULT_ROUTE_TYPE (type)) ? | |
522 | zclient->default_information : zclient->redist[AFI_IP][type]; | |
523 | } | |
524 | ||
525 | int | |
526 | eigrp_redistribute_set (struct eigrp *eigrp, int type, struct eigrp_metrics metric) | |
527 | { | |
528 | ||
529 | if (eigrp_is_type_redistributed (type)) | |
530 | { | |
531 | if (eigrp_metrics_is_same(&metric, &eigrp->dmetric[type])) | |
532 | { | |
533 | eigrp->dmetric[type] = metric; | |
534 | } | |
535 | ||
536 | eigrp_external_routes_refresh (eigrp, type); | |
537 | ||
538 | // if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE)) | |
539 | // zlog_debug ("Redistribute[%s]: Refresh Type[%d], Metric[%d]", | |
540 | // eigrp_redist_string(type), | |
541 | // metric_type (eigrp, type), metric_value (eigrp, type)); | |
542 | return CMD_SUCCESS; | |
543 | } | |
544 | ||
545 | eigrp->dmetric[type] = metric; | |
546 | ||
547 | zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, | |
548 | AFI_IP, type, 0, VRF_DEFAULT); | |
549 | ||
550 | // if (IS_DEBUG_EIGRP (zebra, ZEBRA_REDISTRIBUTE)) | |
551 | // zlog_debug ("Redistribute[%s]: Start Type[%d], Metric[%d]", | |
552 | // ospf_redist_string(type), | |
553 | // metric_type (ospf, type), metric_value (ospf, type)); | |
554 | ||
555 | ++eigrp->redistribute; | |
556 | ||
557 | return CMD_SUCCESS; | |
558 | } | |
559 | ||
560 | int | |
561 | eigrp_redistribute_unset (struct eigrp *eigrp, int type) | |
562 | { | |
563 | ||
564 | if (eigrp_is_type_redistributed (type)) | |
565 | { | |
566 | memset(&eigrp->dmetric[type], 0, sizeof(struct eigrp_metrics)); | |
567 | zclient_redistribute (ZEBRA_REDISTRIBUTE_DELETE, zclient, | |
568 | AFI_IP, type, 0, VRF_DEFAULT); | |
569 | --eigrp->redistribute; | |
570 | } | |
571 | ||
572 | // if (IS_DEBUG_EIGRP (zebra, ZEBRA_REDISTRIBUTE)) | |
573 | // zlog_debug ("Redistribute[%s]: Start Type[%d], Metric[%d]", | |
574 | // ospf_redist_string(type), | |
575 | // metric_type (ospf, type), metric_value (ospf, type)); | |
576 | ||
577 | return CMD_SUCCESS; | |
578 | } | |
579 |