Coverage Report

Created: 2025-08-28 06:29

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