1 /*
2  * Copyright (C) 2020  Cumulus Networks, Inc.
3  * Chirag Shah
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published by the Free
7  * Software Foundation; either version 2 of the License, or (at your option)
8  * any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  * more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; see the file COPYING; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
20 #include <zebra.h>
21 #include "northbound.h"
22 #include "libfrr.h"
23 #include "zebra_nb.h"
24 #include "zebra/interface.h"
25 #include "zebra/zebra_router.h"
26 #include "zebra/debug.h"
27 #include "printfrr.h"
28 
29 /*
30  * XPath: /frr-interface:lib/interface/frr-zebra:zebra/state/up-count
31  */
32 struct yang_data *
lib_interface_zebra_state_up_count_get_elem(struct nb_cb_get_elem_args * args)33 lib_interface_zebra_state_up_count_get_elem(struct nb_cb_get_elem_args *args)
34 {
35 	const struct interface *ifp = args->list_entry;
36 	struct zebra_if *zebra_if;
37 
38 	zebra_if = ifp->info;
39 
40 	return yang_data_new_uint16(args->xpath, zebra_if->up_count);
41 }
42 
43 /*
44  * XPath: /frr-interface:lib/interface/frr-zebra:zebra/state/down-count
45  */
46 struct yang_data *
lib_interface_zebra_state_down_count_get_elem(struct nb_cb_get_elem_args * args)47 lib_interface_zebra_state_down_count_get_elem(struct nb_cb_get_elem_args *args)
48 {
49 	const struct interface *ifp = args->list_entry;
50 	struct zebra_if *zebra_if;
51 
52 	zebra_if = ifp->info;
53 
54 	return yang_data_new_uint16(args->xpath, zebra_if->down_count);
55 }
56 
57 /*
58  * XPath: /frr-interface:lib/interface/frr-zebra:zebra/state/zif-type
59  */
60 struct yang_data *
lib_interface_zebra_state_zif_type_get_elem(struct nb_cb_get_elem_args * args)61 lib_interface_zebra_state_zif_type_get_elem(struct nb_cb_get_elem_args *args)
62 {
63 	/* TODO: implement me. */
64 	return NULL;
65 }
66 
67 /*
68  * XPath: /frr-interface:lib/interface/frr-zebra:zebra/state/ptm-status
69  */
70 struct yang_data *
lib_interface_zebra_state_ptm_status_get_elem(struct nb_cb_get_elem_args * args)71 lib_interface_zebra_state_ptm_status_get_elem(struct nb_cb_get_elem_args *args)
72 {
73 	/* TODO: implement me. */
74 	return NULL;
75 }
76 
77 /*
78  * XPath: /frr-interface:lib/interface/frr-zebra:zebra/state/vlan-id
79  */
80 struct yang_data *
lib_interface_zebra_state_vlan_id_get_elem(struct nb_cb_get_elem_args * args)81 lib_interface_zebra_state_vlan_id_get_elem(struct nb_cb_get_elem_args *args)
82 {
83 	const struct interface *ifp = args->list_entry;
84 	struct zebra_if *zebra_if;
85 	struct zebra_l2info_vlan *vlan_info;
86 
87 	if (!IS_ZEBRA_IF_VLAN(ifp))
88 		return NULL;
89 
90 	zebra_if = ifp->info;
91 	vlan_info = &zebra_if->l2info.vl;
92 
93 	return yang_data_new_uint16(args->xpath, vlan_info->vid);
94 }
95 
96 /*
97  * XPath: /frr-interface:lib/interface/frr-zebra:zebra/state/vni-id
98  */
99 struct yang_data *
lib_interface_zebra_state_vni_id_get_elem(struct nb_cb_get_elem_args * args)100 lib_interface_zebra_state_vni_id_get_elem(struct nb_cb_get_elem_args *args)
101 {
102 	const struct interface *ifp = args->list_entry;
103 	struct zebra_if *zebra_if;
104 	struct zebra_l2info_vxlan *vxlan_info;
105 
106 	if (!IS_ZEBRA_IF_VXLAN(ifp))
107 		return NULL;
108 
109 	zebra_if = ifp->info;
110 	vxlan_info = &zebra_if->l2info.vxl;
111 
112 	return yang_data_new_uint32(args->xpath, vxlan_info->vni);
113 }
114 
115 /*
116  * XPath: /frr-interface:lib/interface/frr-zebra:zebra/state/remote-vtep
117  */
118 struct yang_data *
lib_interface_zebra_state_remote_vtep_get_elem(struct nb_cb_get_elem_args * args)119 lib_interface_zebra_state_remote_vtep_get_elem(struct nb_cb_get_elem_args *args)
120 {
121 	const struct interface *ifp = args->list_entry;
122 	struct zebra_if *zebra_if;
123 	struct zebra_l2info_vxlan *vxlan_info;
124 
125 	if (!IS_ZEBRA_IF_VXLAN(ifp))
126 		return NULL;
127 
128 	zebra_if = ifp->info;
129 	vxlan_info = &zebra_if->l2info.vxl;
130 
131 	return yang_data_new_ipv4(args->xpath, &vxlan_info->vtep_ip);
132 }
133 
134 /*
135  * XPath: /frr-interface:lib/interface/frr-zebra:zebra/state/mcast-group
136  */
137 struct yang_data *
lib_interface_zebra_state_mcast_group_get_elem(struct nb_cb_get_elem_args * args)138 lib_interface_zebra_state_mcast_group_get_elem(struct nb_cb_get_elem_args *args)
139 {
140 	const struct interface *ifp = args->list_entry;
141 	struct zebra_if *zebra_if;
142 	struct zebra_l2info_vxlan *vxlan_info;
143 
144 	if (!IS_ZEBRA_IF_VXLAN(ifp))
145 		return NULL;
146 
147 	zebra_if = ifp->info;
148 	vxlan_info = &zebra_if->l2info.vxl;
149 
150 	return yang_data_new_ipv4(args->xpath, &vxlan_info->mcast_grp);
151 }
152 
lib_vrf_zebra_ribs_rib_get_next(struct nb_cb_get_next_args * args)153 const void *lib_vrf_zebra_ribs_rib_get_next(struct nb_cb_get_next_args *args)
154 {
155 	struct vrf *vrf = (struct vrf *)args->parent_list_entry;
156 	struct zebra_router_table *zrt =
157 		(struct zebra_router_table *)args->list_entry;
158 
159 	struct zebra_vrf *zvrf;
160 	afi_t afi;
161 	safi_t safi;
162 
163 	zvrf = zebra_vrf_lookup_by_id(vrf->vrf_id);
164 
165 	if (args->list_entry == NULL) {
166 		afi = AFI_IP;
167 		safi = SAFI_UNICAST;
168 
169 		zrt = zebra_router_find_zrt(zvrf, zvrf->table_id, afi, safi);
170 		if (zrt == NULL)
171 			return NULL;
172 	} else {
173 		zrt = RB_NEXT(zebra_router_table_head, zrt);
174 		/* vrf_id/ns_id do not match, only walk for the given VRF */
175 		while (zrt && zrt->ns_id != zvrf->zns->ns_id)
176 			zrt = RB_NEXT(zebra_router_table_head, zrt);
177 	}
178 
179 	return zrt;
180 }
181 
lib_vrf_zebra_ribs_rib_get_keys(struct nb_cb_get_keys_args * args)182 int lib_vrf_zebra_ribs_rib_get_keys(struct nb_cb_get_keys_args *args)
183 {
184 	const struct zebra_router_table *zrt = args->list_entry;
185 
186 	args->keys->num = 2;
187 
188 	snprintfrr(args->keys->key[0], sizeof(args->keys->key[0]), "%s",
189 		   yang_afi_safi_value2identity(zrt->afi, zrt->safi));
190 	snprintfrr(args->keys->key[1], sizeof(args->keys->key[1]), "%u",
191 		   zrt->tableid);
192 
193 	return NB_OK;
194 }
195 
196 const void *
lib_vrf_zebra_ribs_rib_lookup_entry(struct nb_cb_lookup_entry_args * args)197 lib_vrf_zebra_ribs_rib_lookup_entry(struct nb_cb_lookup_entry_args *args)
198 {
199 	struct vrf *vrf = (struct vrf *)args->parent_list_entry;
200 	struct zebra_vrf *zvrf;
201 	afi_t afi;
202 	safi_t safi;
203 	uint32_t table_id = 0;
204 
205 	zvrf = zebra_vrf_lookup_by_id(vrf->vrf_id);
206 
207 	yang_afi_safi_identity2value(args->keys->key[0], &afi, &safi);
208 	table_id = yang_str2uint32(args->keys->key[1]);
209 	/* table_id 0 assume vrf's table_id. */
210 	if (!table_id)
211 		table_id = zvrf->table_id;
212 
213 	return zebra_router_find_zrt(zvrf, table_id, afi, safi);
214 }
215 
216 /*
217  * XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route
218  */
219 const void *
lib_vrf_zebra_ribs_rib_route_get_next(struct nb_cb_get_next_args * args)220 lib_vrf_zebra_ribs_rib_route_get_next(struct nb_cb_get_next_args *args)
221 {
222 	const struct zebra_router_table *zrt = args->parent_list_entry;
223 	struct route_node *rn = (struct route_node *)args->list_entry;
224 
225 	if (args->list_entry == NULL)
226 		rn = route_top(zrt->table);
227 	else
228 		rn = srcdest_route_next((struct route_node *)rn);
229 	/* Optimization: skip empty route nodes. */
230 	while (rn && rn->info == NULL)
231 		rn = route_next(rn);
232 
233 	/* Skip link-local routes. */
234 	if (rn && rn->p.family == AF_INET6
235 	    && IN6_IS_ADDR_LINKLOCAL(&rn->p.u.prefix6))
236 		return NULL;
237 
238 	return rn;
239 }
240 
lib_vrf_zebra_ribs_rib_route_get_keys(struct nb_cb_get_keys_args * args)241 int lib_vrf_zebra_ribs_rib_route_get_keys(struct nb_cb_get_keys_args *args)
242 {
243 	const struct route_node *rn = args->list_entry;
244 
245 	args->keys->num = 1;
246 	prefix2str(&rn->p, args->keys->key[0], sizeof(args->keys->key[0]));
247 
248 	return NB_OK;
249 }
250 
251 const void *
lib_vrf_zebra_ribs_rib_route_lookup_entry(struct nb_cb_lookup_entry_args * args)252 lib_vrf_zebra_ribs_rib_route_lookup_entry(struct nb_cb_lookup_entry_args *args)
253 {
254 	const struct zebra_router_table *zrt = args->parent_list_entry;
255 	struct prefix p;
256 	struct route_node *rn;
257 
258 	yang_str2prefix(args->keys->key[0], &p);
259 
260 	rn = route_node_lookup(zrt->table, &p);
261 
262 	if (!rn)
263 		return NULL;
264 
265 	route_unlock_node(rn);
266 
267 	return rn;
268 }
269 
270 /*
271  * XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/prefix
272  */
273 struct yang_data *
lib_vrf_zebra_ribs_rib_route_prefix_get_elem(struct nb_cb_get_elem_args * args)274 lib_vrf_zebra_ribs_rib_route_prefix_get_elem(struct nb_cb_get_elem_args *args)
275 {
276 	const struct route_node *rn = args->list_entry;
277 
278 	return yang_data_new_prefix(args->xpath, &rn->p);
279 }
280 
281 /*
282  * XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/route-entry
283  */
lib_vrf_zebra_ribs_rib_route_route_entry_get_next(struct nb_cb_get_next_args * args)284 const void *lib_vrf_zebra_ribs_rib_route_route_entry_get_next(
285 	struct nb_cb_get_next_args *args)
286 {
287 	struct route_entry *re = (struct route_entry *)args->list_entry;
288 	struct route_node *rn = (struct route_node *)args->parent_list_entry;
289 
290 	if (args->list_entry == NULL)
291 		RNODE_FIRST_RE(rn, re);
292 	else
293 		RNODE_NEXT_RE(rn, re);
294 
295 	return re;
296 }
297 
lib_vrf_zebra_ribs_rib_route_route_entry_get_keys(struct nb_cb_get_keys_args * args)298 int lib_vrf_zebra_ribs_rib_route_route_entry_get_keys(
299 	struct nb_cb_get_keys_args *args)
300 {
301 	struct route_entry *re = (struct route_entry *)args->list_entry;
302 
303 	args->keys->num = 1;
304 
305 	strlcpy(args->keys->key[0], zebra_route_string(re->type),
306 		sizeof(args->keys->key[0]));
307 
308 	return NB_OK;
309 }
310 
lib_vrf_zebra_ribs_rib_route_route_entry_lookup_entry(struct nb_cb_lookup_entry_args * args)311 const void *lib_vrf_zebra_ribs_rib_route_route_entry_lookup_entry(
312 	struct nb_cb_lookup_entry_args *args)
313 {
314 	struct route_node *rn = (struct route_node *)args->parent_list_entry;
315 	struct route_entry *re = NULL;
316 	int proto_type = 0;
317 	afi_t afi;
318 
319 	afi = family2afi(rn->p.family);
320 	proto_type = proto_redistnum(afi, args->keys->key[0]);
321 
322 	RNODE_FOREACH_RE (rn, re) {
323 		if (proto_type == re->type)
324 			return re;
325 	}
326 
327 	return NULL;
328 }
329 
330 /*
331  * XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/route-entry/protocol
332  */
lib_vrf_zebra_ribs_rib_route_route_entry_protocol_get_elem(struct nb_cb_get_elem_args * args)333 struct yang_data *lib_vrf_zebra_ribs_rib_route_route_entry_protocol_get_elem(
334 	struct nb_cb_get_elem_args *args)
335 {
336 	struct route_entry *re = (struct route_entry *)args->list_entry;
337 
338 	return yang_data_new_enum(args->xpath, re->type);
339 }
340 
341 /*
342  * XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/route-entry/instance
343  */
lib_vrf_zebra_ribs_rib_route_route_entry_instance_get_elem(struct nb_cb_get_elem_args * args)344 struct yang_data *lib_vrf_zebra_ribs_rib_route_route_entry_instance_get_elem(
345 	struct nb_cb_get_elem_args *args)
346 {
347 	struct route_entry *re = (struct route_entry *)args->list_entry;
348 
349 	if (re->instance)
350 		return yang_data_new_uint16(args->xpath, re->instance);
351 
352 	return NULL;
353 }
354 
355 /*
356  * XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/route-entry/distance
357  */
lib_vrf_zebra_ribs_rib_route_route_entry_distance_get_elem(struct nb_cb_get_elem_args * args)358 struct yang_data *lib_vrf_zebra_ribs_rib_route_route_entry_distance_get_elem(
359 	struct nb_cb_get_elem_args *args)
360 {
361 	struct route_entry *re = (struct route_entry *)args->list_entry;
362 
363 	return yang_data_new_uint8(args->xpath, re->distance);
364 }
365 
366 /*
367  * XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/route-entry/metric
368  */
lib_vrf_zebra_ribs_rib_route_route_entry_metric_get_elem(struct nb_cb_get_elem_args * args)369 struct yang_data *lib_vrf_zebra_ribs_rib_route_route_entry_metric_get_elem(
370 	struct nb_cb_get_elem_args *args)
371 {
372 	struct route_entry *re = (struct route_entry *)args->list_entry;
373 
374 	return yang_data_new_uint32(args->xpath, re->metric);
375 }
376 
377 /*
378  * XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/route-entry/tag
379  */
lib_vrf_zebra_ribs_rib_route_route_entry_tag_get_elem(struct nb_cb_get_elem_args * args)380 struct yang_data *lib_vrf_zebra_ribs_rib_route_route_entry_tag_get_elem(
381 	struct nb_cb_get_elem_args *args)
382 {
383 	struct route_entry *re = (struct route_entry *)args->list_entry;
384 
385 	if (re->tag)
386 		return yang_data_new_uint32(args->xpath, re->tag);
387 
388 	return NULL;
389 }
390 
391 /*
392  * XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/route-entry/selected
393  */
lib_vrf_zebra_ribs_rib_route_route_entry_selected_get_elem(struct nb_cb_get_elem_args * args)394 struct yang_data *lib_vrf_zebra_ribs_rib_route_route_entry_selected_get_elem(
395 	struct nb_cb_get_elem_args *args)
396 {
397 	struct route_entry *re = (struct route_entry *)args->list_entry;
398 
399 	if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED))
400 		return yang_data_new_empty(args->xpath);
401 
402 	return NULL;
403 }
404 
405 /*
406  * XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/route-entry/installed
407  */
lib_vrf_zebra_ribs_rib_route_route_entry_installed_get_elem(struct nb_cb_get_elem_args * args)408 struct yang_data *lib_vrf_zebra_ribs_rib_route_route_entry_installed_get_elem(
409 	struct nb_cb_get_elem_args *args)
410 {
411 	struct route_entry *re = (struct route_entry *)args->list_entry;
412 
413 	if (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED))
414 		return yang_data_new_empty(args->xpath);
415 
416 	return NULL;
417 }
418 
419 /*
420  * XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/route-entry/failed
421  */
lib_vrf_zebra_ribs_rib_route_route_entry_failed_get_elem(struct nb_cb_get_elem_args * args)422 struct yang_data *lib_vrf_zebra_ribs_rib_route_route_entry_failed_get_elem(
423 	struct nb_cb_get_elem_args *args)
424 {
425 	struct route_entry *re = (struct route_entry *)args->list_entry;
426 
427 	if (CHECK_FLAG(re->status, ROUTE_ENTRY_FAILED))
428 		return yang_data_new_empty(args->xpath);
429 
430 	return NULL;
431 }
432 
433 /*
434  * XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/route-entry/queued
435  */
lib_vrf_zebra_ribs_rib_route_route_entry_queued_get_elem(struct nb_cb_get_elem_args * args)436 struct yang_data *lib_vrf_zebra_ribs_rib_route_route_entry_queued_get_elem(
437 	struct nb_cb_get_elem_args *args)
438 {
439 	struct route_entry *re = (struct route_entry *)args->list_entry;
440 
441 	if (CHECK_FLAG(re->status, ROUTE_ENTRY_QUEUED))
442 		return yang_data_new_empty(args->xpath);
443 
444 	return NULL;
445 }
446 
447 /*
448  * XPath:
449  * /frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/route-entry/internal-flags
450  */
451 struct yang_data *
lib_vrf_zebra_ribs_rib_route_route_entry_internal_flags_get_elem(struct nb_cb_get_elem_args * args)452 lib_vrf_zebra_ribs_rib_route_route_entry_internal_flags_get_elem(
453 	struct nb_cb_get_elem_args *args)
454 {
455 	struct route_entry *re = (struct route_entry *)args->list_entry;
456 
457 	if (re->flags)
458 		return yang_data_new_int32(args->xpath, re->flags);
459 
460 	return NULL;
461 }
462 
463 /*
464  * XPath:
465  * /frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/route-entry/internal-status
466  */
467 struct yang_data *
lib_vrf_zebra_ribs_rib_route_route_entry_internal_status_get_elem(struct nb_cb_get_elem_args * args)468 lib_vrf_zebra_ribs_rib_route_route_entry_internal_status_get_elem(
469 	struct nb_cb_get_elem_args *args)
470 {
471 	struct route_entry *re = (struct route_entry *)args->list_entry;
472 
473 	if (re->status)
474 		return yang_data_new_int32(args->xpath, re->status);
475 
476 	return NULL;
477 }
478 
479 /*
480  * XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/route-entry/uptime
481  */
lib_vrf_zebra_ribs_rib_route_route_entry_uptime_get_elem(struct nb_cb_get_elem_args * args)482 struct yang_data *lib_vrf_zebra_ribs_rib_route_route_entry_uptime_get_elem(
483 	struct nb_cb_get_elem_args *args)
484 {
485 	struct route_entry *re = (struct route_entry *)args->list_entry;
486 
487 	return yang_data_new_date_and_time(args->xpath, re->uptime);
488 }
489 
490 /*
491  * XPath:
492  * /frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/route-entry/nexthop-group/id
493  */
494 struct yang_data *
lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_id_get_elem(struct nb_cb_get_elem_args * args)495 lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_id_get_elem(
496 	struct nb_cb_get_elem_args *args)
497 {
498 	struct route_entry *re = (struct route_entry *)args->list_entry;
499 
500 	return yang_data_new_uint32(args->xpath, re->nhe->id);
501 }
502 
503 /*
504  * XPath:
505  * /frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/route-entry/nexthop-group/nexthop
506  */
507 const void *
lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_get_next(struct nb_cb_get_next_args * args)508 lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_get_next(
509 	struct nb_cb_get_next_args *args)
510 {
511 	struct nexthop *nexthop = (struct nexthop *)args->list_entry;
512 	struct route_entry *re = (struct route_entry *)args->parent_list_entry;
513 	struct nhg_hash_entry *nhe = re->nhe;
514 
515 	if (args->list_entry == NULL) {
516 		nexthop = nhe->nhg.nexthop;
517 	} else
518 		nexthop = nexthop_next(nexthop);
519 
520 	return nexthop;
521 }
522 
lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_get_keys(struct nb_cb_get_keys_args * args)523 int lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_get_keys(
524 	struct nb_cb_get_keys_args *args)
525 {
526 	struct nexthop *nexthop = (struct nexthop *)args->list_entry;
527 
528 	args->keys->num = 4;
529 
530 	strlcpy(args->keys->key[0], yang_nexthop_type2str(nexthop->type),
531 		sizeof(args->keys->key[0]));
532 
533 	snprintfrr(args->keys->key[1], sizeof(args->keys->key[1]), "%" PRIu32,
534 		   nexthop->vrf_id);
535 
536 	switch (nexthop->type) {
537 	case NEXTHOP_TYPE_IPV4:
538 	case NEXTHOP_TYPE_IPV4_IFINDEX:
539 		snprintfrr(args->keys->key[2], sizeof(args->keys->key[2]),
540 			   "%pI4", &nexthop->gate.ipv4);
541 		if (nexthop->ifindex)
542 			strlcpy(args->keys->key[3],
543 				ifindex2ifname(nexthop->ifindex,
544 					       nexthop->vrf_id),
545 				sizeof(args->keys->key[3]));
546 		else
547 			/* no ifindex */
548 			strlcpy(args->keys->key[3], " ",
549 				sizeof(args->keys->key[3]));
550 
551 		break;
552 	case NEXTHOP_TYPE_IPV6:
553 	case NEXTHOP_TYPE_IPV6_IFINDEX:
554 		snprintfrr(args->keys->key[2], sizeof(args->keys->key[2]),
555 			   "%pI6", &nexthop->gate.ipv6);
556 
557 		if (nexthop->ifindex)
558 			strlcpy(args->keys->key[3],
559 				ifindex2ifname(nexthop->ifindex,
560 					       nexthop->vrf_id),
561 				sizeof(args->keys->key[3]));
562 		else
563 			/* no ifindex */
564 			strlcpy(args->keys->key[3], " ",
565 				sizeof(args->keys->key[3]));
566 
567 		break;
568 	case NEXTHOP_TYPE_IFINDEX:
569 		strlcpy(args->keys->key[2], "", sizeof(args->keys->key[2]));
570 		strlcpy(args->keys->key[3],
571 			ifindex2ifname(nexthop->ifindex, nexthop->vrf_id),
572 			sizeof(args->keys->key[3]));
573 
574 		break;
575 	case NEXTHOP_TYPE_BLACKHOLE:
576 		/* Gateway IP */
577 		strlcpy(args->keys->key[2], "", sizeof(args->keys->key[2]));
578 		strlcpy(args->keys->key[3], " ", sizeof(args->keys->key[3]));
579 		break;
580 	default:
581 		break;
582 	}
583 
584 	return NB_OK;
585 }
586 
587 const void *
lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_lookup_entry(struct nb_cb_lookup_entry_args * args)588 lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_lookup_entry(
589 	struct nb_cb_lookup_entry_args *args)
590 {
591 	struct nhg_hash_entry *nhe;
592 	struct nexthop nexthop_lookup = {};
593 	struct nexthop *nexthop;
594 	const char *nh_type_str;
595 
596 	nhe = (struct nhg_hash_entry *)args->parent_list_entry;
597 	nexthop_lookup.vrf_id = nhe->vrf_id;
598 
599 	/*
600 	 * Get nexthop type.
601 	 * TODO: use yang_str2enum() instead.
602 	 */
603 	nh_type_str = args->keys->key[0];
604 	if (strmatch(nh_type_str, "ifindex"))
605 		nexthop_lookup.type = NEXTHOP_TYPE_IFINDEX;
606 	else if (strmatch(nh_type_str, "ip4"))
607 		nexthop_lookup.type = NEXTHOP_TYPE_IPV4;
608 	else if (strmatch(nh_type_str, "ip4-ifindex"))
609 		nexthop_lookup.type = NEXTHOP_TYPE_IPV4_IFINDEX;
610 	else if (strmatch(nh_type_str, "ip6"))
611 		nexthop_lookup.type = NEXTHOP_TYPE_IPV6;
612 	else if (strmatch(nh_type_str, "ip6-ifindex"))
613 		nexthop_lookup.type = NEXTHOP_TYPE_IPV6_IFINDEX;
614 	else if (strmatch(nh_type_str, "blackhole"))
615 		nexthop_lookup.type = NEXTHOP_TYPE_BLACKHOLE;
616 	else
617 		/* unexpected */
618 		return NULL;
619 
620 	/* Get nexthop address. */
621 	switch (nexthop_lookup.type) {
622 	case NEXTHOP_TYPE_IPV4:
623 	case NEXTHOP_TYPE_IPV4_IFINDEX:
624 		yang_str2ipv4(args->keys->key[1], &nexthop_lookup.gate.ipv4);
625 		break;
626 	case NEXTHOP_TYPE_IPV6:
627 	case NEXTHOP_TYPE_IPV6_IFINDEX:
628 		yang_str2ipv6(args->keys->key[1], &nexthop_lookup.gate.ipv6);
629 		break;
630 	case NEXTHOP_TYPE_IFINDEX:
631 	case NEXTHOP_TYPE_BLACKHOLE:
632 		break;
633 	}
634 
635 	/* Get nexthop interface. */
636 	switch (nexthop_lookup.type) {
637 	case NEXTHOP_TYPE_IPV4_IFINDEX:
638 	case NEXTHOP_TYPE_IPV6_IFINDEX:
639 	case NEXTHOP_TYPE_IFINDEX:
640 		nexthop_lookup.ifindex =
641 			ifname2ifindex(args->keys->key[2], nhe->vrf_id);
642 		break;
643 	case NEXTHOP_TYPE_IPV4:
644 	case NEXTHOP_TYPE_IPV6:
645 	case NEXTHOP_TYPE_BLACKHOLE:
646 		break;
647 	}
648 
649 	/* Lookup requested nexthop (ignore weight and metric). */
650 	for (ALL_NEXTHOPS(nhe->nhg, nexthop)) {
651 		nexthop_lookup.weight = nexthop->weight;
652 		nexthop_lookup.src = nexthop->src;
653 		if (nexthop_same_no_labels(&nexthop_lookup, nexthop))
654 			return nexthop;
655 	}
656 
657 	return NULL;
658 }
659 
660 /*
661  * XPath:
662  * /frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/route-entry/nexthop-group/nexthop/nh-type
663  */
664 struct yang_data *
lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_nh_type_get_elem(struct nb_cb_get_elem_args * args)665 lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_nh_type_get_elem(
666 	struct nb_cb_get_elem_args *args)
667 {
668 	struct nexthop *nexthop = (struct nexthop *)args->list_entry;
669 
670 	switch (nexthop->type) {
671 	case NEXTHOP_TYPE_IFINDEX:
672 		return yang_data_new_string(args->xpath, "ifindex");
673 		break;
674 	case NEXTHOP_TYPE_IPV4:
675 		return yang_data_new_string(args->xpath, "ip4");
676 		break;
677 	case NEXTHOP_TYPE_IPV4_IFINDEX:
678 		return yang_data_new_string(args->xpath, "ip4-ifindex");
679 		break;
680 	case NEXTHOP_TYPE_IPV6:
681 		return yang_data_new_string(args->xpath, "ip6");
682 		break;
683 	case NEXTHOP_TYPE_IPV6_IFINDEX:
684 		return yang_data_new_string(args->xpath, "ip6-ifindex");
685 		break;
686 	default:
687 		break;
688 	}
689 
690 	return NULL;
691 }
692 
693 /*
694  * XPath:
695  * /frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/route-entry/nexthop-group/nexthop/vrf
696  */
697 struct yang_data *
lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_vrf_get_elem(struct nb_cb_get_elem_args * args)698 lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_vrf_get_elem(
699 	struct nb_cb_get_elem_args *args)
700 {
701 	struct nexthop *nexthop = (struct nexthop *)args->list_entry;
702 
703 	return yang_data_new_string(args->xpath,
704 				    vrf_id_to_name(nexthop->vrf_id));
705 }
706 
707 /*
708  * XPath:
709  * /frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/route-entry/nexthop-group/nexthop/gateway
710  */
711 struct yang_data *
lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_gateway_get_elem(struct nb_cb_get_elem_args * args)712 lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_gateway_get_elem(
713 	struct nb_cb_get_elem_args *args)
714 {
715 	struct nexthop *nexthop = (struct nexthop *)args->list_entry;
716 	struct ipaddr addr;
717 
718 	switch (nexthop->type) {
719 	case NEXTHOP_TYPE_IPV4:
720 	case NEXTHOP_TYPE_IPV4_IFINDEX:
721 		addr.ipa_type = IPADDR_V4;
722 		memcpy(&addr.ipaddr_v4, &(nexthop->gate.ipv4),
723 		       sizeof(struct in_addr));
724 		break;
725 	case NEXTHOP_TYPE_IPV6:
726 	case NEXTHOP_TYPE_IPV6_IFINDEX:
727 		addr.ipa_type = IPADDR_V6;
728 		memcpy(&addr.ipaddr_v6, &(nexthop->gate.ipv6),
729 		       sizeof(struct in6_addr));
730 		break;
731 	case NEXTHOP_TYPE_BLACKHOLE:
732 	case NEXTHOP_TYPE_IFINDEX:
733 		/* No addr here */
734 		return yang_data_new_string(args->xpath, "");
735 		break;
736 	default:
737 		break;
738 	}
739 
740 	return yang_data_new_ip(args->xpath, &addr);
741 }
742 
743 /*
744  * XPath:
745  * /frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/route-entry/nexthop-group/nexthop/interface
746  */
747 struct yang_data *
lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_interface_get_elem(struct nb_cb_get_elem_args * args)748 lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_interface_get_elem(
749 	struct nb_cb_get_elem_args *args)
750 {
751 	struct nexthop *nexthop = (struct nexthop *)args->list_entry;
752 
753 	if (nexthop->ifindex)
754 		return yang_data_new_string(
755 			args->xpath,
756 			ifindex2ifname(nexthop->ifindex, nexthop->vrf_id));
757 
758 	return NULL;
759 }
760 
761 /*
762  * XPath:
763  * /frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/route-entry/nexthop-group/nexthop/bh-type
764  */
765 struct yang_data *
lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_bh_type_get_elem(struct nb_cb_get_elem_args * args)766 lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_bh_type_get_elem(
767 	struct nb_cb_get_elem_args *args)
768 {
769 	struct nexthop *nexthop = (struct nexthop *)args->list_entry;
770 	const char *type_str = "";
771 
772 	if (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)
773 		return NULL;
774 
775 	switch (nexthop->bh_type) {
776 	case BLACKHOLE_NULL:
777 		type_str = "null";
778 		break;
779 	case BLACKHOLE_REJECT:
780 		type_str = "reject";
781 		break;
782 	case BLACKHOLE_ADMINPROHIB:
783 		type_str = "prohibited";
784 		break;
785 	case BLACKHOLE_UNSPEC:
786 		type_str = "unspec";
787 		break;
788 	}
789 
790 	return yang_data_new_string(args->xpath, type_str);
791 }
792 
793 /*
794  * XPath:
795  * /frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/route-entry/nexthop-group/nexthop/onlink
796  */
797 struct yang_data *
lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_onlink_get_elem(struct nb_cb_get_elem_args * args)798 lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_onlink_get_elem(
799 	struct nb_cb_get_elem_args *args)
800 {
801 	struct nexthop *nexthop = (struct nexthop *)args->list_entry;
802 
803 	if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
804 		return yang_data_new_bool(args->xpath, true);
805 
806 	return NULL;
807 }
808 
809 /*
810  * XPath:
811  * /frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/route-entry/nexthop-group/nexthop/srte-color
812  */
813 struct yang_data *
lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_color_get_elem(struct nb_cb_get_elem_args * args)814 lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_color_get_elem(
815 	struct nb_cb_get_elem_args *args)
816 {
817 	struct nexthop *nexthop = (struct nexthop *)args->list_entry;
818 
819 	if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_SRTE))
820 		return yang_data_new_uint32(args->xpath, nexthop->srte_color);
821 
822 	return NULL;
823 }
824 
825 /*
826  * XPath:
827  * /frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/route-entry/nexthop-group/nexthop/mpls-label-stack/entry
828  */
829 const void *
lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_mpls_label_stack_entry_get_next(struct nb_cb_get_next_args * args)830 lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_mpls_label_stack_entry_get_next(
831 	struct nb_cb_get_next_args *args)
832 {
833 	/* TODO: implement me. */
834 	return NULL;
835 }
836 
lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_mpls_label_stack_entry_get_keys(struct nb_cb_get_keys_args * args)837 int lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_mpls_label_stack_entry_get_keys(
838 	struct nb_cb_get_keys_args *args)
839 {
840 	/* TODO: implement me. */
841 	return NB_OK;
842 }
843 
844 const void *
lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_mpls_label_stack_entry_lookup_entry(struct nb_cb_lookup_entry_args * args)845 lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_mpls_label_stack_entry_lookup_entry(
846 	struct nb_cb_lookup_entry_args *args)
847 {
848 	/* TODO: implement me. */
849 	return NULL;
850 }
851 
852 /*
853  * XPath:
854  * /frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/route-entry/nexthop-group/nexthop/mpls-label-stack/entry/id
855  */
856 struct yang_data *
lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_mpls_label_stack_entry_id_get_elem(struct nb_cb_get_elem_args * args)857 lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_mpls_label_stack_entry_id_get_elem(
858 	struct nb_cb_get_elem_args *args)
859 {
860 	/* TODO: implement me. */
861 	return NULL;
862 }
863 
864 /*
865  * XPath:
866  * /frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/route-entry/nexthop-group/nexthop/mpls-label-stack/entry/label
867  */
868 struct yang_data *
lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_mpls_label_stack_entry_label_get_elem(struct nb_cb_get_elem_args * args)869 lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_mpls_label_stack_entry_label_get_elem(
870 	struct nb_cb_get_elem_args *args)
871 {
872 	/* TODO: implement me. */
873 	return NULL;
874 }
875 
876 /*
877  * XPath:
878  * /frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/route-entry/nexthop-group/nexthop/mpls-label-stack/entry/ttl
879  */
880 struct yang_data *
lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_mpls_label_stack_entry_ttl_get_elem(struct nb_cb_get_elem_args * args)881 lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_mpls_label_stack_entry_ttl_get_elem(
882 	struct nb_cb_get_elem_args *args)
883 {
884 	/* TODO: implement me. */
885 	return NULL;
886 }
887 
888 /*
889  * XPath:
890  * /frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/route-entry/nexthop-group/nexthop/mpls-label-stack/entry/traffic-class
891  */
892 struct yang_data *
lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_mpls_label_stack_entry_traffic_class_get_elem(struct nb_cb_get_elem_args * args)893 lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_mpls_label_stack_entry_traffic_class_get_elem(
894 	struct nb_cb_get_elem_args *args)
895 {
896 	/* TODO: implement me. */
897 	return NULL;
898 }
899 
900 /*
901  * XPath:
902  * /frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/route-entry/nexthop-group/nexthop/duplicate
903  */
904 struct yang_data *
lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_duplicate_get_elem(struct nb_cb_get_elem_args * args)905 lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_duplicate_get_elem(
906 	struct nb_cb_get_elem_args *args)
907 {
908 	struct nexthop *nexthop = (struct nexthop *)args->list_entry;
909 
910 	if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE))
911 		return yang_data_new_empty(args->xpath);
912 
913 	return NULL;
914 }
915 
916 /*
917  * XPath:
918  * /frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/route-entry/nexthop-group/nexthop/recursive
919  */
920 struct yang_data *
lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_recursive_get_elem(struct nb_cb_get_elem_args * args)921 lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_recursive_get_elem(
922 	struct nb_cb_get_elem_args *args)
923 {
924 	struct nexthop *nexthop = (struct nexthop *)args->list_entry;
925 
926 	if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
927 		return yang_data_new_empty(args->xpath);
928 
929 	return NULL;
930 }
931 
932 /*
933  * XPath:
934  * /frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/route-entry/nexthop-group/nexthop/active
935  */
936 struct yang_data *
lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_active_get_elem(struct nb_cb_get_elem_args * args)937 lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_active_get_elem(
938 	struct nb_cb_get_elem_args *args)
939 {
940 	struct nexthop *nexthop = (struct nexthop *)args->list_entry;
941 
942 	if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
943 		return yang_data_new_empty(args->xpath);
944 
945 	return NULL;
946 }
947 
948 /*
949  * XPath:
950  * /frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/route-entry/nexthop-group/nexthop/fib
951  */
952 struct yang_data *
lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_fib_get_elem(struct nb_cb_get_elem_args * args)953 lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_fib_get_elem(
954 	struct nb_cb_get_elem_args *args)
955 {
956 	struct nexthop *nexthop = (struct nexthop *)args->list_entry;
957 
958 	if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))
959 		return yang_data_new_empty(args->xpath);
960 
961 	return NULL;
962 }
963 
964 /*
965  * XPath:
966  * /frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/route-entry/nexthop-group/nexthop/weight
967  */
968 struct yang_data *
lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_weight_get_elem(struct nb_cb_get_elem_args * args)969 lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_weight_get_elem(
970 	struct nb_cb_get_elem_args *args)
971 {
972 	struct nexthop *nexthop = (struct nexthop *)args->list_entry;
973 
974 	if (nexthop->weight)
975 		return yang_data_new_uint8(args->xpath, nexthop->weight);
976 
977 	return NULL;
978 }
979