1 /*
2  * EIGRP daemon northbound implementation.
3  *
4  * Copyright (C) 2019 Network Device Education Foundation, Inc. ("NetDEF")
5  *                    Rafael Zalamena
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20  * 02110-1301 USA.
21  */
22 
23 #include <zebra.h>
24 
25 #include "lib/keychain.h"
26 #include "lib/log.h"
27 #include "lib/northbound.h"
28 #include "lib/table.h"
29 #include "lib/vrf.h"
30 #include "lib/zclient.h"
31 
32 #include "eigrp_structs.h"
33 #include "eigrpd.h"
34 #include "eigrp_interface.h"
35 #include "eigrp_network.h"
36 #include "eigrp_zebra.h"
37 
38 /* Helper functions. */
redistribute_get_metrics(const struct lyd_node * dnode,struct eigrp_metrics * em)39 static void redistribute_get_metrics(const struct lyd_node *dnode,
40 				     struct eigrp_metrics *em)
41 {
42 	memset(em, 0, sizeof(*em));
43 
44 	if (yang_dnode_exists(dnode, "./bandwidth"))
45 		em->bandwidth = yang_dnode_get_uint32(dnode, "./bandwidth");
46 	if (yang_dnode_exists(dnode, "./delay"))
47 		em->delay = yang_dnode_get_uint32(dnode, "./delay");
48 #if 0 /* TODO: How does MTU work? */
49 	if (yang_dnode_exists(dnode, "./mtu"))
50 		em->mtu[0] = yang_dnode_get_uint32(dnode, "./mtu");
51 #endif
52 	if (yang_dnode_exists(dnode, "./load"))
53 		em->load = yang_dnode_get_uint32(dnode, "./load");
54 	if (yang_dnode_exists(dnode, "./reliability"))
55 		em->reliability = yang_dnode_get_uint32(dnode, "./reliability");
56 }
57 
eigrp_interface_lookup(const struct eigrp * eigrp,const char * ifname)58 static struct eigrp_interface *eigrp_interface_lookup(const struct eigrp *eigrp,
59 						      const char *ifname)
60 {
61 	struct eigrp_interface *eif;
62 	struct listnode *ln;
63 
64 	for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, ln, eif)) {
65 		if (strcmp(ifname, eif->ifp->name))
66 			continue;
67 
68 		return eif;
69 	}
70 
71 	return NULL;
72 }
73 
74 /*
75  * XPath: /frr-eigrpd:eigrpd/instance
76  */
eigrpd_instance_create(struct nb_cb_create_args * args)77 static int eigrpd_instance_create(struct nb_cb_create_args *args)
78 {
79 	struct eigrp *eigrp;
80 	const char *vrf;
81 	vrf_id_t vrfid;
82 
83 	switch (args->event) {
84 	case NB_EV_VALIDATE:
85 		/* NOTHING */
86 		break;
87 	case NB_EV_PREPARE:
88 		vrf = yang_dnode_get_string(args->dnode, "./vrf");
89 		vrfid = vrf_name_to_id(vrf);
90 
91 		eigrp = eigrp_get(yang_dnode_get_uint16(args->dnode, "./asn"),
92 				  vrfid);
93 		args->resource->ptr = eigrp;
94 		break;
95 	case NB_EV_ABORT:
96 		eigrp_finish_final(args->resource->ptr);
97 		break;
98 	case NB_EV_APPLY:
99 		nb_running_set_entry(args->dnode, args->resource->ptr);
100 		break;
101 	}
102 
103 	return NB_OK;
104 }
105 
eigrpd_instance_destroy(struct nb_cb_destroy_args * args)106 static int eigrpd_instance_destroy(struct nb_cb_destroy_args *args)
107 {
108 	struct eigrp *eigrp;
109 
110 	switch (args->event) {
111 	case NB_EV_VALIDATE:
112 	case NB_EV_PREPARE:
113 	case NB_EV_ABORT:
114 		/* NOTHING */
115 		break;
116 	case NB_EV_APPLY:
117 		eigrp = nb_running_unset_entry(args->dnode);
118 		eigrp_finish_final(eigrp);
119 		break;
120 	}
121 
122 	return NB_OK;
123 }
124 
125 /*
126  * XPath: /frr-eigrpd:eigrpd/instance/router-id
127  */
eigrpd_instance_router_id_modify(struct nb_cb_modify_args * args)128 static int eigrpd_instance_router_id_modify(struct nb_cb_modify_args *args)
129 {
130 	struct eigrp *eigrp;
131 
132 	switch (args->event) {
133 	case NB_EV_VALIDATE:
134 	case NB_EV_PREPARE:
135 	case NB_EV_ABORT:
136 		/* NOTHING */
137 		break;
138 	case NB_EV_APPLY:
139 		eigrp = nb_running_get_entry(args->dnode, NULL, true);
140 		yang_dnode_get_ipv4(&eigrp->router_id_static, args->dnode,
141 				    NULL);
142 		break;
143 	}
144 
145 	return NB_OK;
146 }
147 
eigrpd_instance_router_id_destroy(struct nb_cb_destroy_args * args)148 static int eigrpd_instance_router_id_destroy(struct nb_cb_destroy_args *args)
149 {
150 	struct eigrp *eigrp;
151 
152 	switch (args->event) {
153 	case NB_EV_VALIDATE:
154 	case NB_EV_PREPARE:
155 	case NB_EV_ABORT:
156 		/* NOTHING */
157 		break;
158 	case NB_EV_APPLY:
159 		eigrp = nb_running_get_entry(args->dnode, NULL, true);
160 		eigrp->router_id_static.s_addr = INADDR_ANY;
161 		break;
162 	}
163 
164 	return NB_OK;
165 }
166 
167 /*
168  * XPath: /frr-eigrpd:eigrpd/instance/passive-interface
169  */
170 static int
eigrpd_instance_passive_interface_create(struct nb_cb_create_args * args)171 eigrpd_instance_passive_interface_create(struct nb_cb_create_args *args)
172 {
173 	struct eigrp_interface *eif;
174 	struct eigrp *eigrp;
175 	const char *ifname;
176 
177 	switch (args->event) {
178 	case NB_EV_VALIDATE:
179 		eigrp = nb_running_get_entry(args->dnode, NULL, false);
180 		if (eigrp == NULL) {
181 			/*
182 			 * XXX: we can't verify if the interface exists
183 			 * and is active until EIGRP is up.
184 			 */
185 			break;
186 		}
187 
188 		ifname = yang_dnode_get_string(args->dnode, NULL);
189 		eif = eigrp_interface_lookup(eigrp, ifname);
190 		if (eif == NULL)
191 			return NB_ERR_INCONSISTENCY;
192 		break;
193 	case NB_EV_PREPARE:
194 	case NB_EV_ABORT:
195 		/* NOTHING */
196 		break;
197 	case NB_EV_APPLY:
198 		eigrp = nb_running_get_entry(args->dnode, NULL, true);
199 		ifname = yang_dnode_get_string(args->dnode, NULL);
200 		eif = eigrp_interface_lookup(eigrp, ifname);
201 		if (eif == NULL)
202 			return NB_ERR_INCONSISTENCY;
203 
204 		eif->params.passive_interface = EIGRP_IF_PASSIVE;
205 		break;
206 	}
207 
208 	return NB_OK;
209 }
210 
211 static int
eigrpd_instance_passive_interface_destroy(struct nb_cb_destroy_args * args)212 eigrpd_instance_passive_interface_destroy(struct nb_cb_destroy_args *args)
213 {
214 	struct eigrp_interface *eif;
215 	struct eigrp *eigrp;
216 	const char *ifname;
217 
218 	switch (args->event) {
219 	case NB_EV_VALIDATE:
220 	case NB_EV_PREPARE:
221 	case NB_EV_ABORT:
222 		/* NOTHING */
223 		break;
224 	case NB_EV_APPLY:
225 		eigrp = nb_running_get_entry(args->dnode, NULL, true);
226 		ifname = yang_dnode_get_string(args->dnode, NULL);
227 		eif = eigrp_interface_lookup(eigrp, ifname);
228 		if (eif == NULL)
229 			break;
230 
231 		eif->params.passive_interface = EIGRP_IF_ACTIVE;
232 		break;
233 	}
234 
235 	return NB_OK;
236 }
237 
238 /*
239  * XPath: /frr-eigrpd:eigrpd/instance/active-time
240  */
eigrpd_instance_active_time_modify(struct nb_cb_modify_args * args)241 static int eigrpd_instance_active_time_modify(struct nb_cb_modify_args *args)
242 {
243 	switch (args->event) {
244 	case NB_EV_VALIDATE:
245 		/* TODO: Not implemented. */
246 		return NB_ERR_INCONSISTENCY;
247 	case NB_EV_PREPARE:
248 	case NB_EV_ABORT:
249 	case NB_EV_APPLY:
250 		/* NOTHING */
251 		break;
252 	}
253 
254 	return NB_OK;
255 }
256 
257 /*
258  * XPath: /frr-eigrpd:eigrpd/instance/variance
259  */
eigrpd_instance_variance_modify(struct nb_cb_modify_args * args)260 static int eigrpd_instance_variance_modify(struct nb_cb_modify_args *args)
261 {
262 	struct eigrp *eigrp;
263 
264 	switch (args->event) {
265 	case NB_EV_VALIDATE:
266 	case NB_EV_PREPARE:
267 	case NB_EV_ABORT:
268 		/* NOTHING */
269 		break;
270 	case NB_EV_APPLY:
271 		eigrp = nb_running_get_entry(args->dnode, NULL, true);
272 		eigrp->variance = yang_dnode_get_uint8(args->dnode, NULL);
273 		break;
274 	}
275 
276 	return NB_OK;
277 }
278 
eigrpd_instance_variance_destroy(struct nb_cb_destroy_args * args)279 static int eigrpd_instance_variance_destroy(struct nb_cb_destroy_args *args)
280 {
281 	struct eigrp *eigrp;
282 
283 	switch (args->event) {
284 	case NB_EV_VALIDATE:
285 	case NB_EV_PREPARE:
286 	case NB_EV_ABORT:
287 		/* NOTHING */
288 		break;
289 	case NB_EV_APPLY:
290 		eigrp = nb_running_get_entry(args->dnode, NULL, true);
291 		eigrp->variance = EIGRP_VARIANCE_DEFAULT;
292 		break;
293 	}
294 
295 	return NB_OK;
296 }
297 
298 /*
299  * XPath: /frr-eigrpd:eigrpd/instance/maximum-paths
300  */
eigrpd_instance_maximum_paths_modify(struct nb_cb_modify_args * args)301 static int eigrpd_instance_maximum_paths_modify(struct nb_cb_modify_args *args)
302 {
303 	struct eigrp *eigrp;
304 
305 	switch (args->event) {
306 	case NB_EV_VALIDATE:
307 	case NB_EV_PREPARE:
308 	case NB_EV_ABORT:
309 		/* NOTHING */
310 		break;
311 	case NB_EV_APPLY:
312 		eigrp = nb_running_get_entry(args->dnode, NULL, true);
313 		eigrp->max_paths = yang_dnode_get_uint8(args->dnode, NULL);
314 		break;
315 	}
316 
317 	return NB_OK;
318 }
319 
320 static int
eigrpd_instance_maximum_paths_destroy(struct nb_cb_destroy_args * args)321 eigrpd_instance_maximum_paths_destroy(struct nb_cb_destroy_args *args)
322 {
323 	struct eigrp *eigrp;
324 
325 	switch (args->event) {
326 	case NB_EV_VALIDATE:
327 	case NB_EV_PREPARE:
328 	case NB_EV_ABORT:
329 		/* NOTHING */
330 		break;
331 	case NB_EV_APPLY:
332 		eigrp = nb_running_get_entry(args->dnode, NULL, true);
333 		eigrp->max_paths = EIGRP_MAX_PATHS_DEFAULT;
334 		break;
335 	}
336 
337 	return NB_OK;
338 }
339 
340 /*
341  * XPath: /frr-eigrpd:eigrpd/instance/metric-weights/K1
342  */
343 static int
eigrpd_instance_metric_weights_K1_modify(struct nb_cb_modify_args * args)344 eigrpd_instance_metric_weights_K1_modify(struct nb_cb_modify_args *args)
345 {
346 	struct eigrp *eigrp;
347 
348 	switch (args->event) {
349 	case NB_EV_VALIDATE:
350 	case NB_EV_PREPARE:
351 	case NB_EV_ABORT:
352 		/* NOTHING */
353 		break;
354 	case NB_EV_APPLY:
355 		eigrp = nb_running_get_entry(args->dnode, NULL, true);
356 		eigrp->k_values[0] = yang_dnode_get_uint8(args->dnode, NULL);
357 		break;
358 	}
359 
360 	return NB_OK;
361 }
362 
363 static int
eigrpd_instance_metric_weights_K1_destroy(struct nb_cb_destroy_args * args)364 eigrpd_instance_metric_weights_K1_destroy(struct nb_cb_destroy_args *args)
365 {
366 	struct eigrp *eigrp;
367 
368 	switch (args->event) {
369 	case NB_EV_VALIDATE:
370 	case NB_EV_PREPARE:
371 	case NB_EV_ABORT:
372 		/* NOTHING */
373 		break;
374 	case NB_EV_APPLY:
375 		eigrp = nb_running_get_entry(args->dnode, NULL, true);
376 		eigrp->k_values[0] = EIGRP_K1_DEFAULT;
377 		break;
378 	}
379 
380 	return NB_OK;
381 }
382 
383 /*
384  * XPath: /frr-eigrpd:eigrpd/instance/metric-weights/K2
385  */
386 static int
eigrpd_instance_metric_weights_K2_modify(struct nb_cb_modify_args * args)387 eigrpd_instance_metric_weights_K2_modify(struct nb_cb_modify_args *args)
388 {
389 	struct eigrp *eigrp;
390 
391 	switch (args->event) {
392 	case NB_EV_VALIDATE:
393 	case NB_EV_PREPARE:
394 	case NB_EV_ABORT:
395 		/* NOTHING */
396 		break;
397 	case NB_EV_APPLY:
398 		eigrp = nb_running_get_entry(args->dnode, NULL, true);
399 		eigrp->k_values[1] = yang_dnode_get_uint8(args->dnode, NULL);
400 		break;
401 	}
402 
403 	return NB_OK;
404 }
405 
406 static int
eigrpd_instance_metric_weights_K2_destroy(struct nb_cb_destroy_args * args)407 eigrpd_instance_metric_weights_K2_destroy(struct nb_cb_destroy_args *args)
408 {
409 	struct eigrp *eigrp;
410 
411 	switch (args->event) {
412 	case NB_EV_VALIDATE:
413 	case NB_EV_PREPARE:
414 	case NB_EV_ABORT:
415 		/* NOTHING */
416 		break;
417 	case NB_EV_APPLY:
418 		eigrp = nb_running_get_entry(args->dnode, NULL, true);
419 		eigrp->k_values[1] = EIGRP_K2_DEFAULT;
420 		break;
421 	}
422 
423 	return NB_OK;
424 }
425 
426 /*
427  * XPath: /frr-eigrpd:eigrpd/instance/metric-weights/K3
428  */
429 static int
eigrpd_instance_metric_weights_K3_modify(struct nb_cb_modify_args * args)430 eigrpd_instance_metric_weights_K3_modify(struct nb_cb_modify_args *args)
431 {
432 	struct eigrp *eigrp;
433 
434 	switch (args->event) {
435 	case NB_EV_VALIDATE:
436 	case NB_EV_PREPARE:
437 	case NB_EV_ABORT:
438 		/* NOTHING */
439 		break;
440 	case NB_EV_APPLY:
441 		eigrp = nb_running_get_entry(args->dnode, NULL, true);
442 		eigrp->k_values[2] = yang_dnode_get_uint8(args->dnode, NULL);
443 		break;
444 	}
445 
446 	return NB_OK;
447 }
448 
449 static int
eigrpd_instance_metric_weights_K3_destroy(struct nb_cb_destroy_args * args)450 eigrpd_instance_metric_weights_K3_destroy(struct nb_cb_destroy_args *args)
451 {
452 	struct eigrp *eigrp;
453 
454 	switch (args->event) {
455 	case NB_EV_VALIDATE:
456 	case NB_EV_PREPARE:
457 	case NB_EV_ABORT:
458 		/* NOTHING */
459 		break;
460 	case NB_EV_APPLY:
461 		eigrp = nb_running_get_entry(args->dnode, NULL, true);
462 		eigrp->k_values[2] = EIGRP_K3_DEFAULT;
463 		break;
464 	}
465 
466 	return NB_OK;
467 }
468 
469 /*
470  * XPath: /frr-eigrpd:eigrpd/instance/metric-weights/K4
471  */
472 static int
eigrpd_instance_metric_weights_K4_modify(struct nb_cb_modify_args * args)473 eigrpd_instance_metric_weights_K4_modify(struct nb_cb_modify_args *args)
474 {
475 	struct eigrp *eigrp;
476 
477 	switch (args->event) {
478 	case NB_EV_VALIDATE:
479 	case NB_EV_PREPARE:
480 	case NB_EV_ABORT:
481 		/* NOTHING */
482 		break;
483 	case NB_EV_APPLY:
484 		eigrp = nb_running_get_entry(args->dnode, NULL, true);
485 		eigrp->k_values[3] = yang_dnode_get_uint8(args->dnode, NULL);
486 		break;
487 	}
488 
489 	return NB_OK;
490 }
491 
492 static int
eigrpd_instance_metric_weights_K4_destroy(struct nb_cb_destroy_args * args)493 eigrpd_instance_metric_weights_K4_destroy(struct nb_cb_destroy_args *args)
494 {
495 	struct eigrp *eigrp;
496 
497 	switch (args->event) {
498 	case NB_EV_VALIDATE:
499 	case NB_EV_PREPARE:
500 	case NB_EV_ABORT:
501 		/* NOTHING */
502 		break;
503 	case NB_EV_APPLY:
504 		eigrp = nb_running_get_entry(args->dnode, NULL, true);
505 		eigrp->k_values[3] = EIGRP_K4_DEFAULT;
506 		break;
507 	}
508 
509 	return NB_OK;
510 }
511 
512 /*
513  * XPath: /frr-eigrpd:eigrpd/instance/metric-weights/K5
514  */
515 static int
eigrpd_instance_metric_weights_K5_modify(struct nb_cb_modify_args * args)516 eigrpd_instance_metric_weights_K5_modify(struct nb_cb_modify_args *args)
517 {
518 	struct eigrp *eigrp;
519 
520 	switch (args->event) {
521 	case NB_EV_VALIDATE:
522 	case NB_EV_PREPARE:
523 	case NB_EV_ABORT:
524 		/* NOTHING */
525 		break;
526 	case NB_EV_APPLY:
527 		eigrp = nb_running_get_entry(args->dnode, NULL, true);
528 		eigrp->k_values[4] = yang_dnode_get_uint8(args->dnode, NULL);
529 		break;
530 	}
531 
532 	return NB_OK;
533 }
534 
535 static int
eigrpd_instance_metric_weights_K5_destroy(struct nb_cb_destroy_args * args)536 eigrpd_instance_metric_weights_K5_destroy(struct nb_cb_destroy_args *args)
537 {
538 	struct eigrp *eigrp;
539 
540 	switch (args->event) {
541 	case NB_EV_VALIDATE:
542 	case NB_EV_PREPARE:
543 	case NB_EV_ABORT:
544 		/* NOTHING */
545 		break;
546 	case NB_EV_APPLY:
547 		eigrp = nb_running_get_entry(args->dnode, NULL, true);
548 		eigrp->k_values[4] = EIGRP_K5_DEFAULT;
549 		break;
550 	}
551 
552 	return NB_OK;
553 }
554 
555 /*
556  * XPath: /frr-eigrpd:eigrpd/instance/metric-weights/K6
557  */
558 static int
eigrpd_instance_metric_weights_K6_modify(struct nb_cb_modify_args * args)559 eigrpd_instance_metric_weights_K6_modify(struct nb_cb_modify_args *args)
560 {
561 	struct eigrp *eigrp;
562 
563 	switch (args->event) {
564 	case NB_EV_VALIDATE:
565 	case NB_EV_PREPARE:
566 	case NB_EV_ABORT:
567 		/* NOTHING */
568 		break;
569 	case NB_EV_APPLY:
570 		eigrp = nb_running_get_entry(args->dnode, NULL, true);
571 		eigrp->k_values[5] = yang_dnode_get_uint8(args->dnode, NULL);
572 		break;
573 	}
574 
575 	return NB_OK;
576 }
577 
578 static int
eigrpd_instance_metric_weights_K6_destroy(struct nb_cb_destroy_args * args)579 eigrpd_instance_metric_weights_K6_destroy(struct nb_cb_destroy_args *args)
580 {
581 	struct eigrp *eigrp;
582 
583 	switch (args->event) {
584 	case NB_EV_VALIDATE:
585 	case NB_EV_PREPARE:
586 	case NB_EV_ABORT:
587 		/* NOTHING */
588 		break;
589 	case NB_EV_APPLY:
590 		eigrp = nb_running_get_entry(args->dnode, NULL, true);
591 		eigrp->k_values[5] = EIGRP_K6_DEFAULT;
592 		break;
593 	}
594 
595 	return NB_OK;
596 }
597 
598 /*
599  * XPath: /frr-eigrpd:eigrpd/instance/network
600  */
eigrpd_instance_network_create(struct nb_cb_create_args * args)601 static int eigrpd_instance_network_create(struct nb_cb_create_args *args)
602 {
603 	struct route_node *rnode;
604 	struct prefix prefix;
605 	struct eigrp *eigrp;
606 	int exists;
607 
608 	yang_dnode_get_ipv4p(&prefix, args->dnode, NULL);
609 
610 	switch (args->event) {
611 	case NB_EV_VALIDATE:
612 		eigrp = nb_running_get_entry(args->dnode, NULL, false);
613 		/* If entry doesn't exist it means the list is empty. */
614 		if (eigrp == NULL)
615 			break;
616 
617 		rnode = route_node_get(eigrp->networks, &prefix);
618 		exists = (rnode->info != NULL);
619 		route_unlock_node(rnode);
620 		if (exists)
621 			return NB_ERR_INCONSISTENCY;
622 		break;
623 	case NB_EV_PREPARE:
624 	case NB_EV_ABORT:
625 		/* NOTHING */
626 		break;
627 	case NB_EV_APPLY:
628 		eigrp = nb_running_get_entry(args->dnode, NULL, true);
629 		if (eigrp_network_set(eigrp, &prefix) == 0)
630 			return NB_ERR_INCONSISTENCY;
631 		break;
632 	}
633 
634 	return NB_OK;
635 }
636 
eigrpd_instance_network_destroy(struct nb_cb_destroy_args * args)637 static int eigrpd_instance_network_destroy(struct nb_cb_destroy_args *args)
638 {
639 	struct route_node *rnode;
640 	struct prefix prefix;
641 	struct eigrp *eigrp;
642 	int exists = 0;
643 
644 	yang_dnode_get_ipv4p(&prefix, args->dnode, NULL);
645 
646 	switch (args->event) {
647 	case NB_EV_VALIDATE:
648 		eigrp = nb_running_get_entry(args->dnode, NULL, false);
649 		/* If entry doesn't exist it means the list is empty. */
650 		if (eigrp == NULL)
651 			break;
652 
653 		rnode = route_node_get(eigrp->networks, &prefix);
654 		exists = (rnode->info != NULL);
655 		route_unlock_node(rnode);
656 		if (exists == 0)
657 			return NB_ERR_INCONSISTENCY;
658 		break;
659 	case NB_EV_PREPARE:
660 	case NB_EV_ABORT:
661 		/* NOTHING */
662 		break;
663 	case NB_EV_APPLY:
664 		eigrp = nb_running_get_entry(args->dnode, NULL, true);
665 		eigrp_network_unset(eigrp, &prefix);
666 		break;
667 	}
668 
669 	return NB_OK;
670 }
671 
672 /*
673  * XPath: /frr-eigrpd:eigrpd/instance/neighbor
674  */
eigrpd_instance_neighbor_create(struct nb_cb_create_args * args)675 static int eigrpd_instance_neighbor_create(struct nb_cb_create_args *args)
676 {
677 	switch (args->event) {
678 	case NB_EV_VALIDATE:
679 		/* TODO: Not implemented. */
680 		return NB_ERR_INCONSISTENCY;
681 	case NB_EV_PREPARE:
682 	case NB_EV_ABORT:
683 	case NB_EV_APPLY:
684 		/* NOTHING */
685 		break;
686 	}
687 
688 	return NB_OK;
689 }
690 
eigrpd_instance_neighbor_destroy(struct nb_cb_destroy_args * args)691 static int eigrpd_instance_neighbor_destroy(struct nb_cb_destroy_args *args)
692 {
693 	switch (args->event) {
694 	case NB_EV_VALIDATE:
695 		/* TODO: Not implemented. */
696 		return NB_ERR_INCONSISTENCY;
697 	case NB_EV_PREPARE:
698 	case NB_EV_ABORT:
699 	case NB_EV_APPLY:
700 		/* NOTHING */
701 		break;
702 	}
703 
704 	return NB_OK;
705 }
706 
707 /*
708  * XPath: /frr-eigrpd:eigrpd/instance/redistribute
709  */
eigrpd_instance_redistribute_create(struct nb_cb_create_args * args)710 static int eigrpd_instance_redistribute_create(struct nb_cb_create_args *args)
711 {
712 	struct eigrp_metrics metrics;
713 	const char *vrfname;
714 	struct eigrp *eigrp;
715 	uint32_t proto;
716 	vrf_id_t vrfid;
717 
718 	switch (args->event) {
719 	case NB_EV_VALIDATE:
720 		proto = yang_dnode_get_enum(args->dnode, "./protocol");
721 		vrfname = yang_dnode_get_string(args->dnode, "../vrf");
722 		vrfid = vrf_name_to_id(vrfname);
723 		if (vrf_bitmap_check(zclient->redist[AFI_IP][proto], vrfid))
724 			return NB_ERR_INCONSISTENCY;
725 		break;
726 	case NB_EV_PREPARE:
727 	case NB_EV_ABORT:
728 		/* NOTHING */
729 		break;
730 	case NB_EV_APPLY:
731 		eigrp = nb_running_get_entry(args->dnode, NULL, true);
732 		proto = yang_dnode_get_enum(args->dnode, "./protocol");
733 		redistribute_get_metrics(args->dnode, &metrics);
734 		eigrp_redistribute_set(eigrp, proto, metrics);
735 		break;
736 	}
737 
738 	return NB_OK;
739 }
740 
eigrpd_instance_redistribute_destroy(struct nb_cb_destroy_args * args)741 static int eigrpd_instance_redistribute_destroy(struct nb_cb_destroy_args *args)
742 {
743 	struct eigrp *eigrp;
744 	uint32_t proto;
745 
746 	switch (args->event) {
747 	case NB_EV_VALIDATE:
748 	case NB_EV_PREPARE:
749 	case NB_EV_ABORT:
750 		/* NOTHING */
751 		break;
752 	case NB_EV_APPLY:
753 		eigrp = nb_running_get_entry(args->dnode, NULL, true);
754 		proto = yang_dnode_get_enum(args->dnode, "./protocol");
755 		eigrp_redistribute_unset(eigrp, proto);
756 		break;
757 	}
758 
759 	return NB_OK;
760 }
761 
762 /*
763  * XPath: /frr-eigrpd:eigrpd/instance/redistribute/route-map
764  */
765 static int
eigrpd_instance_redistribute_route_map_modify(struct nb_cb_modify_args * args)766 eigrpd_instance_redistribute_route_map_modify(struct nb_cb_modify_args *args)
767 {
768 	switch (args->event) {
769 	case NB_EV_VALIDATE:
770 		/* TODO: Not implemented. */
771 		return NB_ERR_INCONSISTENCY;
772 	case NB_EV_PREPARE:
773 	case NB_EV_ABORT:
774 	case NB_EV_APPLY:
775 		/* NOTHING */
776 		break;
777 	}
778 
779 	return NB_OK;
780 }
781 
782 static int
eigrpd_instance_redistribute_route_map_destroy(struct nb_cb_destroy_args * args)783 eigrpd_instance_redistribute_route_map_destroy(struct nb_cb_destroy_args *args)
784 {
785 	switch (args->event) {
786 	case NB_EV_VALIDATE:
787 		/* TODO: Not implemented. */
788 		return NB_ERR_INCONSISTENCY;
789 	case NB_EV_PREPARE:
790 	case NB_EV_ABORT:
791 	case NB_EV_APPLY:
792 		/* NOTHING */
793 		break;
794 	}
795 
796 	return NB_OK;
797 }
798 
799 /*
800  * XPath: /frr-eigrpd:eigrpd/instance/redistribute/metrics/bandwidth
801  */
eigrpd_instance_redistribute_metrics_bandwidth_modify(struct nb_cb_modify_args * args)802 static int eigrpd_instance_redistribute_metrics_bandwidth_modify(
803 	struct nb_cb_modify_args *args)
804 {
805 	struct eigrp_metrics metrics;
806 	struct eigrp *eigrp;
807 	uint32_t proto;
808 
809 	switch (args->event) {
810 	case NB_EV_VALIDATE:
811 	case NB_EV_PREPARE:
812 	case NB_EV_ABORT:
813 		/* NOTHING */
814 		break;
815 	case NB_EV_APPLY:
816 		eigrp = nb_running_get_entry(args->dnode, NULL, true);
817 		proto = yang_dnode_get_enum(args->dnode, "../../protocol");
818 		redistribute_get_metrics(args->dnode, &metrics);
819 		eigrp_redistribute_set(eigrp, proto, metrics);
820 		break;
821 	}
822 
823 	return NB_OK;
824 }
825 
eigrpd_instance_redistribute_metrics_bandwidth_destroy(struct nb_cb_destroy_args * args)826 static int eigrpd_instance_redistribute_metrics_bandwidth_destroy(
827 	struct nb_cb_destroy_args *args)
828 {
829 	struct eigrp_metrics metrics;
830 	struct eigrp *eigrp;
831 	uint32_t proto;
832 
833 	switch (args->event) {
834 	case NB_EV_VALIDATE:
835 	case NB_EV_PREPARE:
836 	case NB_EV_ABORT:
837 		/* NOTHING */
838 		break;
839 	case NB_EV_APPLY:
840 		eigrp = nb_running_get_entry(args->dnode, NULL, true);
841 		proto = yang_dnode_get_enum(args->dnode, "../../protocol");
842 		redistribute_get_metrics(args->dnode, &metrics);
843 		eigrp_redistribute_set(eigrp, proto, metrics);
844 		break;
845 	}
846 
847 	return NB_OK;
848 }
849 
850 /*
851  * XPath: /frr-eigrpd:eigrpd/instance/redistribute/metrics/delay
852  */
eigrpd_instance_redistribute_metrics_delay_modify(struct nb_cb_modify_args * args)853 static int eigrpd_instance_redistribute_metrics_delay_modify(
854 	struct nb_cb_modify_args *args)
855 {
856 	return eigrpd_instance_redistribute_metrics_bandwidth_modify(args);
857 }
858 
eigrpd_instance_redistribute_metrics_delay_destroy(struct nb_cb_destroy_args * args)859 static int eigrpd_instance_redistribute_metrics_delay_destroy(
860 	struct nb_cb_destroy_args *args)
861 {
862 	return eigrpd_instance_redistribute_metrics_bandwidth_destroy(args);
863 }
864 
865 /*
866  * XPath: /frr-eigrpd:eigrpd/instance/redistribute/metrics/reliability
867  */
eigrpd_instance_redistribute_metrics_reliability_modify(struct nb_cb_modify_args * args)868 static int eigrpd_instance_redistribute_metrics_reliability_modify(
869 	struct nb_cb_modify_args *args)
870 {
871 	return eigrpd_instance_redistribute_metrics_bandwidth_modify(args);
872 }
873 
eigrpd_instance_redistribute_metrics_reliability_destroy(struct nb_cb_destroy_args * args)874 static int eigrpd_instance_redistribute_metrics_reliability_destroy(
875 	struct nb_cb_destroy_args *args)
876 {
877 	return eigrpd_instance_redistribute_metrics_bandwidth_destroy(args);
878 }
879 
880 /*
881  * XPath: /frr-eigrpd:eigrpd/instance/redistribute/metrics/load
882  */
883 static int
eigrpd_instance_redistribute_metrics_load_modify(struct nb_cb_modify_args * args)884 eigrpd_instance_redistribute_metrics_load_modify(struct nb_cb_modify_args *args)
885 {
886 	return eigrpd_instance_redistribute_metrics_bandwidth_modify(args);
887 }
888 
eigrpd_instance_redistribute_metrics_load_destroy(struct nb_cb_destroy_args * args)889 static int eigrpd_instance_redistribute_metrics_load_destroy(
890 	struct nb_cb_destroy_args *args)
891 {
892 	return eigrpd_instance_redistribute_metrics_bandwidth_destroy(args);
893 }
894 
895 /*
896  * XPath: /frr-eigrpd:eigrpd/instance/redistribute/metrics/mtu
897  */
898 static int
eigrpd_instance_redistribute_metrics_mtu_modify(struct nb_cb_modify_args * args)899 eigrpd_instance_redistribute_metrics_mtu_modify(struct nb_cb_modify_args *args)
900 {
901 	return eigrpd_instance_redistribute_metrics_bandwidth_modify(args);
902 }
903 
eigrpd_instance_redistribute_metrics_mtu_destroy(struct nb_cb_destroy_args * args)904 static int eigrpd_instance_redistribute_metrics_mtu_destroy(
905 	struct nb_cb_destroy_args *args)
906 {
907 	return eigrpd_instance_redistribute_metrics_bandwidth_destroy(args);
908 }
909 
910 /*
911  * XPath: /frr-interface:lib/interface/frr-eigrpd:eigrp/delay
912  */
lib_interface_eigrp_delay_modify(struct nb_cb_modify_args * args)913 static int lib_interface_eigrp_delay_modify(struct nb_cb_modify_args *args)
914 {
915 	struct eigrp_interface *ei;
916 	struct interface *ifp;
917 
918 	switch (args->event) {
919 	case NB_EV_VALIDATE:
920 		ifp = nb_running_get_entry(args->dnode, NULL, false);
921 		if (ifp == NULL) {
922 			/*
923 			 * XXX: we can't verify if the interface exists
924 			 * and is active until EIGRP is up.
925 			 */
926 			break;
927 		}
928 
929 		ei = ifp->info;
930 		if (ei == NULL)
931 			return NB_ERR_INCONSISTENCY;
932 		break;
933 	case NB_EV_PREPARE:
934 	case NB_EV_ABORT:
935 		/* NOTHING */
936 		break;
937 	case NB_EV_APPLY:
938 		ifp = nb_running_get_entry(args->dnode, NULL, true);
939 		ei = ifp->info;
940 		if (ei == NULL)
941 			return NB_ERR_INCONSISTENCY;
942 
943 		ei->params.delay = yang_dnode_get_uint32(args->dnode, NULL);
944 		eigrp_if_reset(ifp);
945 		break;
946 	}
947 
948 	return NB_OK;
949 }
950 
951 /*
952  * XPath: /frr-interface:lib/interface/frr-eigrpd:eigrp/bandwidth
953  */
lib_interface_eigrp_bandwidth_modify(struct nb_cb_modify_args * args)954 static int lib_interface_eigrp_bandwidth_modify(struct nb_cb_modify_args *args)
955 {
956 	struct interface *ifp;
957 	struct eigrp_interface *ei;
958 
959 	switch (args->event) {
960 	case NB_EV_VALIDATE:
961 		ifp = nb_running_get_entry(args->dnode, NULL, false);
962 		if (ifp == NULL) {
963 			/*
964 			 * XXX: we can't verify if the interface exists
965 			 * and is active until EIGRP is up.
966 			 */
967 			break;
968 		}
969 
970 		ei = ifp->info;
971 		if (ei == NULL)
972 			return NB_ERR_INCONSISTENCY;
973 		break;
974 	case NB_EV_PREPARE:
975 	case NB_EV_ABORT:
976 		/* NOTHING */
977 		break;
978 	case NB_EV_APPLY:
979 		ifp = nb_running_get_entry(args->dnode, NULL, true);
980 		ei = ifp->info;
981 		if (ei == NULL)
982 			return NB_ERR_INCONSISTENCY;
983 
984 		ei->params.bandwidth = yang_dnode_get_uint32(args->dnode, NULL);
985 		eigrp_if_reset(ifp);
986 		break;
987 	}
988 
989 	return NB_OK;
990 }
991 
992 /*
993  * XPath: /frr-interface:lib/interface/frr-eigrpd:eigrp/hello-interval
994  */
995 static int
lib_interface_eigrp_hello_interval_modify(struct nb_cb_modify_args * args)996 lib_interface_eigrp_hello_interval_modify(struct nb_cb_modify_args *args)
997 {
998 	struct interface *ifp;
999 	struct eigrp_interface *ei;
1000 
1001 	switch (args->event) {
1002 	case NB_EV_VALIDATE:
1003 		ifp = nb_running_get_entry(args->dnode, NULL, false);
1004 		if (ifp == NULL) {
1005 			/*
1006 			 * XXX: we can't verify if the interface exists
1007 			 * and is active until EIGRP is up.
1008 			 */
1009 			break;
1010 		}
1011 
1012 		ei = ifp->info;
1013 		if (ei == NULL)
1014 			return NB_ERR_INCONSISTENCY;
1015 		break;
1016 	case NB_EV_PREPARE:
1017 	case NB_EV_ABORT:
1018 		/* NOTHING */
1019 		break;
1020 	case NB_EV_APPLY:
1021 		ifp = nb_running_get_entry(args->dnode, NULL, true);
1022 		ei = ifp->info;
1023 		if (ei == NULL)
1024 			return NB_ERR_INCONSISTENCY;
1025 
1026 		ei->params.v_hello = yang_dnode_get_uint16(args->dnode, NULL);
1027 		break;
1028 	}
1029 
1030 	return NB_OK;
1031 }
1032 
1033 /*
1034  * XPath: /frr-interface:lib/interface/frr-eigrpd:eigrp/hold-time
1035  */
lib_interface_eigrp_hold_time_modify(struct nb_cb_modify_args * args)1036 static int lib_interface_eigrp_hold_time_modify(struct nb_cb_modify_args *args)
1037 {
1038 	struct interface *ifp;
1039 	struct eigrp_interface *ei;
1040 
1041 	switch (args->event) {
1042 	case NB_EV_VALIDATE:
1043 		ifp = nb_running_get_entry(args->dnode, NULL, false);
1044 		if (ifp == NULL) {
1045 			/*
1046 			 * XXX: we can't verify if the interface exists
1047 			 * and is active until EIGRP is up.
1048 			 */
1049 			break;
1050 		}
1051 
1052 		ei = ifp->info;
1053 		if (ei == NULL)
1054 			return NB_ERR_INCONSISTENCY;
1055 		break;
1056 	case NB_EV_PREPARE:
1057 	case NB_EV_ABORT:
1058 		/* NOTHING */
1059 		break;
1060 	case NB_EV_APPLY:
1061 		ifp = nb_running_get_entry(args->dnode, NULL, true);
1062 		ei = ifp->info;
1063 		if (ei == NULL)
1064 			return NB_ERR_INCONSISTENCY;
1065 
1066 		ei->params.v_wait = yang_dnode_get_uint16(args->dnode, NULL);
1067 		break;
1068 	}
1069 
1070 	return NB_OK;
1071 }
1072 
1073 /*
1074  * XPath: /frr-interface:lib/interface/frr-eigrpd:eigrp/split-horizon
1075  */
1076 static int
lib_interface_eigrp_split_horizon_modify(struct nb_cb_modify_args * args)1077 lib_interface_eigrp_split_horizon_modify(struct nb_cb_modify_args *args)
1078 {
1079 	switch (args->event) {
1080 	case NB_EV_VALIDATE:
1081 		/* TODO: Not implemented. */
1082 		return NB_ERR_INCONSISTENCY;
1083 	case NB_EV_PREPARE:
1084 	case NB_EV_ABORT:
1085 	case NB_EV_APPLY:
1086 		/* NOTHING */
1087 		break;
1088 	}
1089 
1090 	return NB_OK;
1091 }
1092 
1093 /*
1094  * XPath: /frr-interface:lib/interface/frr-eigrpd:eigrp/instance
1095  */
lib_interface_eigrp_instance_create(struct nb_cb_create_args * args)1096 static int lib_interface_eigrp_instance_create(struct nb_cb_create_args *args)
1097 {
1098 	struct eigrp_interface *eif;
1099 	struct interface *ifp;
1100 	struct eigrp *eigrp;
1101 
1102 	switch (args->event) {
1103 	case NB_EV_VALIDATE:
1104 		ifp = nb_running_get_entry(args->dnode, NULL, false);
1105 		if (ifp == NULL) {
1106 			/*
1107 			 * XXX: we can't verify if the interface exists
1108 			 * and is active until EIGRP is up.
1109 			 */
1110 			break;
1111 		}
1112 
1113 		eigrp = eigrp_get(yang_dnode_get_uint16(args->dnode, "./asn"),
1114 				  ifp->vrf_id);
1115 		eif = eigrp_interface_lookup(eigrp, ifp->name);
1116 		if (eif == NULL)
1117 			return NB_ERR_INCONSISTENCY;
1118 		break;
1119 	case NB_EV_PREPARE:
1120 	case NB_EV_ABORT:
1121 		/* NOTHING */
1122 		break;
1123 	case NB_EV_APPLY:
1124 		ifp = nb_running_get_entry(args->dnode, NULL, true);
1125 		eigrp = eigrp_get(yang_dnode_get_uint16(args->dnode, "./asn"),
1126 				  ifp->vrf_id);
1127 		eif = eigrp_interface_lookup(eigrp, ifp->name);
1128 		if (eif == NULL)
1129 			return NB_ERR_INCONSISTENCY;
1130 
1131 		nb_running_set_entry(args->dnode, eif);
1132 		break;
1133 	}
1134 
1135 	return NB_OK;
1136 }
1137 
lib_interface_eigrp_instance_destroy(struct nb_cb_destroy_args * args)1138 static int lib_interface_eigrp_instance_destroy(struct nb_cb_destroy_args *args)
1139 {
1140 	switch (args->event) {
1141 	case NB_EV_VALIDATE:
1142 	case NB_EV_PREPARE:
1143 	case NB_EV_ABORT:
1144 		/* NOTHING */
1145 		break;
1146 	case NB_EV_APPLY:
1147 		nb_running_unset_entry(args->dnode);
1148 		break;
1149 	}
1150 
1151 	return NB_OK;
1152 }
1153 
1154 /*
1155  * XPath:
1156  * /frr-interface:lib/interface/frr-eigrpd:eigrp/instance/summarize-addresses
1157  */
lib_interface_eigrp_instance_summarize_addresses_create(struct nb_cb_create_args * args)1158 static int lib_interface_eigrp_instance_summarize_addresses_create(
1159 	struct nb_cb_create_args *args)
1160 {
1161 	switch (args->event) {
1162 	case NB_EV_VALIDATE:
1163 		/* TODO: Not implemented. */
1164 		return NB_ERR_INCONSISTENCY;
1165 	case NB_EV_PREPARE:
1166 	case NB_EV_ABORT:
1167 	case NB_EV_APPLY:
1168 		/* NOTHING */
1169 		break;
1170 	}
1171 
1172 	return NB_OK;
1173 }
1174 
lib_interface_eigrp_instance_summarize_addresses_destroy(struct nb_cb_destroy_args * args)1175 static int lib_interface_eigrp_instance_summarize_addresses_destroy(
1176 	struct nb_cb_destroy_args *args)
1177 {
1178 	switch (args->event) {
1179 	case NB_EV_VALIDATE:
1180 		/* TODO: Not implemented. */
1181 		return NB_ERR_INCONSISTENCY;
1182 	case NB_EV_PREPARE:
1183 	case NB_EV_ABORT:
1184 	case NB_EV_APPLY:
1185 		/* NOTHING */
1186 		break;
1187 	}
1188 
1189 	return NB_OK;
1190 }
1191 
1192 /*
1193  * XPath: /frr-interface:lib/interface/frr-eigrpd:eigrp/instance/authentication
1194  */
lib_interface_eigrp_instance_authentication_modify(struct nb_cb_modify_args * args)1195 static int lib_interface_eigrp_instance_authentication_modify(
1196 	struct nb_cb_modify_args *args)
1197 {
1198 	struct eigrp_interface *eif;
1199 
1200 	switch (args->event) {
1201 	case NB_EV_VALIDATE:
1202 	case NB_EV_PREPARE:
1203 	case NB_EV_ABORT:
1204 		/* NOTHING */
1205 		break;
1206 	case NB_EV_APPLY:
1207 		eif = nb_running_get_entry(args->dnode, NULL, true);
1208 		eif->params.auth_type = yang_dnode_get_enum(args->dnode, NULL);
1209 		break;
1210 	}
1211 
1212 	return NB_OK;
1213 }
1214 
1215 /*
1216  * XPath: /frr-interface:lib/interface/frr-eigrpd:eigrp/instance/keychain
1217  */
1218 static int
lib_interface_eigrp_instance_keychain_modify(struct nb_cb_modify_args * args)1219 lib_interface_eigrp_instance_keychain_modify(struct nb_cb_modify_args *args)
1220 {
1221 	struct eigrp_interface *eif;
1222 	struct keychain *keychain;
1223 
1224 	switch (args->event) {
1225 	case NB_EV_VALIDATE:
1226 		keychain = keychain_lookup(
1227 			yang_dnode_get_string(args->dnode, NULL));
1228 		if (keychain == NULL)
1229 			return NB_ERR_INCONSISTENCY;
1230 		break;
1231 	case NB_EV_PREPARE:
1232 		args->resource->ptr =
1233 			strdup(yang_dnode_get_string(args->dnode, NULL));
1234 		if (args->resource->ptr == NULL)
1235 			return NB_ERR_RESOURCE;
1236 		break;
1237 	case NB_EV_ABORT:
1238 		free(args->resource->ptr);
1239 		args->resource->ptr = NULL;
1240 		break;
1241 	case NB_EV_APPLY:
1242 		eif = nb_running_get_entry(args->dnode, NULL, true);
1243 		if (eif->params.auth_keychain)
1244 			free(eif->params.auth_keychain);
1245 
1246 		eif->params.auth_keychain = args->resource->ptr;
1247 		break;
1248 	}
1249 
1250 	return NB_OK;
1251 }
1252 
1253 static int
lib_interface_eigrp_instance_keychain_destroy(struct nb_cb_destroy_args * args)1254 lib_interface_eigrp_instance_keychain_destroy(struct nb_cb_destroy_args *args)
1255 {
1256 	struct eigrp_interface *eif;
1257 
1258 	switch (args->event) {
1259 	case NB_EV_VALIDATE:
1260 	case NB_EV_PREPARE:
1261 	case NB_EV_ABORT:
1262 		/* NOTHING */
1263 		break;
1264 	case NB_EV_APPLY:
1265 		eif = nb_running_get_entry(args->dnode, NULL, true);
1266 		if (eif->params.auth_keychain)
1267 			free(eif->params.auth_keychain);
1268 
1269 		eif->params.auth_keychain = NULL;
1270 		break;
1271 	}
1272 
1273 	return NB_OK;
1274 }
1275 
1276 /* clang-format off */
1277 const struct frr_yang_module_info frr_eigrpd_info = {
1278 	.name = "frr-eigrpd",
1279 	.nodes = {
1280 		{
1281 			.xpath = "/frr-eigrpd:eigrpd/instance",
1282 			.cbs = {
1283 				.create = eigrpd_instance_create,
1284 				.destroy = eigrpd_instance_destroy,
1285 				.cli_show = eigrp_cli_show_header,
1286 				.cli_show_end = eigrp_cli_show_end_header,
1287 			}
1288 		},
1289 		{
1290 			.xpath = "/frr-eigrpd:eigrpd/instance/router-id",
1291 			.cbs = {
1292 				.modify = eigrpd_instance_router_id_modify,
1293 				.destroy = eigrpd_instance_router_id_destroy,
1294 				.cli_show = eigrp_cli_show_router_id,
1295 			}
1296 		},
1297 		{
1298 			.xpath = "/frr-eigrpd:eigrpd/instance/passive-interface",
1299 			.cbs = {
1300 				.create = eigrpd_instance_passive_interface_create,
1301 				.destroy = eigrpd_instance_passive_interface_destroy,
1302 				.cli_show = eigrp_cli_show_passive_interface,
1303 			}
1304 		},
1305 		{
1306 			.xpath = "/frr-eigrpd:eigrpd/instance/active-time",
1307 			.cbs = {
1308 				.modify = eigrpd_instance_active_time_modify,
1309 				.cli_show = eigrp_cli_show_active_time,
1310 			}
1311 		},
1312 		{
1313 			.xpath = "/frr-eigrpd:eigrpd/instance/variance",
1314 			.cbs = {
1315 				.modify = eigrpd_instance_variance_modify,
1316 				.destroy = eigrpd_instance_variance_destroy,
1317 				.cli_show = eigrp_cli_show_variance,
1318 			}
1319 		},
1320 		{
1321 			.xpath = "/frr-eigrpd:eigrpd/instance/maximum-paths",
1322 			.cbs = {
1323 				.modify = eigrpd_instance_maximum_paths_modify,
1324 				.destroy = eigrpd_instance_maximum_paths_destroy,
1325 				.cli_show = eigrp_cli_show_maximum_paths,
1326 			}
1327 		},
1328 		{
1329 			.xpath = "/frr-eigrpd:eigrpd/instance/metric-weights",
1330 			.cbs = {
1331 				.cli_show = eigrp_cli_show_metrics,
1332 			}
1333 		},
1334 		{
1335 			.xpath = "/frr-eigrpd:eigrpd/instance/metric-weights/K1",
1336 			.cbs = {
1337 				.modify = eigrpd_instance_metric_weights_K1_modify,
1338 				.destroy = eigrpd_instance_metric_weights_K1_destroy,
1339 			}
1340 		},
1341 		{
1342 			.xpath = "/frr-eigrpd:eigrpd/instance/metric-weights/K2",
1343 			.cbs = {
1344 				.modify = eigrpd_instance_metric_weights_K2_modify,
1345 				.destroy = eigrpd_instance_metric_weights_K2_destroy,
1346 			}
1347 		},
1348 		{
1349 			.xpath = "/frr-eigrpd:eigrpd/instance/metric-weights/K3",
1350 			.cbs = {
1351 				.modify = eigrpd_instance_metric_weights_K3_modify,
1352 				.destroy = eigrpd_instance_metric_weights_K3_destroy,
1353 			}
1354 		},
1355 		{
1356 			.xpath = "/frr-eigrpd:eigrpd/instance/metric-weights/K4",
1357 			.cbs = {
1358 				.modify = eigrpd_instance_metric_weights_K4_modify,
1359 				.destroy = eigrpd_instance_metric_weights_K4_destroy,
1360 			}
1361 		},
1362 		{
1363 			.xpath = "/frr-eigrpd:eigrpd/instance/metric-weights/K5",
1364 			.cbs = {
1365 				.modify = eigrpd_instance_metric_weights_K5_modify,
1366 				.destroy = eigrpd_instance_metric_weights_K5_destroy,
1367 			}
1368 		},
1369 		{
1370 			.xpath = "/frr-eigrpd:eigrpd/instance/metric-weights/K6",
1371 			.cbs = {
1372 				.modify = eigrpd_instance_metric_weights_K6_modify,
1373 				.destroy = eigrpd_instance_metric_weights_K6_destroy,
1374 			}
1375 		},
1376 		{
1377 			.xpath = "/frr-eigrpd:eigrpd/instance/network",
1378 			.cbs = {
1379 				.create = eigrpd_instance_network_create,
1380 				.destroy = eigrpd_instance_network_destroy,
1381 				.cli_show = eigrp_cli_show_network,
1382 			}
1383 		},
1384 		{
1385 			.xpath = "/frr-eigrpd:eigrpd/instance/neighbor",
1386 			.cbs = {
1387 				.create = eigrpd_instance_neighbor_create,
1388 				.destroy = eigrpd_instance_neighbor_destroy,
1389 				.cli_show = eigrp_cli_show_neighbor,
1390 			}
1391 		},
1392 		{
1393 			.xpath = "/frr-eigrpd:eigrpd/instance/redistribute",
1394 			.cbs = {
1395 				.create = eigrpd_instance_redistribute_create,
1396 				.destroy = eigrpd_instance_redistribute_destroy,
1397 				.cli_show = eigrp_cli_show_redistribute,
1398 			}
1399 		},
1400 		{
1401 			.xpath = "/frr-eigrpd:eigrpd/instance/redistribute/route-map",
1402 			.cbs = {
1403 				.modify = eigrpd_instance_redistribute_route_map_modify,
1404 				.destroy = eigrpd_instance_redistribute_route_map_destroy,
1405 			}
1406 		},
1407 		{
1408 			.xpath = "/frr-eigrpd:eigrpd/instance/redistribute/metrics/bandwidth",
1409 			.cbs = {
1410 				.modify = eigrpd_instance_redistribute_metrics_bandwidth_modify,
1411 				.destroy = eigrpd_instance_redistribute_metrics_bandwidth_destroy,
1412 			}
1413 		},
1414 		{
1415 			.xpath = "/frr-eigrpd:eigrpd/instance/redistribute/metrics/delay",
1416 			.cbs = {
1417 				.modify = eigrpd_instance_redistribute_metrics_delay_modify,
1418 				.destroy = eigrpd_instance_redistribute_metrics_delay_destroy,
1419 			}
1420 		},
1421 		{
1422 			.xpath = "/frr-eigrpd:eigrpd/instance/redistribute/metrics/reliability",
1423 			.cbs = {
1424 				.modify = eigrpd_instance_redistribute_metrics_reliability_modify,
1425 				.destroy = eigrpd_instance_redistribute_metrics_reliability_destroy,
1426 			}
1427 		},
1428 		{
1429 			.xpath = "/frr-eigrpd:eigrpd/instance/redistribute/metrics/load",
1430 			.cbs = {
1431 				.modify = eigrpd_instance_redistribute_metrics_load_modify,
1432 				.destroy = eigrpd_instance_redistribute_metrics_load_destroy,
1433 			}
1434 		},
1435 		{
1436 			.xpath = "/frr-eigrpd:eigrpd/instance/redistribute/metrics/mtu",
1437 			.cbs = {
1438 				.modify = eigrpd_instance_redistribute_metrics_mtu_modify,
1439 				.destroy = eigrpd_instance_redistribute_metrics_mtu_destroy,
1440 			}
1441 		},
1442 		{
1443 			.xpath = "/frr-interface:lib/interface/frr-eigrpd:eigrp/delay",
1444 			.cbs = {
1445 				.modify = lib_interface_eigrp_delay_modify,
1446 				.cli_show = eigrp_cli_show_delay,
1447 			}
1448 		},
1449 		{
1450 			.xpath = "/frr-interface:lib/interface/frr-eigrpd:eigrp/bandwidth",
1451 			.cbs = {
1452 				.modify = lib_interface_eigrp_bandwidth_modify,
1453 				.cli_show = eigrp_cli_show_bandwidth,
1454 			}
1455 		},
1456 		{
1457 			.xpath = "/frr-interface:lib/interface/frr-eigrpd:eigrp/hello-interval",
1458 			.cbs = {
1459 				.modify = lib_interface_eigrp_hello_interval_modify,
1460 				.cli_show = eigrp_cli_show_hello_interval,
1461 			}
1462 		},
1463 		{
1464 			.xpath = "/frr-interface:lib/interface/frr-eigrpd:eigrp/hold-time",
1465 			.cbs = {
1466 				.modify = lib_interface_eigrp_hold_time_modify,
1467 				.cli_show = eigrp_cli_show_hold_time,
1468 			}
1469 		},
1470 		{
1471 			.xpath = "/frr-interface:lib/interface/frr-eigrpd:eigrp/split-horizon",
1472 			.cbs = {
1473 				.modify = lib_interface_eigrp_split_horizon_modify,
1474 			}
1475 		},
1476 		{
1477 			.xpath = "/frr-interface:lib/interface/frr-eigrpd:eigrp/instance",
1478 			.cbs = {
1479 				.create = lib_interface_eigrp_instance_create,
1480 				.destroy = lib_interface_eigrp_instance_destroy,
1481 			}
1482 		},
1483 		{
1484 			.xpath = "/frr-interface:lib/interface/frr-eigrpd:eigrp/instance/summarize-addresses",
1485 			.cbs = {
1486 				.create = lib_interface_eigrp_instance_summarize_addresses_create,
1487 				.destroy = lib_interface_eigrp_instance_summarize_addresses_destroy,
1488 				.cli_show = eigrp_cli_show_summarize_address,
1489 			}
1490 		},
1491 		{
1492 			.xpath = "/frr-interface:lib/interface/frr-eigrpd:eigrp/instance/authentication",
1493 			.cbs = {
1494 				.modify = lib_interface_eigrp_instance_authentication_modify,
1495 				.cli_show = eigrp_cli_show_authentication,
1496 			}
1497 		},
1498 		{
1499 			.xpath = "/frr-interface:lib/interface/frr-eigrpd:eigrp/instance/keychain",
1500 			.cbs = {
1501 				.modify = lib_interface_eigrp_instance_keychain_modify,
1502 				.destroy = lib_interface_eigrp_instance_keychain_destroy,
1503 				.cli_show = eigrp_cli_show_keychain,
1504 			}
1505 		},
1506 		{
1507 			.xpath = NULL,
1508 		},
1509 	}
1510 };
1511