]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_zebra.c
Merge pull request #3931 from chiragshah6/evpn_dev1
[mirror_frr.git] / ospf6d / ospf6_zebra.c
1 /*
2 * Copyright (C) 2003 Yasuhiro Ohara
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 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
19 */
20
21 #include <zebra.h>
22
23 #include "log.h"
24 #include "vty.h"
25 #include "command.h"
26 #include "prefix.h"
27 #include "stream.h"
28 #include "zclient.h"
29 #include "memory.h"
30 #include "lib/bfd.h"
31 #include "lib_errors.h"
32
33 #include "ospf6_proto.h"
34 #include "ospf6_top.h"
35 #include "ospf6_interface.h"
36 #include "ospf6_route.h"
37 #include "ospf6_lsa.h"
38 #include "ospf6_lsdb.h"
39 #include "ospf6_asbr.h"
40 #include "ospf6_zebra.h"
41 #include "ospf6d.h"
42
43 DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_DISTANCE, "OSPF6 distance")
44
45 unsigned char conf_debug_ospf6_zebra = 0;
46
47 /* information about zebra. */
48 struct zclient *zclient = NULL;
49
50 /* Router-id update message from zebra. */
51 static int ospf6_router_id_update_zebra(int command, struct zclient *zclient,
52 zebra_size_t length, vrf_id_t vrf_id)
53 {
54 struct prefix router_id;
55 struct ospf6 *o = ospf6;
56
57 zebra_router_id_update_read(zclient->ibuf, &router_id);
58
59 om6->zebra_router_id = router_id.u.prefix4.s_addr;
60
61 if (o == NULL)
62 return 0;
63
64 o->router_id_zebra = router_id.u.prefix4;
65 if (IS_OSPF6_DEBUG_ZEBRA(RECV)) {
66 char buf[INET_ADDRSTRLEN];
67
68 zlog_debug("%s: zebra router-id %s update",
69 __PRETTY_FUNCTION__,
70 inet_ntop(AF_INET, &router_id.u.prefix4,
71 buf, INET_ADDRSTRLEN));
72 }
73
74 ospf6_router_id_update();
75
76 return 0;
77 }
78
79 /* redistribute function */
80 void ospf6_zebra_redistribute(int type)
81 {
82 if (vrf_bitmap_check(zclient->redist[AFI_IP6][type], VRF_DEFAULT))
83 return;
84 vrf_bitmap_set(zclient->redist[AFI_IP6][type], VRF_DEFAULT);
85
86 if (zclient->sock > 0)
87 zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient,
88 AFI_IP6, type, 0, VRF_DEFAULT);
89 }
90
91 void ospf6_zebra_no_redistribute(int type)
92 {
93 if (!vrf_bitmap_check(zclient->redist[AFI_IP6][type], VRF_DEFAULT))
94 return;
95 vrf_bitmap_unset(zclient->redist[AFI_IP6][type], VRF_DEFAULT);
96 if (zclient->sock > 0)
97 zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient,
98 AFI_IP6, type, 0, VRF_DEFAULT);
99 }
100
101 /* Inteface addition message from zebra. */
102 static int ospf6_zebra_if_add(int command, struct zclient *zclient,
103 zebra_size_t length, vrf_id_t vrf_id)
104 {
105 struct interface *ifp;
106
107 ifp = zebra_interface_add_read(zclient->ibuf, vrf_id);
108 if (IS_OSPF6_DEBUG_ZEBRA(RECV))
109 zlog_debug("Zebra Interface add: %s index %d mtu %d", ifp->name,
110 ifp->ifindex, ifp->mtu6);
111 ospf6_interface_if_add(ifp);
112 return 0;
113 }
114
115 static int ospf6_zebra_if_del(int command, struct zclient *zclient,
116 zebra_size_t length, vrf_id_t vrf_id)
117 {
118 struct interface *ifp;
119
120 if (!(ifp = zebra_interface_state_read(zclient->ibuf, vrf_id)))
121 return 0;
122
123 if (if_is_up(ifp))
124 zlog_warn("Zebra: got delete of %s, but interface is still up",
125 ifp->name);
126
127 if (IS_OSPF6_DEBUG_ZEBRA(RECV))
128 zlog_debug("Zebra Interface delete: %s index %d mtu %d",
129 ifp->name, ifp->ifindex, ifp->mtu6);
130
131 if_set_index(ifp, IFINDEX_INTERNAL);
132 return 0;
133 }
134
135 static int ospf6_zebra_if_state_update(int command, struct zclient *zclient,
136 zebra_size_t length, vrf_id_t vrf_id)
137 {
138 struct interface *ifp;
139
140 ifp = zebra_interface_state_read(zclient->ibuf, vrf_id);
141 if (ifp == NULL)
142 return 0;
143
144 if (IS_OSPF6_DEBUG_ZEBRA(RECV))
145 zlog_debug(
146 "Zebra Interface state change: "
147 "%s index %d flags %llx metric %d mtu %d bandwidth %d",
148 ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
149 ifp->metric, ifp->mtu6, ifp->bandwidth);
150
151 ospf6_interface_state_update(ifp);
152 return 0;
153 }
154
155 static int ospf6_zebra_if_address_update_add(int command,
156 struct zclient *zclient,
157 zebra_size_t length,
158 vrf_id_t vrf_id)
159 {
160 struct connected *c;
161 char buf[128];
162
163 c = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD,
164 zclient->ibuf, vrf_id);
165 if (c == NULL)
166 return 0;
167
168 if (IS_OSPF6_DEBUG_ZEBRA(RECV))
169 zlog_debug("Zebra Interface address add: %s %5s %s/%d",
170 c->ifp->name, prefix_family_str(c->address),
171 inet_ntop(c->address->family, &c->address->u.prefix,
172 buf, sizeof(buf)),
173 c->address->prefixlen);
174
175 if (c->address->family == AF_INET6) {
176 ospf6_interface_state_update(c->ifp);
177 ospf6_interface_connected_route_update(c->ifp);
178 }
179 return 0;
180 }
181
182 static int ospf6_zebra_if_address_update_delete(int command,
183 struct zclient *zclient,
184 zebra_size_t length,
185 vrf_id_t vrf_id)
186 {
187 struct connected *c;
188 char buf[128];
189
190 c = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE,
191 zclient->ibuf, vrf_id);
192 if (c == NULL)
193 return 0;
194
195 if (IS_OSPF6_DEBUG_ZEBRA(RECV))
196 zlog_debug("Zebra Interface address delete: %s %5s %s/%d",
197 c->ifp->name, prefix_family_str(c->address),
198 inet_ntop(c->address->family, &c->address->u.prefix,
199 buf, sizeof(buf)),
200 c->address->prefixlen);
201
202 if (c->address->family == AF_INET6) {
203 ospf6_interface_connected_route_update(c->ifp);
204 ospf6_interface_state_update(c->ifp);
205 }
206
207 connected_free(c);
208
209 return 0;
210 }
211
212 static int ospf6_zebra_read_route(int command, struct zclient *zclient,
213 zebra_size_t length, vrf_id_t vrf_id)
214 {
215 struct zapi_route api;
216 unsigned long ifindex;
217 struct in6_addr *nexthop;
218
219 if (ospf6 == NULL)
220 return 0;
221
222 if (zapi_route_decode(zclient->ibuf, &api) < 0)
223 return -1;
224
225 /* we completely ignore srcdest routes for now. */
226 if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
227 return 0;
228
229 if (IN6_IS_ADDR_LINKLOCAL(&api.prefix.u.prefix6))
230 return 0;
231
232 ifindex = api.nexthops[0].ifindex;
233 nexthop = &api.nexthops[0].gate.ipv6;
234
235 if (IS_OSPF6_DEBUG_ZEBRA(RECV)) {
236 char prefixstr[PREFIX2STR_BUFFER], nexthopstr[128];
237 prefix2str((struct prefix *)&api.prefix, prefixstr,
238 sizeof(prefixstr));
239 inet_ntop(AF_INET6, nexthop, nexthopstr, sizeof(nexthopstr));
240
241 zlog_debug(
242 "Zebra Receive route %s: %s %s nexthop %s ifindex %ld tag %" ROUTE_TAG_PRI,
243 (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD ? "add"
244 : "delete"),
245 zebra_route_string(api.type), prefixstr, nexthopstr,
246 ifindex, api.tag);
247 }
248
249 if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
250 ospf6_asbr_redistribute_add(api.type, ifindex, &api.prefix,
251 api.nexthop_num, nexthop, api.tag);
252 else
253 ospf6_asbr_redistribute_remove(api.type, ifindex, &api.prefix);
254
255 return 0;
256 }
257
258 DEFUN (show_zebra,
259 show_ospf6_zebra_cmd,
260 "show ipv6 ospf6 zebra",
261 SHOW_STR
262 IPV6_STR
263 OSPF6_STR
264 ZEBRA_STR)
265 {
266 int i;
267 if (zclient == NULL) {
268 vty_out(vty, "Not connected to zebra\n");
269 return CMD_SUCCESS;
270 }
271
272 vty_out(vty, "Zebra Infomation\n");
273 vty_out(vty, " fail: %d\n", zclient->fail);
274 vty_out(vty, " redistribute default: %d\n",
275 vrf_bitmap_check(zclient->default_information[AFI_IP6],
276 VRF_DEFAULT));
277 vty_out(vty, " redistribute:");
278 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
279 if (vrf_bitmap_check(zclient->redist[AFI_IP6][i], VRF_DEFAULT))
280 vty_out(vty, " %s", zebra_route_string(i));
281 }
282 vty_out(vty, "\n");
283 return CMD_SUCCESS;
284 }
285
286 #define ADD 0
287 #define REM 1
288 static void ospf6_zebra_route_update(int type, struct ospf6_route *request)
289 {
290 struct zapi_route api;
291 char buf[PREFIX2STR_BUFFER];
292 int nhcount;
293 int ret = 0;
294 struct prefix *dest;
295
296 if (IS_OSPF6_DEBUG_ZEBRA(SEND)) {
297 prefix2str(&request->prefix, buf, sizeof(buf));
298 zlog_debug("Send %s route: %s",
299 (type == REM ? "remove" : "add"), buf);
300 }
301
302 if (zclient->sock < 0) {
303 if (IS_OSPF6_DEBUG_ZEBRA(SEND))
304 zlog_debug(" Not connected to Zebra");
305 return;
306 }
307
308 if (request->path.origin.adv_router == ospf6->router_id
309 && (request->path.type == OSPF6_PATH_TYPE_EXTERNAL1
310 || request->path.type == OSPF6_PATH_TYPE_EXTERNAL2)) {
311 if (IS_OSPF6_DEBUG_ZEBRA(SEND))
312 zlog_debug(" Ignore self-originated external route");
313 return;
314 }
315
316 /* If removing is the best path and if there's another path,
317 treat this request as add the secondary path */
318 if (type == REM && ospf6_route_is_best(request) && request->next
319 && ospf6_route_is_same(request, request->next)) {
320 if (IS_OSPF6_DEBUG_ZEBRA(SEND))
321 zlog_debug(
322 " Best-path removal resulted Sencondary addition");
323 type = ADD;
324 request = request->next;
325 }
326
327 /* Only the best path will be sent to zebra. */
328 if (!ospf6_route_is_best(request)) {
329 /* this is not preferred best route, ignore */
330 if (IS_OSPF6_DEBUG_ZEBRA(SEND))
331 zlog_debug(" Ignore non-best route");
332 return;
333 }
334
335 nhcount = ospf6_route_num_nexthops(request);
336 if (nhcount == 0) {
337 if (IS_OSPF6_DEBUG_ZEBRA(SEND))
338 zlog_debug(" No nexthop, ignore");
339 return;
340 }
341
342 dest = &request->prefix;
343
344 memset(&api, 0, sizeof(api));
345 api.vrf_id = VRF_DEFAULT;
346 api.type = ZEBRA_ROUTE_OSPF6;
347 api.safi = SAFI_UNICAST;
348 api.prefix = *dest;
349 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
350 api.nexthop_num = MIN(nhcount, MULTIPATH_NUM);
351 ospf6_route_zebra_copy_nexthops(request, api.nexthops, api.nexthop_num);
352 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
353 api.metric = (request->path.metric_type == 2 ? request->path.u.cost_e2
354 : request->path.cost);
355 if (request->path.tag) {
356 SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
357 api.tag = request->path.tag;
358 }
359
360 SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
361 api.distance =
362 ospf6_distance_apply((struct prefix_ipv6 *)dest, request);
363
364 if (type == REM)
365 ret = zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
366 else
367 ret = zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
368
369 if (ret < 0)
370 flog_err(EC_LIB_ZAPI_SOCKET,
371 "zclient_route_send() %s failed: %s",
372 (type == REM ? "delete" : "add"),
373 safe_strerror(errno));
374
375 return;
376 }
377
378 void ospf6_zebra_route_update_add(struct ospf6_route *request)
379 {
380 ospf6_zebra_route_update(ADD, request);
381 }
382
383 void ospf6_zebra_route_update_remove(struct ospf6_route *request)
384 {
385 ospf6_zebra_route_update(REM, request);
386 }
387
388 void ospf6_zebra_add_discard(struct ospf6_route *request)
389 {
390 struct zapi_route api;
391 char buf[INET6_ADDRSTRLEN];
392 struct prefix *dest = &request->prefix;
393
394 if (!CHECK_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) {
395 memset(&api, 0, sizeof(api));
396 api.vrf_id = VRF_DEFAULT;
397 api.type = ZEBRA_ROUTE_OSPF6;
398 api.safi = SAFI_UNICAST;
399 api.prefix = *dest;
400 zapi_route_set_blackhole(&api, BLACKHOLE_NULL);
401
402 zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
403
404 if (IS_OSPF6_DEBUG_ZEBRA(SEND))
405 zlog_debug("Zebra: Route add discard %s/%d",
406 inet_ntop(AF_INET6, &dest->u.prefix6, buf,
407 INET6_ADDRSTRLEN),
408 dest->prefixlen);
409
410 SET_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED);
411 } else {
412 if (IS_OSPF6_DEBUG_ZEBRA(SEND))
413 zlog_debug(
414 "Zebra: Blackhole route present already %s/%d",
415 inet_ntop(AF_INET6, &dest->u.prefix6, buf,
416 INET6_ADDRSTRLEN),
417 dest->prefixlen);
418 }
419 }
420
421 void ospf6_zebra_delete_discard(struct ospf6_route *request)
422 {
423 struct zapi_route api;
424 char buf[INET6_ADDRSTRLEN];
425 struct prefix *dest = &request->prefix;
426
427 if (CHECK_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) {
428 memset(&api, 0, sizeof(api));
429 api.vrf_id = VRF_DEFAULT;
430 api.type = ZEBRA_ROUTE_OSPF6;
431 api.safi = SAFI_UNICAST;
432 api.prefix = *dest;
433 zapi_route_set_blackhole(&api, BLACKHOLE_NULL);
434
435 zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
436
437 if (IS_OSPF6_DEBUG_ZEBRA(SEND))
438 zlog_debug("Zebra: Route delete discard %s/%d",
439 inet_ntop(AF_INET6, &dest->u.prefix6, buf,
440 INET6_ADDRSTRLEN),
441 dest->prefixlen);
442
443 UNSET_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED);
444 } else {
445 if (IS_OSPF6_DEBUG_ZEBRA(SEND))
446 zlog_debug(
447 "Zebra: Blackhole route already deleted %s/%d",
448 inet_ntop(AF_INET6, &dest->u.prefix6, buf,
449 INET6_ADDRSTRLEN),
450 dest->prefixlen);
451 }
452 }
453
454 static struct ospf6_distance *ospf6_distance_new(void)
455 {
456 return XCALLOC(MTYPE_OSPF6_DISTANCE, sizeof(struct ospf6_distance));
457 }
458
459 static void ospf6_distance_free(struct ospf6_distance *odistance)
460 {
461 XFREE(MTYPE_OSPF6_DISTANCE, odistance);
462 }
463
464 int ospf6_distance_set(struct vty *vty, struct ospf6 *o,
465 const char *distance_str, const char *ip_str,
466 const char *access_list_str)
467 {
468 int ret;
469 struct prefix_ipv6 p;
470 uint8_t distance;
471 struct route_node *rn;
472 struct ospf6_distance *odistance;
473
474 ret = str2prefix_ipv6(ip_str, &p);
475 if (ret == 0) {
476 vty_out(vty, "Malformed prefix\n");
477 return CMD_WARNING_CONFIG_FAILED;
478 }
479
480 distance = atoi(distance_str);
481
482 /* Get OSPF6 distance node. */
483 rn = route_node_get(o->distance_table, (struct prefix *)&p);
484 if (rn->info) {
485 odistance = rn->info;
486 route_unlock_node(rn);
487 } else {
488 odistance = ospf6_distance_new();
489 rn->info = odistance;
490 }
491
492 /* Set distance value. */
493 odistance->distance = distance;
494
495 /* Reset access-list configuration. */
496 if (odistance->access_list) {
497 free(odistance->access_list);
498 odistance->access_list = NULL;
499 }
500 if (access_list_str)
501 odistance->access_list = strdup(access_list_str);
502
503 return CMD_SUCCESS;
504 }
505
506 int ospf6_distance_unset(struct vty *vty, struct ospf6 *o,
507 const char *distance_str, const char *ip_str,
508 const char *access_list_str)
509 {
510 int ret;
511 struct prefix_ipv6 p;
512 struct route_node *rn;
513 struct ospf6_distance *odistance;
514
515 ret = str2prefix_ipv6(ip_str, &p);
516 if (ret == 0) {
517 vty_out(vty, "Malformed prefix\n");
518 return CMD_WARNING_CONFIG_FAILED;
519 }
520
521 rn = route_node_lookup(o->distance_table, (struct prefix *)&p);
522 if (!rn) {
523 vty_out(vty, "Cant't find specified prefix\n");
524 return CMD_WARNING_CONFIG_FAILED;
525 }
526
527 odistance = rn->info;
528
529 if (odistance->access_list)
530 free(odistance->access_list);
531 ospf6_distance_free(odistance);
532
533 rn->info = NULL;
534 route_unlock_node(rn);
535 route_unlock_node(rn);
536
537 return CMD_SUCCESS;
538 }
539
540 void ospf6_distance_reset(struct ospf6 *o)
541 {
542 struct route_node *rn;
543 struct ospf6_distance *odistance;
544
545 for (rn = route_top(o->distance_table); rn; rn = route_next(rn))
546 if ((odistance = rn->info) != NULL) {
547 if (odistance->access_list)
548 free(odistance->access_list);
549 ospf6_distance_free(odistance);
550 rn->info = NULL;
551 route_unlock_node(rn);
552 }
553 }
554
555 uint8_t ospf6_distance_apply(struct prefix_ipv6 *p, struct ospf6_route * or)
556 {
557 struct ospf6 *o;
558
559 o = ospf6;
560 if (o == NULL)
561 return 0;
562
563 if (o->distance_intra)
564 if (or->path.type == OSPF6_PATH_TYPE_INTRA)
565 return o->distance_intra;
566
567 if (o->distance_inter)
568 if (or->path.type == OSPF6_PATH_TYPE_INTER)
569 return o->distance_inter;
570
571 if (o->distance_external)
572 if (or->path.type == OSPF6_PATH_TYPE_EXTERNAL1 ||
573 or->path.type == OSPF6_PATH_TYPE_EXTERNAL2)
574 return o->distance_external;
575
576 if (o->distance_all)
577 return o->distance_all;
578
579 return 0;
580 }
581
582 static void ospf6_zebra_connected(struct zclient *zclient)
583 {
584 /* Send the client registration */
585 bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER);
586
587 zclient_send_reg_requests(zclient, VRF_DEFAULT);
588 }
589
590 void ospf6_zebra_init(struct thread_master *master)
591 {
592 /* Allocate zebra structure. */
593 zclient = zclient_new(master, &zclient_options_default);
594 zclient_init(zclient, ZEBRA_ROUTE_OSPF6, 0, &ospf6d_privs);
595 zclient->zebra_connected = ospf6_zebra_connected;
596 zclient->router_id_update = ospf6_router_id_update_zebra;
597 zclient->interface_add = ospf6_zebra_if_add;
598 zclient->interface_delete = ospf6_zebra_if_del;
599 zclient->interface_up = ospf6_zebra_if_state_update;
600 zclient->interface_down = ospf6_zebra_if_state_update;
601 zclient->interface_address_add = ospf6_zebra_if_address_update_add;
602 zclient->interface_address_delete =
603 ospf6_zebra_if_address_update_delete;
604 zclient->redistribute_route_add = ospf6_zebra_read_route;
605 zclient->redistribute_route_del = ospf6_zebra_read_route;
606
607 /* Install command element for zebra node. */
608 install_element(VIEW_NODE, &show_ospf6_zebra_cmd);
609 }
610
611 /* Debug */
612
613 DEFUN (debug_ospf6_zebra_sendrecv,
614 debug_ospf6_zebra_sendrecv_cmd,
615 "debug ospf6 zebra [<send|recv>]",
616 DEBUG_STR
617 OSPF6_STR
618 "Debug connection between zebra\n"
619 "Debug Sending zebra\n"
620 "Debug Receiving zebra\n"
621 )
622 {
623 int idx_send_recv = 3;
624 unsigned char level = 0;
625
626 if (argc == 4) {
627 if (strmatch(argv[idx_send_recv]->text, "send"))
628 level = OSPF6_DEBUG_ZEBRA_SEND;
629 else if (strmatch(argv[idx_send_recv]->text, "recv"))
630 level = OSPF6_DEBUG_ZEBRA_RECV;
631 } else
632 level = OSPF6_DEBUG_ZEBRA_SEND | OSPF6_DEBUG_ZEBRA_RECV;
633
634 OSPF6_DEBUG_ZEBRA_ON(level);
635 return CMD_SUCCESS;
636 }
637
638 DEFUN (no_debug_ospf6_zebra_sendrecv,
639 no_debug_ospf6_zebra_sendrecv_cmd,
640 "no debug ospf6 zebra [<send|recv>]",
641 NO_STR
642 DEBUG_STR
643 OSPF6_STR
644 "Debug connection between zebra\n"
645 "Debug Sending zebra\n"
646 "Debug Receiving zebra\n"
647 )
648 {
649 int idx_send_recv = 4;
650 unsigned char level = 0;
651
652 if (argc == 5) {
653 if (strmatch(argv[idx_send_recv]->text, "send"))
654 level = OSPF6_DEBUG_ZEBRA_SEND;
655 else if (strmatch(argv[idx_send_recv]->text, "recv"))
656 level = OSPF6_DEBUG_ZEBRA_RECV;
657 } else
658 level = OSPF6_DEBUG_ZEBRA_SEND | OSPF6_DEBUG_ZEBRA_RECV;
659
660 OSPF6_DEBUG_ZEBRA_OFF(level);
661 return CMD_SUCCESS;
662 }
663
664
665 int config_write_ospf6_debug_zebra(struct vty *vty)
666 {
667 if (IS_OSPF6_DEBUG_ZEBRA(SEND) && IS_OSPF6_DEBUG_ZEBRA(RECV))
668 vty_out(vty, "debug ospf6 zebra\n");
669 else {
670 if (IS_OSPF6_DEBUG_ZEBRA(SEND))
671 vty_out(vty, "debug ospf6 zebra send\n");
672 if (IS_OSPF6_DEBUG_ZEBRA(RECV))
673 vty_out(vty, "debug ospf6 zebra recv\n");
674 }
675 return 0;
676 }
677
678 void install_element_ospf6_debug_zebra(void)
679 {
680 install_element(ENABLE_NODE, &debug_ospf6_zebra_sendrecv_cmd);
681 install_element(ENABLE_NODE, &no_debug_ospf6_zebra_sendrecv_cmd);
682 install_element(CONFIG_NODE, &debug_ospf6_zebra_sendrecv_cmd);
683 install_element(CONFIG_NODE, &no_debug_ospf6_zebra_sendrecv_cmd);
684 }