Coverage Report

Created: 2026-02-21 06:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/frr/zebra/interface.c
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
 * Interface function.
4
 * Copyright (C) 1997, 1999 Kunihiro Ishiguro
5
 */
6
7
#include <zebra.h>
8
9
#include "if.h"
10
#include "lib_errors.h"
11
#include "vty.h"
12
#include "sockunion.h"
13
#include "prefix.h"
14
#include "command.h"
15
#include "memory.h"
16
#include "ioctl.h"
17
#include "connected.h"
18
#include "log.h"
19
#include "zclient.h"
20
#include "vrf.h"
21
#include "lib/northbound_cli.h"
22
23
#include "zebra/rtadv.h"
24
#include "zebra_ns.h"
25
#include "zebra_vrf.h"
26
#include "zebra/interface.h"
27
#include "zebra/rib.h"
28
#include "zebra/rt.h"
29
#include "zebra/zebra_router.h"
30
#include "zebra/redistribute.h"
31
#include "zebra/debug.h"
32
#include "zebra/irdp.h"
33
#include "zebra/zebra_ptm.h"
34
#include "zebra/rt_netlink.h"
35
#include "zebra/if_netlink.h"
36
#include "zebra/interface.h"
37
#include "zebra/zebra_vxlan.h"
38
#include "zebra/zebra_errors.h"
39
#include "zebra/zebra_evpn_mh.h"
40
41
2
DEFINE_MTYPE_STATIC(ZEBRA, ZINFO, "Zebra Interface Information");
42
2
43
2
#define ZEBRA_PTM_SUPPORT
44
2
45
2
DEFINE_HOOK(zebra_if_extra_info, (struct vty * vty, struct interface *ifp),
46
2
      (vty, ifp));
47
2
DEFINE_HOOK(zebra_if_config_wr, (struct vty * vty, struct interface *ifp),
48
2
      (vty, ifp));
49
2
50
2
DEFINE_MTYPE(ZEBRA, ZIF_DESC, "Intf desc");
51
2
52
2
static void if_down_del_nbr_connected(struct interface *ifp);
53
2
54
2
static void if_zebra_speed_update(struct event *thread)
55
2
{
56
0
  struct interface *ifp = EVENT_ARG(thread);
57
0
  struct zebra_if *zif = ifp->info;
58
0
  uint32_t new_speed;
59
0
  bool changed = false;
60
0
  int error = 0;
61
0
62
0
  new_speed = kernel_get_speed(ifp, &error);
63
0
64
0
  /* error may indicate vrf not available or
65
0
   * interfaces not available.
66
0
   * note that loopback & virtual interfaces can return 0 as speed
67
0
   */
68
0
  if (error < 0)
69
0
    return;
70
0
71
0
  if (new_speed != ifp->speed) {
72
0
    zlog_info("%s: %s old speed: %u new speed: %u", __func__,
73
0
        ifp->name, ifp->speed, new_speed);
74
0
    ifp->speed = new_speed;
75
0
    if_add_update(ifp);
76
0
    changed = true;
77
0
  }
78
0
79
0
  if (changed || new_speed == UINT32_MAX) {
80
0
#define SPEED_UPDATE_SLEEP_TIME 5
81
0
#define SPEED_UPDATE_COUNT_MAX (4 * 60 / SPEED_UPDATE_SLEEP_TIME)
82
0
    /*
83
0
     * Some interfaces never actually have an associated speed
84
0
     * with them ( I am looking at you bridges ).
85
0
     * So instead of iterating forever, let's give the
86
0
     * system 4 minutes to try to figure out the speed
87
0
     * if after that it it's probably never going to become
88
0
     * useful.
89
0
     * Since I don't know all the wonderful types of interfaces
90
0
     * that may come into existence in the future I am going
91
0
     * to not update the system to keep track of that.  This
92
0
     * is far simpler to just stop trying after 4 minutes
93
0
     */
94
0
    if (new_speed == UINT32_MAX &&
95
0
        zif->speed_update_count == SPEED_UPDATE_COUNT_MAX)
96
0
      return;
97
0
98
0
    zif->speed_update_count++;
99
0
    event_add_timer(zrouter.master, if_zebra_speed_update, ifp,
100
0
        SPEED_UPDATE_SLEEP_TIME, &zif->speed_update);
101
0
    event_ignore_late_timer(zif->speed_update);
102
0
  }
103
0
}
104
105
static void zebra_if_node_destroy(route_table_delegate_t *delegate,
106
          struct route_table *table,
107
          struct route_node *node)
108
0
{
109
0
  if (node->info)
110
0
    list_delete((struct list **)&node->info);
111
0
  route_node_destroy(delegate, table, node);
112
0
}
113
114
static void zebra_if_nhg_dependents_free(struct zebra_if *zebra_if)
115
0
{
116
0
  nhg_connected_tree_free(&zebra_if->nhg_dependents);
117
0
}
118
119
static void zebra_if_nhg_dependents_init(struct zebra_if *zebra_if)
120
0
{
121
0
  nhg_connected_tree_init(&zebra_if->nhg_dependents);
122
0
}
123
124
125
route_table_delegate_t zebra_if_table_delegate = {
126
  .create_node = route_node_create,
127
  .destroy_node = zebra_if_node_destroy};
128
129
/* Called when new interface is added. */
130
static int if_zebra_new_hook(struct interface *ifp)
131
0
{
132
0
  struct zebra_if *zebra_if;
133
134
0
  zebra_if = XCALLOC(MTYPE_ZINFO, sizeof(struct zebra_if));
135
0
  zebra_if->ifp = ifp;
136
137
0
  zebra_if->multicast = IF_ZEBRA_DATA_UNSPEC;
138
0
  zebra_if->shutdown = IF_ZEBRA_DATA_OFF;
139
140
0
  zebra_if->link_nsid = NS_UNKNOWN;
141
142
0
  zebra_if_nhg_dependents_init(zebra_if);
143
144
0
  zebra_ptm_if_init(zebra_if);
145
146
0
  ifp->ptm_enable = zebra_ptm_get_enable_state();
147
148
0
  rtadv_if_init(zebra_if);
149
150
0
  memset(&zebra_if->neigh_mac[0], 0, 6);
151
152
  /* Initialize installed address chains tree. */
153
0
  zebra_if->ipv4_subnets =
154
0
    route_table_init_with_delegate(&zebra_if_table_delegate);
155
156
0
  ifp->info = zebra_if;
157
158
  /*
159
   * Some platforms are telling us that the interface is
160
   * up and ready to go.  When we check the speed we
161
   * sometimes get the wrong value.  Wait a couple
162
   * of seconds and ask again.  Hopefully it's all settled
163
   * down upon startup.
164
   */
165
0
  zebra_if->speed_update_count = 0;
166
0
  event_add_timer(zrouter.master, if_zebra_speed_update, ifp, 15,
167
0
      &zebra_if->speed_update);
168
0
  event_ignore_late_timer(zebra_if->speed_update);
169
170
0
  return 0;
171
0
}
172
173
static void if_nhg_dependents_check_valid(struct nhg_hash_entry *nhe)
174
0
{
175
0
  zebra_nhg_check_valid(nhe);
176
0
}
177
178
static void if_down_nhg_dependents(const struct interface *ifp)
179
0
{
180
0
  struct nhg_connected *rb_node_dep = NULL;
181
0
  struct zebra_if *zif = (struct zebra_if *)ifp->info;
182
183
0
  frr_each(nhg_connected_tree, &zif->nhg_dependents, rb_node_dep)
184
0
    if_nhg_dependents_check_valid(rb_node_dep->nhe);
185
0
}
186
187
static void if_nhg_dependents_release(const struct interface *ifp)
188
0
{
189
0
  struct nhg_connected *rb_node_dep = NULL;
190
0
  struct zebra_if *zif = (struct zebra_if *)ifp->info;
191
192
0
  frr_each(nhg_connected_tree, &zif->nhg_dependents, rb_node_dep) {
193
0
    rb_node_dep->nhe->ifp = NULL; /* Null it out */
194
0
    if_nhg_dependents_check_valid(rb_node_dep->nhe);
195
0
  }
196
0
}
197
198
/* Called when interface is deleted. */
199
static int if_zebra_delete_hook(struct interface *ifp)
200
0
{
201
0
  struct zebra_if *zebra_if;
202
203
0
  if (ifp->info) {
204
0
    zebra_if = ifp->info;
205
206
    /* If we set protodown, clear our reason now from the kernel */
207
0
    if (ZEBRA_IF_IS_PROTODOWN(zebra_if) && zebra_if->protodown_rc &&
208
0
        !ZEBRA_IF_IS_PROTODOWN_ONLY_EXTERNAL(zebra_if))
209
0
      zebra_if_update_protodown_rc(ifp, true,
210
0
                 (zebra_if->protodown_rc &
211
0
                  ~ZEBRA_PROTODOWN_ALL));
212
213
    /* Free installed address chains tree. */
214
0
    if (zebra_if->ipv4_subnets)
215
0
      route_table_finish(zebra_if->ipv4_subnets);
216
217
0
    rtadv_if_fini(zebra_if);
218
219
0
    zebra_l2_bridge_if_cleanup(ifp);
220
0
    zebra_evpn_if_cleanup(zebra_if);
221
0
    zebra_evpn_mac_ifp_del(ifp);
222
223
0
    if_nhg_dependents_release(ifp);
224
0
    zebra_if_nhg_dependents_free(zebra_if);
225
226
0
    XFREE(MTYPE_ZIF_DESC, zebra_if->desc);
227
228
0
    EVENT_OFF(zebra_if->speed_update);
229
230
0
    XFREE(MTYPE_ZINFO, zebra_if);
231
0
  }
232
233
0
  return 0;
234
0
}
235
236
/* Build the table key */
237
static void if_build_key(uint32_t ifindex, struct prefix *p)
238
0
{
239
0
  p->family = AF_INET;
240
0
  p->prefixlen = IPV4_MAX_BITLEN;
241
0
  p->u.prefix4.s_addr = ifindex;
242
0
}
243
244
/* Link an interface in a per NS interface tree */
245
struct interface *if_link_per_ns(struct zebra_ns *ns, struct interface *ifp)
246
0
{
247
0
  struct prefix p;
248
0
  struct route_node *rn;
249
250
0
  if (ifp->ifindex == IFINDEX_INTERNAL)
251
0
    return NULL;
252
253
0
  if_build_key(ifp->ifindex, &p);
254
0
  rn = route_node_get(ns->if_table, &p);
255
0
  if (rn->info) {
256
0
    ifp = (struct interface *)rn->info;
257
0
    route_unlock_node(rn); /* get */
258
0
    return ifp;
259
0
  }
260
261
0
  rn->info = ifp;
262
0
  ifp->node = rn;
263
264
0
  return ifp;
265
0
}
266
267
/* Delete a VRF. This is called in vrf_terminate(). */
268
void if_unlink_per_ns(struct interface *ifp)
269
0
{
270
0
  if (!ifp->node)
271
0
    return;
272
273
0
  ifp->node->info = NULL;
274
0
  route_unlock_node(ifp->node);
275
0
  ifp->node = NULL;
276
0
}
277
278
/* Look up an interface by identifier within a NS */
279
struct interface *if_lookup_by_index_per_ns(struct zebra_ns *ns,
280
              uint32_t ifindex)
281
0
{
282
0
  struct prefix p;
283
0
  struct route_node *rn;
284
0
  struct interface *ifp = NULL;
285
286
0
  if_build_key(ifindex, &p);
287
0
  rn = route_node_lookup(ns->if_table, &p);
288
0
  if (rn) {
289
0
    ifp = (struct interface *)rn->info;
290
0
    route_unlock_node(rn); /* lookup */
291
0
  }
292
0
  return ifp;
293
0
}
294
295
/* Look up an interface by name within a NS */
296
struct interface *if_lookup_by_name_per_ns(struct zebra_ns *ns,
297
             const char *ifname)
298
0
{
299
0
  struct route_node *rn;
300
0
  struct interface *ifp;
301
302
0
  for (rn = route_top(ns->if_table); rn; rn = route_next(rn)) {
303
0
    ifp = (struct interface *)rn->info;
304
0
    if (ifp && strcmp(ifp->name, ifname) == 0) {
305
0
      route_unlock_node(rn);
306
0
      return (ifp);
307
0
    }
308
0
  }
309
310
0
  return NULL;
311
0
}
312
313
struct interface *if_lookup_by_index_per_nsid(ns_id_t ns_id, uint32_t ifindex)
314
0
{
315
0
  struct zebra_ns *zns;
316
317
0
  zns = zebra_ns_lookup(ns_id);
318
0
  return zns ? if_lookup_by_index_per_ns(zns, ifindex) : NULL;
319
0
}
320
321
const char *ifindex2ifname_per_ns(struct zebra_ns *zns, unsigned int ifindex)
322
0
{
323
0
  struct interface *ifp;
324
325
0
  return ((ifp = if_lookup_by_index_per_ns(zns, ifindex)) != NULL)
326
0
           ? ifp->name
327
0
           : "unknown";
328
0
}
329
330
/* Tie an interface address to its derived subnet list of addresses. */
331
int if_subnet_add(struct interface *ifp, struct connected *ifc)
332
0
{
333
0
  struct route_node *rn;
334
0
  struct zebra_if *zebra_if;
335
0
  struct prefix cp;
336
0
  struct list *addr_list;
337
338
0
  assert(ifp && ifp->info && ifc);
339
0
  zebra_if = ifp->info;
340
341
  /* Get address derived subnet node and associated address list, while
342
     marking
343
     address secondary attribute appropriately. */
344
0
  cp = *CONNECTED_PREFIX(ifc);
345
0
  apply_mask(&cp);
346
0
  rn = route_node_get(zebra_if->ipv4_subnets, &cp);
347
348
0
  if ((addr_list = rn->info))
349
0
    SET_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY);
350
0
  else {
351
0
    UNSET_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY);
352
0
    rn->info = addr_list = list_new();
353
0
    route_lock_node(rn);
354
0
  }
355
356
  /* Tie address at the tail of address list. */
357
0
  listnode_add(addr_list, ifc);
358
359
  /* Return list element count. */
360
0
  return (addr_list->count);
361
0
}
362
363
/* Untie an interface address from its derived subnet list of addresses. */
364
int if_subnet_delete(struct interface *ifp, struct connected *ifc)
365
0
{
366
0
  struct route_node *rn;
367
0
  struct zebra_if *zebra_if;
368
0
  struct list *addr_list;
369
0
  struct prefix cp;
370
371
0
  assert(ifp && ifp->info && ifc);
372
0
  zebra_if = ifp->info;
373
374
0
  cp = *CONNECTED_PREFIX(ifc);
375
0
  apply_mask(&cp);
376
377
  /* Get address derived subnet node. */
378
0
  rn = route_node_lookup(zebra_if->ipv4_subnets, &cp);
379
0
  if (!(rn && rn->info)) {
380
0
    flog_warn(EC_ZEBRA_REMOVE_ADDR_UNKNOWN_SUBNET,
381
0
        "Trying to remove an address from an unknown subnet. (please report this bug)");
382
0
    return -1;
383
0
  }
384
0
  route_unlock_node(rn);
385
386
  /* Untie address from subnet's address list. */
387
0
  addr_list = rn->info;
388
389
  /* Deleting an address that is not registered is a bug.
390
   * In any case, we shouldn't decrement the lock counter if the address
391
   * is unknown. */
392
0
  if (!listnode_lookup(addr_list, ifc)) {
393
0
    flog_warn(
394
0
      EC_ZEBRA_REMOVE_UNREGISTERED_ADDR,
395
0
      "Trying to remove an address from a subnet where it is not currently registered. (please report this bug)");
396
0
    return -1;
397
0
  }
398
399
0
  listnode_delete(addr_list, ifc);
400
0
  route_unlock_node(rn);
401
402
  /* Return list element count, if not empty. */
403
0
  if (addr_list->count) {
404
    /* If deleted address is primary, mark subsequent one as such
405
     * and distribute. */
406
0
    if (!CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)) {
407
0
      ifc = listgetdata(
408
0
        (struct listnode *)listhead(addr_list));
409
0
      zebra_interface_address_delete_update(ifp, ifc);
410
0
      UNSET_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY);
411
      /* XXX: Linux kernel removes all the secondary addresses
412
       * when the primary
413
       * address is removed. We could try to work around that,
414
       * though this is
415
       * non-trivial. */
416
0
      zebra_interface_address_add_update(ifp, ifc);
417
0
    }
418
419
0
    return addr_list->count;
420
0
  }
421
422
  /* Otherwise, free list and route node. */
423
0
  list_delete(&addr_list);
424
0
  rn->info = NULL;
425
0
  route_unlock_node(rn);
426
427
0
  return 0;
428
0
}
429
430
/* if_flags_mangle: A place for hacks that require mangling
431
 * or tweaking the interface flags.
432
 *
433
 * ******************** Solaris flags hacks **************************
434
 *
435
 * Solaris IFF_UP flag reflects only the primary interface as the
436
 * routing socket only sends IFINFO for the primary interface.  Hence
437
 * ~IFF_UP does not per se imply all the logical interfaces are also
438
 * down - which we only know of as addresses. Instead we must determine
439
 * whether the interface really is up or not according to how many
440
 * addresses are still attached. (Solaris always sends RTM_DELADDR if
441
 * an interface, logical or not, goes ~IFF_UP).
442
 *
443
 * Ie, we mangle IFF_UP to *additionally* reflect whether or not there
444
 * are addresses left in struct connected, not just the actual underlying
445
 * IFF_UP flag.
446
 *
447
 * We must hence remember the real state of IFF_UP, which we do in
448
 * struct zebra_if.primary_state.
449
 *
450
 * Setting IFF_UP within zebra to administratively shutdown the
451
 * interface will affect only the primary interface/address on Solaris.
452
 ************************End Solaris flags hacks ***********************
453
 */
454
static void if_flags_mangle(struct interface *ifp, uint64_t *newflags)
455
0
{
456
0
  return;
457
0
}
458
459
/* Update the flags field of the ifp with the new flag set provided.
460
 * Take whatever actions are required for any changes in flags we care
461
 * about.
462
 *
463
 * newflags should be the raw value, as obtained from the OS.
464
 */
465
void if_flags_update(struct interface *ifp, uint64_t newflags)
466
0
{
467
0
  if_flags_mangle(ifp, &newflags);
468
469
0
  if (if_is_no_ptm_operative(ifp)) {
470
    /* operative -> inoperative? */
471
0
    ifp->flags = newflags;
472
0
    if (!if_is_operative(ifp))
473
0
      if_down(ifp);
474
0
  } else {
475
    /* inoperative -> operative? */
476
0
    ifp->flags = newflags;
477
0
    if (if_is_operative(ifp))
478
0
      if_up(ifp, true);
479
0
  }
480
0
}
481
482
/* Wake up configured address if it is not in current kernel
483
   address. */
484
void if_addr_wakeup(struct interface *ifp)
485
0
{
486
0
  struct listnode *node, *nnode;
487
0
  struct connected *ifc;
488
0
  struct prefix *p;
489
0
  enum zebra_dplane_result dplane_res;
490
491
0
  for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, ifc)) {
492
0
    p = ifc->address;
493
494
0
    if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED)
495
0
        && !CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)) {
496
      /* Address check. */
497
0
      if (p->family == AF_INET) {
498
0
        if (!if_is_up(ifp)) {
499
          /* Assume zebra is configured like
500
           * following:
501
           *
502
           *   interface gre0
503
           *    ip addr 192.0.2.1/24
504
           *   !
505
           *
506
           * As soon as zebra becomes first aware
507
           * that gre0 exists in the
508
           * kernel, it will set gre0 up and
509
           * configure its addresses.
510
           *
511
           * (This may happen at startup when the
512
           * interface already exists
513
           * or during runtime when the interface
514
           * is added to the kernel)
515
           *
516
           * XXX: IRDP code is calling here via
517
           * if_add_update - this seems
518
           * somewhat weird.
519
           * XXX: RUNNING is not a settable flag
520
           * on any system
521
           * I (paulj) am aware of.
522
          */
523
0
          if_set_flags(ifp, IFF_UP | IFF_RUNNING);
524
0
          if_refresh(ifp);
525
0
        }
526
527
0
        dplane_res = dplane_intf_addr_set(ifp, ifc);
528
0
        if (dplane_res ==
529
0
            ZEBRA_DPLANE_REQUEST_FAILURE) {
530
0
          flog_err_sys(
531
0
            EC_ZEBRA_IFACE_ADDR_ADD_FAILED,
532
0
            "Can't set interface's address: %s",
533
0
            dplane_res2str(dplane_res));
534
0
          continue;
535
0
        }
536
537
0
        SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
538
        /* The address will be advertised to zebra
539
         * clients when the notification
540
         * from the kernel has been received.
541
         * It will also be added to the interface's
542
         * subnet list then. */
543
0
      }
544
0
      if (p->family == AF_INET6) {
545
0
        if (!if_is_up(ifp)) {
546
          /* See long comment above */
547
0
          if_set_flags(ifp, IFF_UP | IFF_RUNNING);
548
0
          if_refresh(ifp);
549
0
        }
550
551
552
0
        dplane_res = dplane_intf_addr_set(ifp, ifc);
553
0
        if (dplane_res ==
554
0
            ZEBRA_DPLANE_REQUEST_FAILURE) {
555
0
          flog_err_sys(
556
0
            EC_ZEBRA_IFACE_ADDR_ADD_FAILED,
557
0
            "Can't set interface's address: %s",
558
0
            dplane_res2str(dplane_res));
559
0
          continue;
560
0
        }
561
562
0
        SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
563
        /* The address will be advertised to zebra
564
         * clients when the notification
565
         * from the kernel has been received. */
566
0
      }
567
0
    }
568
0
  }
569
0
}
570
571
/* Handle interface addition */
572
void if_add_update(struct interface *ifp)
573
0
{
574
0
  struct zebra_if *if_data;
575
0
  struct zebra_ns *zns;
576
0
  struct zebra_vrf *zvrf = ifp->vrf->info;
577
578
  /* case interface populate before vrf enabled */
579
0
  if (zvrf->zns)
580
0
    zns = zvrf->zns;
581
0
  else
582
0
    zns = zebra_ns_lookup(NS_DEFAULT);
583
0
  if_link_per_ns(zns, ifp);
584
0
  if_data = ifp->info;
585
0
  assert(if_data);
586
587
0
  if (if_data->multicast == IF_ZEBRA_DATA_ON)
588
0
    if_set_flags(ifp, IFF_MULTICAST);
589
0
  else if (if_data->multicast == IF_ZEBRA_DATA_OFF)
590
0
    if_unset_flags(ifp, IFF_MULTICAST);
591
592
0
  zebra_ptm_if_set_ptm_state(ifp, if_data);
593
594
0
  zebra_interface_add_update(ifp);
595
596
0
  if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
597
0
    SET_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE);
598
599
0
    if (if_data->shutdown == IF_ZEBRA_DATA_ON) {
600
0
      if (IS_ZEBRA_DEBUG_KERNEL) {
601
0
        zlog_debug(
602
0
          "interface %s vrf %s(%u) index %d is shutdown. Won't wake it up.",
603
0
          ifp->name, ifp->vrf->name,
604
0
          ifp->vrf->vrf_id, ifp->ifindex);
605
0
      }
606
607
0
      return;
608
0
    }
609
610
0
    if_addr_wakeup(ifp);
611
612
0
    if (IS_ZEBRA_DEBUG_KERNEL)
613
0
      zlog_debug(
614
0
        "interface %s vrf %s(%u) index %d becomes active.",
615
0
        ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
616
0
        ifp->ifindex);
617
618
0
  } else {
619
0
    if (IS_ZEBRA_DEBUG_KERNEL)
620
0
      zlog_debug("interface %s vrf %s(%u) index %d is added.",
621
0
           ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
622
0
           ifp->ifindex);
623
0
  }
624
0
}
625
626
/* Install connected routes corresponding to an interface. */
627
static void if_install_connected(struct interface *ifp)
628
0
{
629
0
  struct listnode *node;
630
0
  struct listnode *next;
631
0
  struct connected *ifc;
632
633
0
  if (ifp->connected) {
634
0
    for (ALL_LIST_ELEMENTS(ifp->connected, node, next, ifc)) {
635
0
      if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
636
0
        zebra_interface_address_add_update(ifp, ifc);
637
638
0
      connected_up(ifp, ifc);
639
0
    }
640
0
  }
641
0
}
642
643
/* Uninstall connected routes corresponding to an interface. */
644
static void if_uninstall_connected(struct interface *ifp)
645
0
{
646
0
  struct listnode *node;
647
0
  struct listnode *next;
648
0
  struct connected *ifc;
649
650
0
  if (ifp->connected) {
651
0
    for (ALL_LIST_ELEMENTS(ifp->connected, node, next, ifc)) {
652
0
      zebra_interface_address_delete_update(ifp, ifc);
653
0
      connected_down(ifp, ifc);
654
0
    }
655
0
  }
656
0
}
657
658
/* Uninstall and delete connected routes corresponding to an interface. */
659
/* TODO - Check why IPv4 handling here is different from install or if_down */
660
static void if_delete_connected(struct interface *ifp)
661
0
{
662
0
  struct connected *ifc;
663
0
  struct prefix cp;
664
0
  struct route_node *rn;
665
0
  struct zebra_if *zebra_if;
666
0
  struct listnode *node;
667
0
  struct listnode *last = NULL;
668
669
0
  zebra_if = ifp->info;
670
671
0
  if (!ifp->connected)
672
0
    return;
673
674
0
  while ((node = (last ? last->next : listhead(ifp->connected)))) {
675
0
    ifc = listgetdata(node);
676
677
0
    cp = *CONNECTED_PREFIX(ifc);
678
0
    apply_mask(&cp);
679
680
0
    if (cp.family == AF_INET
681
0
        && (rn = route_node_lookup(zebra_if->ipv4_subnets, &cp))) {
682
0
      struct listnode *anode;
683
0
      struct listnode *next;
684
0
      struct listnode *first;
685
0
      struct list *addr_list;
686
687
0
      route_unlock_node(rn);
688
0
      addr_list = (struct list *)rn->info;
689
690
      /* Remove addresses, secondaries first. */
691
0
      first = listhead(addr_list);
692
0
      if (first)
693
0
        for (anode = first->next; anode || first;
694
0
             anode = next) {
695
0
          if (!anode) {
696
0
            anode = first;
697
0
            first = NULL;
698
0
          }
699
0
          next = anode->next;
700
701
0
          ifc = listgetdata(anode);
702
0
          connected_down(ifp, ifc);
703
704
          /* XXX: We have to send notifications
705
           * here explicitly, because we destroy
706
           * the ifc before receiving the
707
           * notification about the address being
708
           * deleted.
709
           */
710
0
          zebra_interface_address_delete_update(
711
0
            ifp, ifc);
712
713
0
          UNSET_FLAG(ifc->conf, ZEBRA_IFC_REAL);
714
0
          UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
715
716
          /* Remove from subnet chain. */
717
0
          list_delete_node(addr_list, anode);
718
0
          route_unlock_node(rn);
719
720
          /* Remove from interface address list
721
           * (unconditionally). */
722
0
          if (!CHECK_FLAG(ifc->conf,
723
0
              ZEBRA_IFC_CONFIGURED)) {
724
0
            listnode_delete(ifp->connected,
725
0
                ifc);
726
0
            connected_free(&ifc);
727
0
          } else
728
0
            last = node;
729
0
        }
730
731
      /* Free chain list and respective route node. */
732
0
      list_delete(&addr_list);
733
0
      rn->info = NULL;
734
0
      route_unlock_node(rn);
735
0
    } else if (cp.family == AF_INET6) {
736
0
      connected_down(ifp, ifc);
737
738
0
      zebra_interface_address_delete_update(ifp, ifc);
739
740
0
      UNSET_FLAG(ifc->conf, ZEBRA_IFC_REAL);
741
0
      UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
742
743
0
      if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
744
0
        last = node;
745
0
      else {
746
0
        listnode_delete(ifp->connected, ifc);
747
0
        connected_free(&ifc);
748
0
      }
749
0
    } else {
750
0
      last = node;
751
0
    }
752
0
  }
753
0
}
754
755
/* Handle an interface delete event */
756
void if_delete_update(struct interface **pifp)
757
0
{
758
0
  struct zebra_if *zif;
759
0
  struct interface *ifp = *pifp;
760
761
0
  if (if_is_up(ifp)) {
762
0
    flog_err(
763
0
      EC_LIB_INTERFACE,
764
0
      "interface %s vrf %s(%u) index %d is still up while being deleted.",
765
0
      ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
766
0
      ifp->ifindex);
767
0
    return;
768
0
  }
769
770
0
  if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE))
771
0
    return;
772
773
  /* Mark interface as inactive */
774
0
  UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE);
775
776
0
  if (IS_ZEBRA_DEBUG_KERNEL)
777
0
    zlog_debug("interface %s vrf %s(%u) index %d is now inactive.",
778
0
         ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
779
0
         ifp->ifindex);
780
781
  /* Delete connected routes from the kernel. */
782
0
  if_delete_connected(ifp);
783
784
  /* Send out notification on interface delete. */
785
0
  zebra_interface_delete_update(ifp);
786
787
0
  if_unlink_per_ns(ifp);
788
789
  /* Update ifindex after distributing the delete message.  This is in
790
     case any client needs to have the old value of ifindex available
791
     while processing the deletion.  Each client daemon is responsible
792
     for setting ifindex to IFINDEX_INTERNAL after processing the
793
     interface deletion message. */
794
0
  if_set_index(ifp, IFINDEX_INTERNAL);
795
0
  ifp->node = NULL;
796
797
  /* if the ifp is in a vrf, move it to default so vrf can be deleted if
798
   * desired. This operation is not done for netns implementation to avoid
799
   * collision with interface with the same name in the default vrf (can
800
   * occur with this implementation whereas it is not possible with
801
   * vrf-lite).
802
   */
803
0
  if (ifp->vrf->vrf_id && !vrf_is_backend_netns())
804
0
    if_handle_vrf_change(ifp, VRF_DEFAULT);
805
806
0
  UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK);
807
808
  /* Reset some zebra interface params to default values. */
809
0
  zif = ifp->info;
810
0
  if (zif) {
811
0
    zebra_evpn_if_cleanup(zif);
812
0
    zif->zif_type = ZEBRA_IF_OTHER;
813
0
    zif->zif_slave_type = ZEBRA_IF_SLAVE_NONE;
814
0
    memset(&zif->l2info, 0, sizeof(union zebra_l2if_info));
815
0
    memset(&zif->brslave_info, 0,
816
0
           sizeof(struct zebra_l2info_brslave));
817
0
    zebra_evpn_mac_ifp_del(ifp);
818
0
  }
819
820
0
  if (!ifp->configured) {
821
0
    if (IS_ZEBRA_DEBUG_KERNEL)
822
0
      zlog_debug("interface %s is being deleted from the system",
823
0
           ifp->name);
824
0
    if_delete(pifp);
825
0
  }
826
0
}
827
828
/* VRF change for an interface */
829
void if_handle_vrf_change(struct interface *ifp, vrf_id_t vrf_id)
830
0
{
831
0
  vrf_id_t old_vrf_id;
832
833
0
  old_vrf_id = ifp->vrf->vrf_id;
834
835
  /* Uninstall connected routes. */
836
0
  if_uninstall_connected(ifp);
837
838
  /* Delete any IPv4 neighbors created to implement RFC 5549 */
839
0
  if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(ifp);
840
841
  /* Delete all neighbor addresses learnt through IPv6 RA */
842
0
  if_down_del_nbr_connected(ifp);
843
844
  /* Send out notification on interface VRF change. */
845
  /* This is to issue an UPDATE or a DELETE, as appropriate. */
846
0
  zebra_interface_vrf_update_del(ifp, vrf_id);
847
848
0
  if (if_is_vrf(ifp))
849
0
    return;
850
851
  /* update VRF */
852
0
  if_update_to_new_vrf(ifp, vrf_id);
853
854
  /* Send out notification on interface VRF change. */
855
  /* This is to issue an ADD, if needed. */
856
0
  zebra_interface_vrf_update_add(ifp, old_vrf_id);
857
0
}
858
859
static void ipv6_ll_address_to_mac(struct in6_addr *address, uint8_t *mac)
860
0
{
861
0
  mac[0] = address->s6_addr[8] ^ 0x02;
862
0
  mac[1] = address->s6_addr[9];
863
0
  mac[2] = address->s6_addr[10];
864
0
  mac[3] = address->s6_addr[13];
865
0
  mac[4] = address->s6_addr[14];
866
0
  mac[5] = address->s6_addr[15];
867
0
}
868
869
void if_nbr_mac_to_ipv4ll_neigh_update(struct interface *ifp,
870
               char mac[6],
871
               struct in6_addr *address,
872
               int add)
873
0
{
874
0
  struct zebra_vrf *zvrf = ifp->vrf->info;
875
0
  struct zebra_if *zif = ifp->info;
876
0
  char buf[16] = "169.254.0.1";
877
0
  struct in_addr ipv4_ll;
878
0
  ns_id_t ns_id;
879
880
0
  inet_pton(AF_INET, buf, &ipv4_ll);
881
882
0
  ns_id = zvrf->zns->ns_id;
883
884
  /*
885
   * Remove and re-add any existing neighbor entry for this address,
886
   * since Netlink doesn't currently offer update message types.
887
   */
888
0
  kernel_neigh_update(0, ifp->ifindex, (void *)&ipv4_ll.s_addr, mac, 6,
889
0
          ns_id, AF_INET, true);
890
891
  /* Add new neighbor entry.
892
   *
893
   * We force installation even if current neighbor entry is the same.
894
   * Since this function is used to refresh our MAC entries after an
895
   * interface flap, if we don't force in our custom entries with their
896
   * state set to PERMANENT or REACHABLE then the kernel will attempt to
897
   * resolve our leftover entries, fail, mark them unreachable and then
898
   * they'll be useless to us.
899
   */
900
0
  if (add)
901
0
    kernel_neigh_update(add, ifp->ifindex, (void *)&ipv4_ll.s_addr,
902
0
            mac, 6, ns_id, AF_INET, true);
903
904
0
  memcpy(&zif->neigh_mac[0], &mac[0], 6);
905
906
  /*
907
   * We need to note whether or not we originated a v6
908
   * neighbor entry for this interface.  So that when
909
   * someone unwisely accidentally deletes this entry
910
   * we can shove it back in.
911
   */
912
0
  zif->v6_2_v4_ll_neigh_entry = !!add;
913
0
  memcpy(&zif->v6_2_v4_ll_addr6, address, sizeof(*address));
914
915
0
  zvrf->neigh_updates++;
916
0
}
917
918
void if_nbr_ipv6ll_to_ipv4ll_neigh_update(struct interface *ifp,
919
            struct in6_addr *address, int add)
920
0
{
921
922
0
  char mac[6];
923
924
0
  ipv6_ll_address_to_mac(address, (uint8_t *)mac);
925
0
  if_nbr_mac_to_ipv4ll_neigh_update(ifp, mac, address, add);
926
0
}
927
928
static void if_nbr_ipv6ll_to_ipv4ll_neigh_add_all(struct interface *ifp)
929
0
{
930
0
  if (listhead(ifp->nbr_connected)) {
931
0
    struct nbr_connected *nbr_connected;
932
0
    struct listnode *node;
933
934
0
    for (ALL_LIST_ELEMENTS_RO(ifp->nbr_connected, node,
935
0
            nbr_connected))
936
0
      if_nbr_ipv6ll_to_ipv4ll_neigh_update(
937
0
        ifp, &nbr_connected->address->u.prefix6, 1);
938
0
  }
939
0
}
940
941
void if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(struct interface *ifp)
942
0
{
943
0
  if (listhead(ifp->nbr_connected)) {
944
0
    struct nbr_connected *nbr_connected;
945
0
    struct listnode *node;
946
947
0
    for (ALL_LIST_ELEMENTS_RO(ifp->nbr_connected, node,
948
0
            nbr_connected))
949
0
      if_nbr_ipv6ll_to_ipv4ll_neigh_update(
950
0
        ifp, &nbr_connected->address->u.prefix6, 0);
951
0
  }
952
0
}
953
954
static void if_down_del_nbr_connected(struct interface *ifp)
955
0
{
956
0
  struct nbr_connected *nbr_connected;
957
0
  struct listnode *node, *nnode;
958
959
0
  for (ALL_LIST_ELEMENTS(ifp->nbr_connected, node, nnode,
960
0
             nbr_connected)) {
961
0
    listnode_delete(ifp->nbr_connected, nbr_connected);
962
0
    nbr_connected_free(nbr_connected);
963
0
  }
964
0
}
965
966
void if_nhg_dependents_add(struct interface *ifp, struct nhg_hash_entry *nhe)
967
0
{
968
0
  if (ifp->info) {
969
0
    struct zebra_if *zif = (struct zebra_if *)ifp->info;
970
971
0
    nhg_connected_tree_add_nhe(&zif->nhg_dependents, nhe);
972
0
  }
973
0
}
974
975
void if_nhg_dependents_del(struct interface *ifp, struct nhg_hash_entry *nhe)
976
0
{
977
0
  if (ifp->info) {
978
0
    struct zebra_if *zif = (struct zebra_if *)ifp->info;
979
980
0
    nhg_connected_tree_del_nhe(&zif->nhg_dependents, nhe);
981
0
  }
982
0
}
983
984
unsigned int if_nhg_dependents_count(const struct interface *ifp)
985
0
{
986
0
  if (ifp->info) {
987
0
    struct zebra_if *zif = (struct zebra_if *)ifp->info;
988
989
0
    return nhg_connected_tree_count(&zif->nhg_dependents);
990
0
  }
991
992
0
  return 0;
993
0
}
994
995
996
bool if_nhg_dependents_is_empty(const struct interface *ifp)
997
0
{
998
0
  if (ifp->info) {
999
0
    struct zebra_if *zif = (struct zebra_if *)ifp->info;
1000
1001
0
    return nhg_connected_tree_is_empty(&zif->nhg_dependents);
1002
0
  }
1003
1004
0
  return false;
1005
0
}
1006
1007
/* Interface is up. */
1008
void if_up(struct interface *ifp, bool install_connected)
1009
0
{
1010
0
  struct zebra_if *zif;
1011
0
  struct interface *link_if;
1012
1013
0
  zif = ifp->info;
1014
0
  zif->up_count++;
1015
0
  frr_timestamp(2, zif->up_last, sizeof(zif->up_last));
1016
1017
  /* Notify the protocol daemons. */
1018
0
  if (ifp->ptm_enable && (ifp->ptm_status == ZEBRA_PTM_STATUS_DOWN)) {
1019
0
    flog_warn(EC_ZEBRA_PTM_NOT_READY,
1020
0
        "%s: interface %s hasn't passed ptm check",
1021
0
        __func__, ifp->name);
1022
0
    return;
1023
0
  }
1024
0
  zebra_interface_up_update(ifp);
1025
1026
0
  if_nbr_ipv6ll_to_ipv4ll_neigh_add_all(ifp);
1027
1028
0
  rtadv_if_up(zif);
1029
1030
  /* Install connected routes to the kernel. */
1031
0
  if (install_connected)
1032
0
    if_install_connected(ifp);
1033
1034
  /* Handle interface up for specific types for EVPN. Non-VxLAN interfaces
1035
   * are checked to see if (remote) neighbor entries need to be installed
1036
   * on them for ARP suppression.
1037
   */
1038
0
  if (IS_ZEBRA_IF_VXLAN(ifp))
1039
0
    zebra_vxlan_if_up(ifp);
1040
0
  else if (IS_ZEBRA_IF_BRIDGE(ifp)) {
1041
0
    link_if = ifp;
1042
0
    zebra_vxlan_svi_up(ifp, link_if);
1043
0
  } else if (IS_ZEBRA_IF_VLAN(ifp)) {
1044
0
    link_if = zif->link;
1045
0
    if (link_if)
1046
0
      zebra_vxlan_svi_up(ifp, link_if);
1047
0
  } else if (IS_ZEBRA_IF_MACVLAN(ifp)) {
1048
0
    zebra_vxlan_macvlan_up(ifp);
1049
0
  }
1050
1051
0
  if (zif->es_info.es)
1052
0
    zebra_evpn_es_if_oper_state_change(zif, true /*up*/);
1053
1054
0
  if (zif->flags & ZIF_FLAG_EVPN_MH_UPLINK)
1055
0
    zebra_evpn_mh_uplink_oper_update(zif);
1056
1057
0
  event_add_timer(zrouter.master, if_zebra_speed_update, ifp, 0,
1058
0
      &zif->speed_update);
1059
0
  event_ignore_late_timer(zif->speed_update);
1060
0
}
1061
1062
/* Interface goes down.  We have to manage different behavior of based
1063
   OS. */
1064
void if_down(struct interface *ifp)
1065
0
{
1066
0
  struct zebra_if *zif;
1067
0
  struct interface *link_if;
1068
1069
0
  zif = ifp->info;
1070
0
  zif->down_count++;
1071
0
  frr_timestamp(2, zif->down_last, sizeof(zif->down_last));
1072
1073
0
  if_down_nhg_dependents(ifp);
1074
1075
  /* Handle interface down for specific types for EVPN. Non-VxLAN
1076
   * interfaces
1077
   * are checked to see if (remote) neighbor entries need to be purged
1078
   * for ARP suppression.
1079
   */
1080
0
  if (IS_ZEBRA_IF_VXLAN(ifp))
1081
0
    zebra_vxlan_if_down(ifp);
1082
0
  else if (IS_ZEBRA_IF_BRIDGE(ifp)) {
1083
0
    link_if = ifp;
1084
0
    zebra_vxlan_svi_down(ifp, link_if);
1085
0
  } else if (IS_ZEBRA_IF_VLAN(ifp)) {
1086
0
    link_if = zif->link;
1087
0
    if (link_if)
1088
0
      zebra_vxlan_svi_down(ifp, link_if);
1089
0
  } else if (IS_ZEBRA_IF_MACVLAN(ifp)) {
1090
0
    zebra_vxlan_macvlan_down(ifp);
1091
0
  }
1092
1093
0
  if (zif->es_info.es)
1094
0
    zebra_evpn_es_if_oper_state_change(zif, false /*up*/);
1095
1096
0
  if (zif->flags & ZIF_FLAG_EVPN_MH_UPLINK)
1097
0
    zebra_evpn_mh_uplink_oper_update(zif);
1098
1099
  /* Notify to the protocol daemons. */
1100
0
  zebra_interface_down_update(ifp);
1101
1102
  /* Uninstall connected routes from the kernel. */
1103
0
  if_uninstall_connected(ifp);
1104
1105
0
  if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(ifp);
1106
1107
  /* Delete all neighbor addresses learnt through IPv6 RA */
1108
0
  if_down_del_nbr_connected(ifp);
1109
0
}
1110
1111
void if_refresh(struct interface *ifp)
1112
0
{
1113
#ifndef GNU_LINUX
1114
  if_get_flags(ifp);
1115
#endif
1116
0
}
1117
1118
void zebra_if_update_link(struct interface *ifp, ifindex_t link_ifindex,
1119
        ns_id_t ns_id)
1120
0
{
1121
0
  struct zebra_if *zif;
1122
1123
0
  if (IS_ZEBRA_IF_VETH(ifp))
1124
0
    return;
1125
0
  zif = (struct zebra_if *)ifp->info;
1126
0
  zif->link_nsid = ns_id;
1127
0
  zif->link_ifindex = link_ifindex;
1128
0
  zif->link = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id),
1129
0
                link_ifindex);
1130
0
}
1131
1132
/*
1133
 * during initial link dump kernel does not order lower devices before
1134
 * upper devices so we need to fixup link dependencies at the end of dump
1135
 */
1136
void zebra_if_update_all_links(struct zebra_ns *zns)
1137
0
{
1138
0
  struct route_node *rn;
1139
0
  struct interface *ifp;
1140
0
  struct zebra_if *zif;
1141
1142
0
  if (IS_ZEBRA_DEBUG_KERNEL)
1143
0
    zlog_info("fixup link dependencies");
1144
1145
0
  for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
1146
0
    ifp = (struct interface *)rn->info;
1147
0
    if (!ifp)
1148
0
      continue;
1149
0
    zif = ifp->info;
1150
    /* update bond-member to bond linkages */
1151
0
    if ((IS_ZEBRA_IF_BOND_SLAVE(ifp))
1152
0
        && (zif->bondslave_info.bond_ifindex != IFINDEX_INTERNAL)
1153
0
        && !zif->bondslave_info.bond_if) {
1154
0
      if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_KERNEL)
1155
0
        zlog_debug("bond mbr %s map to bond %d",
1156
0
             zif->ifp->name,
1157
0
             zif->bondslave_info.bond_ifindex);
1158
0
      zebra_l2_map_slave_to_bond(zif, ifp->vrf->vrf_id);
1159
0
    }
1160
1161
    /* update SVI linkages */
1162
0
    if ((zif->link_ifindex != IFINDEX_INTERNAL) && !zif->link) {
1163
0
      zif->link = if_lookup_by_index_per_nsid(
1164
0
        zif->link_nsid, zif->link_ifindex);
1165
0
      if (IS_ZEBRA_DEBUG_KERNEL)
1166
0
        zlog_debug("interface %s/%d's lower fixup to %s/%d",
1167
0
            ifp->name, ifp->ifindex,
1168
0
            zif->link?zif->link->name:"unk",
1169
0
            zif->link_ifindex);
1170
0
    }
1171
1172
    /* Update VLAN<=>SVI map */
1173
0
    if (IS_ZEBRA_IF_VLAN(ifp))
1174
0
      zebra_evpn_acc_bd_svi_set(zif, NULL,
1175
0
              !!if_is_operative(ifp));
1176
0
  }
1177
0
}
1178
1179
static bool if_ignore_set_protodown(const struct interface *ifp, bool new_down,
1180
            uint32_t new_protodown_rc)
1181
0
{
1182
0
  struct zebra_if *zif;
1183
0
  bool old_down, old_set_down, old_unset_down;
1184
1185
0
  zif = ifp->info;
1186
1187
  /* Current state as we know it */
1188
0
  old_down = !!(ZEBRA_IF_IS_PROTODOWN(zif));
1189
0
  old_set_down = !!CHECK_FLAG(zif->flags, ZIF_FLAG_SET_PROTODOWN);
1190
0
  old_unset_down = !!CHECK_FLAG(zif->flags, ZIF_FLAG_UNSET_PROTODOWN);
1191
1192
0
  if (new_protodown_rc == zif->protodown_rc) {
1193
    /* Early return if already down & reason bitfield matches */
1194
0
    if (new_down == old_down) {
1195
0
      if (IS_ZEBRA_DEBUG_KERNEL)
1196
0
        zlog_debug(
1197
0
          "Ignoring request to set protodown %s for interface %s (%u): protodown %s is already set (reason bitfield: old 0x%x new 0x%x)",
1198
0
          new_down ? "on" : "off", ifp->name,
1199
0
          ifp->ifindex, new_down ? "on" : "off",
1200
0
          zif->protodown_rc, new_protodown_rc);
1201
1202
0
      return true;
1203
0
    }
1204
1205
    /* Early return if already set queued & reason bitfield matches
1206
     */
1207
0
    if (new_down && old_set_down) {
1208
0
      if (IS_ZEBRA_DEBUG_KERNEL)
1209
0
        zlog_debug(
1210
0
          "Ignoring request to set protodown %s for interface %s (%u): protodown %s is already queued to dplane (reason bitfield: old 0x%x new 0x%x)",
1211
0
          new_down ? "on" : "off", ifp->name,
1212
0
          ifp->ifindex, new_down ? "on" : "off",
1213
0
          zif->protodown_rc, new_protodown_rc);
1214
1215
0
      return true;
1216
0
    }
1217
1218
    /* Early return if already unset queued & reason bitfield
1219
     * matches */
1220
0
    if (!new_down && old_unset_down) {
1221
0
      if (IS_ZEBRA_DEBUG_KERNEL)
1222
0
        zlog_debug(
1223
0
          "Ignoring request to set protodown %s for interface %s (%u): protodown %s is already queued to dplane (reason bitfield: old 0x%x new 0x%x)",
1224
0
          new_down ? "on" : "off", ifp->name,
1225
0
          ifp->ifindex, new_down ? "on" : "off",
1226
0
          zif->protodown_rc, new_protodown_rc);
1227
1228
0
      return true;
1229
0
    }
1230
0
  }
1231
1232
0
  return false;
1233
0
}
1234
1235
int zebra_if_update_protodown_rc(struct interface *ifp, bool new_down,
1236
         uint32_t new_protodown_rc)
1237
0
{
1238
0
  struct zebra_if *zif;
1239
1240
0
  zif = ifp->info;
1241
1242
  /* Check if we already have this state or it's queued */
1243
0
  if (if_ignore_set_protodown(ifp, new_down, new_protodown_rc))
1244
0
    return 1;
1245
1246
0
  zlog_info(
1247
0
    "Setting protodown %s - interface %s (%u): reason bitfield change from 0x%x --> 0x%x",
1248
0
    new_down ? "on" : "off", ifp->name, ifp->ifindex,
1249
0
    zif->protodown_rc, new_protodown_rc);
1250
1251
0
  zif->protodown_rc = new_protodown_rc;
1252
1253
0
  if (new_down)
1254
0
    SET_FLAG(zif->flags, ZIF_FLAG_SET_PROTODOWN);
1255
0
  else
1256
0
    SET_FLAG(zif->flags, ZIF_FLAG_UNSET_PROTODOWN);
1257
1258
0
#ifdef HAVE_NETLINK
1259
0
  dplane_intf_update(ifp);
1260
#else
1261
  zlog_warn("Protodown is not supported on this platform");
1262
#endif
1263
0
  return 0;
1264
0
}
1265
1266
int zebra_if_set_protodown(struct interface *ifp, bool new_down,
1267
         enum protodown_reasons new_reason)
1268
0
{
1269
0
  struct zebra_if *zif;
1270
0
  uint32_t new_protodown_rc;
1271
1272
0
  zif = ifp->info;
1273
1274
0
  if (new_down)
1275
0
    new_protodown_rc = zif->protodown_rc | new_reason;
1276
0
  else
1277
0
    new_protodown_rc = zif->protodown_rc & ~new_reason;
1278
1279
0
  return zebra_if_update_protodown_rc(ifp, new_down, new_protodown_rc);
1280
0
}
1281
1282
/*
1283
 * Handle an interface events based on info in a dplane context object.
1284
 * This runs in the main pthread, using the info in the context object to
1285
 * modify an interface.
1286
 */
1287
static void zebra_if_addr_update_ctx(struct zebra_dplane_ctx *ctx,
1288
             struct interface *ifp)
1289
0
{
1290
0
  uint8_t flags = 0;
1291
0
  const char *label = NULL;
1292
0
  uint32_t metric = METRIC_MAX;
1293
0
  const struct prefix *addr, *dest = NULL;
1294
0
  enum dplane_op_e op;
1295
1296
0
  op = dplane_ctx_get_op(ctx);
1297
0
  addr = dplane_ctx_get_intf_addr(ctx);
1298
1299
0
  if (IS_ZEBRA_DEBUG_KERNEL)
1300
0
    zlog_debug("%s: %s: ifindex %s(%u), addr %pFX", __func__,
1301
0
         dplane_op2str(dplane_ctx_get_op(ctx)), ifp->name,
1302
0
         ifp->ifindex, addr);
1303
1304
  /* Is there a peer or broadcast address? */
1305
0
  dest = dplane_ctx_get_intf_dest(ctx);
1306
0
  if (dest->prefixlen == 0)
1307
0
    dest = NULL;
1308
1309
0
  if (dplane_ctx_intf_is_connected(ctx))
1310
0
    SET_FLAG(flags, ZEBRA_IFA_PEER);
1311
1312
  /* Flags. */
1313
0
  if (dplane_ctx_intf_is_secondary(ctx))
1314
0
    SET_FLAG(flags, ZEBRA_IFA_SECONDARY);
1315
1316
  /* Label? */
1317
0
  if (dplane_ctx_intf_has_label(ctx))
1318
0
    label = dplane_ctx_get_intf_label(ctx);
1319
1320
0
  if (label && strcmp(ifp->name, label) == 0)
1321
0
    label = NULL;
1322
1323
0
  metric = dplane_ctx_get_intf_metric(ctx);
1324
1325
  /* Register interface address to the interface. */
1326
0
  if (addr->family == AF_INET) {
1327
0
    if (op == DPLANE_OP_INTF_ADDR_ADD)
1328
0
      connected_add_ipv4(
1329
0
        ifp, flags, &addr->u.prefix4, addr->prefixlen,
1330
0
        dest ? &dest->u.prefix4 : NULL, label, metric);
1331
0
    else if (CHECK_FLAG(flags, ZEBRA_IFA_PEER)) {
1332
      /* Delete with a peer address */
1333
0
      connected_delete_ipv4(ifp, flags, &addr->u.prefix4,
1334
0
                addr->prefixlen,
1335
0
                &dest->u.prefix4);
1336
0
    } else
1337
0
      connected_delete_ipv4(ifp, flags, &addr->u.prefix4,
1338
0
                addr->prefixlen, NULL);
1339
0
  }
1340
1341
0
  if (addr->family == AF_INET6) {
1342
0
    if (op == DPLANE_OP_INTF_ADDR_ADD) {
1343
0
      connected_add_ipv6(ifp, flags, &addr->u.prefix6,
1344
0
             dest ? &dest->u.prefix6 : NULL,
1345
0
             addr->prefixlen, label, metric);
1346
0
    } else
1347
0
      connected_delete_ipv6(ifp, &addr->u.prefix6, NULL,
1348
0
                addr->prefixlen);
1349
0
  }
1350
1351
  /*
1352
   * Linux kernel does not send route delete on interface down/addr del
1353
   * so we have to re-process routes it owns (i.e. kernel routes)
1354
   */
1355
0
  if (op != DPLANE_OP_INTF_ADDR_ADD)
1356
0
    rib_update(RIB_UPDATE_KERNEL);
1357
0
}
1358
1359
static void zebra_if_update_ctx(struct zebra_dplane_ctx *ctx,
1360
        struct interface *ifp)
1361
0
{
1362
0
  enum zebra_dplane_result dp_res;
1363
0
  struct zebra_if *zif;
1364
0
  bool pd_reason_val;
1365
0
  bool down;
1366
1367
0
  dp_res = dplane_ctx_get_status(ctx);
1368
0
  pd_reason_val = dplane_ctx_get_intf_pd_reason_val(ctx);
1369
0
  down = dplane_ctx_intf_is_protodown(ctx);
1370
1371
0
  if (IS_ZEBRA_DEBUG_KERNEL)
1372
0
    zlog_debug("%s: %s: if %s(%u) ctx-protodown %s ctx-reason %d",
1373
0
         __func__, dplane_op2str(dplane_ctx_get_op(ctx)),
1374
0
         ifp->name, ifp->ifindex, down ? "on" : "off",
1375
0
         pd_reason_val);
1376
1377
0
  zif = ifp->info;
1378
0
  if (!zif) {
1379
0
    if (IS_ZEBRA_DEBUG_KERNEL)
1380
0
      zlog_debug("%s: if %s(%u) zebra info pointer is NULL",
1381
0
           __func__, ifp->name, ifp->ifindex);
1382
0
    return;
1383
0
  }
1384
1385
0
  if (dp_res != ZEBRA_DPLANE_REQUEST_SUCCESS) {
1386
0
    if (IS_ZEBRA_DEBUG_KERNEL)
1387
0
      zlog_debug("%s: if %s(%u) dplane update failed",
1388
0
           __func__, ifp->name, ifp->ifindex);
1389
0
    goto done;
1390
0
  }
1391
1392
  /* Update our info */
1393
0
  COND_FLAG(zif->flags, ZIF_FLAG_PROTODOWN, down);
1394
1395
0
done:
1396
  /* Clear our dplane flags */
1397
0
  UNSET_FLAG(zif->flags, ZIF_FLAG_SET_PROTODOWN);
1398
0
  UNSET_FLAG(zif->flags, ZIF_FLAG_UNSET_PROTODOWN);
1399
0
}
1400
1401
/*
1402
 * Handle netconf change from a dplane context object; runs in the main
1403
 * pthread so it can update zebra data structs.
1404
 */
1405
static void zebra_if_netconf_update_ctx(struct zebra_dplane_ctx *ctx,
1406
          struct interface *ifp,
1407
          ifindex_t ifindex)
1408
0
{
1409
0
  struct zebra_if *zif = NULL;
1410
0
  afi_t afi;
1411
0
  enum dplane_netconf_status_e mpls, mcast_on, linkdown;
1412
0
  bool *mcast_set, *linkdown_set;
1413
1414
0
  afi = dplane_ctx_get_afi(ctx);
1415
0
  mpls = dplane_ctx_get_netconf_mpls(ctx);
1416
0
  linkdown = dplane_ctx_get_netconf_linkdown(ctx);
1417
0
  mcast_on = dplane_ctx_get_netconf_mcast(ctx);
1418
1419
0
  if (ifindex == DPLANE_NETCONF_IFINDEX_ALL) {
1420
0
    if (afi == AFI_IP) {
1421
0
      mcast_set = &zrouter.all_mc_forwardingv4;
1422
0
      linkdown_set = &zrouter.all_linkdownv4;
1423
0
    } else {
1424
0
      mcast_set = &zrouter.all_mc_forwardingv6;
1425
0
      linkdown_set = &zrouter.all_linkdownv6;
1426
0
    }
1427
0
  } else if (ifindex == DPLANE_NETCONF_IFINDEX_DEFAULT) {
1428
0
    if (afi == AFI_IP) {
1429
0
      mcast_set = &zrouter.default_mc_forwardingv4;
1430
0
      linkdown_set = &zrouter.default_linkdownv4;
1431
0
    } else {
1432
0
      mcast_set = &zrouter.default_mc_forwardingv6;
1433
0
      linkdown_set = &zrouter.default_linkdownv6;
1434
0
    }
1435
0
  } else {
1436
0
    zif = ifp ? ifp->info : NULL;
1437
0
    if (!zif) {
1438
0
      if (IS_ZEBRA_DEBUG_KERNEL)
1439
0
        zlog_debug(
1440
0
          "%s: if %s(%u) zebra info pointer is NULL",
1441
0
          __func__, ifp ? ifp->name : "(null)",
1442
0
          ifp ? ifp->ifindex : ifindex);
1443
0
      return;
1444
0
    }
1445
0
    if (afi == AFI_IP) {
1446
0
      mcast_set = &zif->v4mcast_on;
1447
0
      linkdown_set = &zif->linkdown;
1448
0
    } else {
1449
0
      mcast_set = &zif->v6mcast_on;
1450
0
      linkdown_set = &zif->linkdownv6;
1451
0
    }
1452
1453
    /*
1454
     * mpls netconf data is neither v4 or v6 it's AF_MPLS!
1455
     */
1456
0
    if (mpls == DPLANE_NETCONF_STATUS_ENABLED) {
1457
0
      zif->mpls = true;
1458
0
      zebra_mpls_turned_on();
1459
0
    } else if (mpls == DPLANE_NETCONF_STATUS_DISABLED)
1460
0
      zif->mpls = false;
1461
0
  }
1462
1463
0
  if (linkdown == DPLANE_NETCONF_STATUS_ENABLED)
1464
0
    *linkdown_set = true;
1465
0
  else if (linkdown == DPLANE_NETCONF_STATUS_DISABLED)
1466
0
    *linkdown_set = false;
1467
1468
0
  if (mcast_on == DPLANE_NETCONF_STATUS_ENABLED)
1469
0
    *mcast_set = true;
1470
0
  else if (mcast_on == DPLANE_NETCONF_STATUS_DISABLED)
1471
0
    *mcast_set = false;
1472
1473
0
  if (IS_ZEBRA_DEBUG_KERNEL)
1474
0
    zlog_debug(
1475
0
      "%s: afi: %d if %s, ifindex %d, mpls %s mc_forwarding: %s linkdown %s",
1476
0
      __func__, afi, ifp ? ifp->name : "Global",
1477
0
      ifp ? ifp->ifindex : ifindex,
1478
0
      (zif ? (zif->mpls ? "ON" : "OFF") : "OFF"),
1479
0
      (*mcast_set ? "ON" : "OFF"),
1480
0
      (*linkdown_set ? "ON" : "OFF"));
1481
0
}
1482
1483
void zebra_if_dplane_result(struct zebra_dplane_ctx *ctx)
1484
0
{
1485
0
  struct zebra_ns *zns;
1486
0
  struct interface *ifp;
1487
0
  ns_id_t ns_id;
1488
0
  enum dplane_op_e op;
1489
0
  enum zebra_dplane_result dp_res;
1490
0
  ifindex_t ifindex;
1491
1492
0
  ns_id = dplane_ctx_get_ns_id(ctx);
1493
0
  dp_res = dplane_ctx_get_status(ctx);
1494
0
  op = dplane_ctx_get_op(ctx);
1495
0
  ifindex = dplane_ctx_get_ifindex(ctx);
1496
1497
0
  if (IS_ZEBRA_DEBUG_DPLANE_DETAIL || IS_ZEBRA_DEBUG_KERNEL)
1498
0
    zlog_debug("Intf dplane ctx %p, op %s, ifindex (%u), result %s",
1499
0
         ctx, dplane_op2str(op), ifindex,
1500
0
         dplane_res2str(dp_res));
1501
1502
0
  zns = zebra_ns_lookup(ns_id);
1503
0
  if (zns == NULL) {
1504
    /* No ns - deleted maybe? */
1505
0
    if (IS_ZEBRA_DEBUG_KERNEL)
1506
0
      zlog_debug("%s: can't find zns id %u", __func__, ns_id);
1507
1508
0
    return;
1509
0
  }
1510
1511
0
  ifp = if_lookup_by_index_per_ns(zns, ifindex);
1512
0
  if (ifp == NULL) {
1513
0
    if (op != DPLANE_OP_INTF_NETCONFIG ||
1514
0
        (ifindex != -1 && ifindex != -2)) {
1515
0
      if (IS_ZEBRA_DEBUG_KERNEL)
1516
0
        zlog_debug(
1517
0
          "%s: can't find ifp at nsid %u index %d",
1518
0
          __func__, ns_id, ifindex);
1519
1520
0
      return;
1521
0
    }
1522
0
  }
1523
1524
0
  switch (op) {
1525
0
  case DPLANE_OP_INTF_ADDR_ADD:
1526
0
  case DPLANE_OP_INTF_ADDR_DEL:
1527
0
    zebra_if_addr_update_ctx(ctx, ifp);
1528
0
    break;
1529
1530
0
  case DPLANE_OP_INTF_INSTALL:
1531
0
  case DPLANE_OP_INTF_UPDATE:
1532
0
  case DPLANE_OP_INTF_DELETE:
1533
0
    zebra_if_update_ctx(ctx, ifp);
1534
0
    break;
1535
1536
0
  case DPLANE_OP_INTF_NETCONFIG:
1537
0
    zebra_if_netconf_update_ctx(ctx, ifp, ifindex);
1538
0
    break;
1539
1540
0
  case DPLANE_OP_ROUTE_INSTALL:
1541
0
  case DPLANE_OP_ROUTE_UPDATE:
1542
0
  case DPLANE_OP_ROUTE_DELETE:
1543
0
  case DPLANE_OP_NH_DELETE:
1544
0
  case DPLANE_OP_NH_INSTALL:
1545
0
  case DPLANE_OP_NH_UPDATE:
1546
0
  case DPLANE_OP_ROUTE_NOTIFY:
1547
0
  case DPLANE_OP_LSP_INSTALL:
1548
0
  case DPLANE_OP_LSP_UPDATE:
1549
0
  case DPLANE_OP_LSP_DELETE:
1550
0
  case DPLANE_OP_LSP_NOTIFY:
1551
0
  case DPLANE_OP_PW_INSTALL:
1552
0
  case DPLANE_OP_PW_UNINSTALL:
1553
0
  case DPLANE_OP_SYS_ROUTE_ADD:
1554
0
  case DPLANE_OP_SYS_ROUTE_DELETE:
1555
0
  case DPLANE_OP_ADDR_INSTALL:
1556
0
  case DPLANE_OP_ADDR_UNINSTALL:
1557
0
  case DPLANE_OP_MAC_INSTALL:
1558
0
  case DPLANE_OP_MAC_DELETE:
1559
0
  case DPLANE_OP_NEIGH_INSTALL:
1560
0
  case DPLANE_OP_NEIGH_UPDATE:
1561
0
  case DPLANE_OP_NEIGH_DELETE:
1562
0
  case DPLANE_OP_NEIGH_IP_INSTALL:
1563
0
  case DPLANE_OP_NEIGH_IP_DELETE:
1564
0
  case DPLANE_OP_VTEP_ADD:
1565
0
  case DPLANE_OP_VTEP_DELETE:
1566
0
  case DPLANE_OP_RULE_ADD:
1567
0
  case DPLANE_OP_RULE_DELETE:
1568
0
  case DPLANE_OP_RULE_UPDATE:
1569
0
  case DPLANE_OP_NEIGH_DISCOVER:
1570
0
  case DPLANE_OP_BR_PORT_UPDATE:
1571
0
  case DPLANE_OP_NONE:
1572
0
  case DPLANE_OP_IPTABLE_ADD:
1573
0
  case DPLANE_OP_IPTABLE_DELETE:
1574
0
  case DPLANE_OP_IPSET_ADD:
1575
0
  case DPLANE_OP_IPSET_DELETE:
1576
0
  case DPLANE_OP_IPSET_ENTRY_ADD:
1577
0
  case DPLANE_OP_IPSET_ENTRY_DELETE:
1578
0
  case DPLANE_OP_NEIGH_TABLE_UPDATE:
1579
0
  case DPLANE_OP_GRE_SET:
1580
0
  case DPLANE_OP_TC_QDISC_INSTALL:
1581
0
  case DPLANE_OP_TC_QDISC_UNINSTALL:
1582
0
  case DPLANE_OP_TC_CLASS_ADD:
1583
0
  case DPLANE_OP_TC_CLASS_DELETE:
1584
0
  case DPLANE_OP_TC_CLASS_UPDATE:
1585
0
  case DPLANE_OP_TC_FILTER_ADD:
1586
0
  case DPLANE_OP_TC_FILTER_DELETE:
1587
0
  case DPLANE_OP_TC_FILTER_UPDATE:
1588
0
    break; /* should never hit here */
1589
0
  }
1590
0
}
1591
1592
/* Dump if address information to vty. */
1593
static void connected_dump_vty(struct vty *vty, json_object *json,
1594
             struct connected *connected)
1595
0
{
1596
0
  struct prefix *p;
1597
0
  json_object *json_addr = NULL;
1598
1599
  /* Print interface address. */
1600
0
  p = connected->address;
1601
1602
0
  if (json) {
1603
0
    json_addr = json_object_new_object();
1604
0
    json_object_array_add(json, json_addr);
1605
0
    json_object_string_addf(json_addr, "address", "%pFX", p);
1606
0
  } else {
1607
0
    vty_out(vty, "  %s %pFX", prefix_family_str(p), p);
1608
0
  }
1609
1610
  /* If there is destination address, print it. */
1611
0
  if (CONNECTED_PEER(connected) && connected->destination) {
1612
0
    if (json) {
1613
0
      json_object_string_addf(json_addr, "peer", "%pFX",
1614
0
            connected->destination);
1615
0
    } else {
1616
0
      vty_out(vty, " peer %pFX", connected->destination);
1617
0
    }
1618
0
  }
1619
1620
0
  if (json)
1621
0
    json_object_boolean_add(
1622
0
      json_addr, "secondary",
1623
0
      CHECK_FLAG(connected->flags, ZEBRA_IFA_SECONDARY));
1624
0
  else if (CHECK_FLAG(connected->flags, ZEBRA_IFA_SECONDARY))
1625
0
    vty_out(vty, " secondary");
1626
1627
0
  if (json)
1628
0
    json_object_boolean_add(
1629
0
      json_addr, "unnumbered",
1630
0
      CHECK_FLAG(connected->flags, ZEBRA_IFA_UNNUMBERED));
1631
0
  else if (CHECK_FLAG(connected->flags, ZEBRA_IFA_UNNUMBERED))
1632
0
    vty_out(vty, " unnumbered");
1633
1634
0
  if (connected->label) {
1635
0
    if (json)
1636
0
      json_object_string_add(json_addr, "label",
1637
0
                 connected->label);
1638
0
    else
1639
0
      vty_out(vty, " %s", connected->label);
1640
0
  }
1641
1642
0
  if (!json)
1643
0
    vty_out(vty, "\n");
1644
0
}
1645
1646
/* Dump interface neighbor address information to vty. */
1647
static void nbr_connected_dump_vty(struct vty *vty, json_object *json,
1648
           struct nbr_connected *connected)
1649
0
{
1650
0
  struct prefix *p;
1651
0
  char buf[PREFIX2STR_BUFFER];
1652
1653
  /* Print interface address. */
1654
0
  p = connected->address;
1655
0
  if (json)
1656
0
    json_array_string_add(json, prefix2str(p, buf, sizeof(buf)));
1657
0
  else
1658
0
    vty_out(vty, "  %s %pFX\n", prefix_family_str(p), p);
1659
0
}
1660
1661
static const char *
1662
zebra_zifslavetype_2str(enum zebra_slave_iftype zif_slave_type)
1663
0
{
1664
0
  switch (zif_slave_type) {
1665
0
  case ZEBRA_IF_SLAVE_BRIDGE:
1666
0
    return "Bridge";
1667
0
  case ZEBRA_IF_SLAVE_VRF:
1668
0
    return "Vrf";
1669
0
  case ZEBRA_IF_SLAVE_BOND:
1670
0
    return "Bond";
1671
0
  case ZEBRA_IF_SLAVE_OTHER:
1672
0
    return "Other";
1673
0
  case ZEBRA_IF_SLAVE_NONE:
1674
0
    return "None";
1675
0
  }
1676
0
  return "None";
1677
0
}
1678
1679
static const char *zebra_ziftype_2str(enum zebra_iftype zif_type)
1680
0
{
1681
0
  switch (zif_type) {
1682
0
  case ZEBRA_IF_OTHER:
1683
0
    return "Other";
1684
1685
0
  case ZEBRA_IF_BRIDGE:
1686
0
    return "Bridge";
1687
1688
0
  case ZEBRA_IF_VLAN:
1689
0
    return "Vlan";
1690
1691
0
  case ZEBRA_IF_VXLAN:
1692
0
    return "Vxlan";
1693
1694
0
  case ZEBRA_IF_VRF:
1695
0
    return "VRF";
1696
1697
0
  case ZEBRA_IF_VETH:
1698
0
    return "VETH";
1699
1700
0
  case ZEBRA_IF_BOND:
1701
0
    return "bond";
1702
1703
0
  case ZEBRA_IF_BOND_SLAVE:
1704
0
    return "bond_slave";
1705
1706
0
  case ZEBRA_IF_MACVLAN:
1707
0
    return "macvlan";
1708
1709
0
  case ZEBRA_IF_GRE:
1710
0
    return "GRE";
1711
1712
0
  default:
1713
0
    return "Unknown";
1714
0
  }
1715
0
}
1716
1717
/* Interface's brief information print out to vty interface. */
1718
static void ifs_dump_brief_vty(struct vty *vty, struct vrf *vrf)
1719
0
{
1720
0
  struct connected *connected;
1721
0
  struct listnode *node;
1722
0
  struct route_node *rn;
1723
0
  struct zebra_if *zebra_if;
1724
0
  struct prefix *p;
1725
0
  struct interface *ifp;
1726
0
  bool print_header = true;
1727
1728
0
  FOR_ALL_INTERFACES (vrf, ifp) {
1729
0
    bool first_pfx_printed = false;
1730
1731
0
    if (print_header) {
1732
0
      vty_out(vty, "%-16s%-8s%-16s%s\n", "Interface",
1733
0
        "Status", "VRF", "Addresses");
1734
0
      vty_out(vty, "%-16s%-8s%-16s%s\n", "---------",
1735
0
        "------", "---", "---------");
1736
0
      print_header = false; /* We have at least 1 iface */
1737
0
    }
1738
0
    zebra_if = ifp->info;
1739
1740
0
    vty_out(vty, "%-16s", ifp->name);
1741
1742
0
    if (if_is_up(ifp))
1743
0
      vty_out(vty, "%-8s", "up");
1744
0
    else
1745
0
      vty_out(vty, "%-8s", "down");
1746
1747
0
    vty_out(vty, "%-16s", vrf->name);
1748
1749
0
    for (rn = route_top(zebra_if->ipv4_subnets); rn;
1750
0
         rn = route_next(rn)) {
1751
0
      if (!rn->info)
1752
0
        continue;
1753
0
      uint32_t list_size = listcount((struct list *)rn->info);
1754
1755
0
      for (ALL_LIST_ELEMENTS_RO((struct list *)rn->info, node,
1756
0
              connected)) {
1757
0
        if (!CHECK_FLAG(connected->flags,
1758
0
            ZEBRA_IFA_SECONDARY)) {
1759
0
          p = connected->address;
1760
0
          if (first_pfx_printed) {
1761
            /* padding to prepare row only
1762
             * for ip addr */
1763
0
            vty_out(vty, "%-40s", "");
1764
0
            if (list_size > 1)
1765
0
              vty_out(vty, "+ ");
1766
0
            vty_out(vty, "%pFX\n", p);
1767
0
          } else {
1768
0
            if (list_size > 1)
1769
0
              vty_out(vty, "+ ");
1770
0
            vty_out(vty, "%pFX\n", p);
1771
0
          }
1772
0
          first_pfx_printed = true;
1773
0
          break;
1774
0
        }
1775
0
      }
1776
0
    }
1777
1778
0
    uint32_t v6_list_size = 0;
1779
0
    for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) {
1780
0
      if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL)
1781
0
        && (connected->address->family == AF_INET6))
1782
0
        v6_list_size++;
1783
0
    }
1784
0
    for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) {
1785
0
      if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL)
1786
0
          && !CHECK_FLAG(connected->flags,
1787
0
             ZEBRA_IFA_SECONDARY)
1788
0
          && (connected->address->family == AF_INET6)) {
1789
0
        p = connected->address;
1790
        /* Don't print link local pfx */
1791
0
        if (!IN6_IS_ADDR_LINKLOCAL(&p->u.prefix6)) {
1792
0
          if (first_pfx_printed) {
1793
            /* padding to prepare row only
1794
             * for ip addr */
1795
0
            vty_out(vty, "%-40s", "");
1796
0
            if (v6_list_size > 1)
1797
0
              vty_out(vty, "+ ");
1798
0
            vty_out(vty, "%pFX\n", p);
1799
0
          } else {
1800
0
            if (v6_list_size > 1)
1801
0
              vty_out(vty, "+ ");
1802
0
            vty_out(vty, "%pFX\n", p);
1803
0
          }
1804
0
          first_pfx_printed = true;
1805
0
          break;
1806
0
        }
1807
0
      }
1808
0
    }
1809
0
    if (!first_pfx_printed)
1810
0
      vty_out(vty, "\n");
1811
0
  }
1812
0
  vty_out(vty, "\n");
1813
0
}
1814
1815
static void ifs_dump_brief_vty_json(json_object *json, struct vrf *vrf)
1816
0
{
1817
0
  struct connected *connected;
1818
0
  struct listnode *node;
1819
0
  struct interface *ifp;
1820
1821
0
  FOR_ALL_INTERFACES (vrf, ifp) {
1822
0
    json_object *json_if;
1823
0
    json_object *json_addrs;
1824
1825
0
    json_if = json_object_new_object();
1826
0
    json_object_object_add(json, ifp->name, json_if);
1827
1828
0
    json_object_string_add(json_if, "status",
1829
0
               if_is_up(ifp) ? "up" : "down");
1830
0
    json_object_string_add(json_if, "vrfName", vrf->name);
1831
1832
0
    json_addrs = json_object_new_array();
1833
0
    json_object_object_add(json_if, "addresses", json_addrs);
1834
0
    for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) {
1835
0
      if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL)
1836
0
          && !CHECK_FLAG(connected->flags,
1837
0
             ZEBRA_IFA_SECONDARY)
1838
0
          && !(connected->address->family == AF_INET6
1839
0
         && IN6_IS_ADDR_LINKLOCAL(
1840
0
           &connected->address->u.prefix6))) {
1841
0
        char buf[PREFIX2STR_BUFFER];
1842
1843
0
        json_array_string_add(
1844
0
          json_addrs,
1845
0
          prefix2str(connected->address, buf,
1846
0
               sizeof(buf)));
1847
0
      }
1848
0
    }
1849
0
  }
1850
0
}
1851
1852
const char *zebra_protodown_rc_str(uint32_t protodown_rc, char *pd_buf,
1853
           uint32_t pd_buf_len)
1854
0
{
1855
0
  pd_buf[0] = '\0';
1856
0
  size_t len;
1857
1858
0
  strlcat(pd_buf, "(", pd_buf_len);
1859
1860
0
  if (CHECK_FLAG(protodown_rc, ZEBRA_PROTODOWN_EXTERNAL))
1861
0
    strlcat(pd_buf, "external,", pd_buf_len);
1862
1863
0
  if (CHECK_FLAG(protodown_rc, ZEBRA_PROTODOWN_EVPN_STARTUP_DELAY))
1864
0
    strlcat(pd_buf, "startup-delay,", pd_buf_len);
1865
1866
0
  if (CHECK_FLAG(protodown_rc, ZEBRA_PROTODOWN_EVPN_UPLINK_DOWN))
1867
0
    strlcat(pd_buf, "uplinks-down,", pd_buf_len);
1868
1869
0
  if (CHECK_FLAG(protodown_rc, ZEBRA_PROTODOWN_VRRP))
1870
0
    strlcat(pd_buf, "vrrp,", pd_buf_len);
1871
1872
0
  if (CHECK_FLAG(protodown_rc, ZEBRA_PROTODOWN_SHARP))
1873
0
    strlcat(pd_buf, "sharp,", pd_buf_len);
1874
1875
0
  len = strnlen(pd_buf, pd_buf_len);
1876
1877
  /* Remove trailing comma */
1878
0
  if (pd_buf[len - 1] == ',')
1879
0
    pd_buf[len - 1] = '\0';
1880
1881
0
  strlcat(pd_buf, ")", pd_buf_len);
1882
1883
0
  return pd_buf;
1884
0
}
1885
1886
static inline bool if_is_protodown_applicable(struct interface *ifp)
1887
0
{
1888
0
  if (IS_ZEBRA_IF_BOND(ifp))
1889
0
    return false;
1890
1891
0
  return true;
1892
0
}
1893
1894
static void zebra_vxlan_if_vni_dump_vty(struct vty *vty,
1895
          struct zebra_vxlan_vni *vni)
1896
0
{
1897
0
  char str[INET6_ADDRSTRLEN];
1898
1899
0
  vty_out(vty, "  VxLAN Id %u", vni->vni);
1900
0
  if (vni->access_vlan)
1901
0
    vty_out(vty, " Access VLAN Id %u\n", vni->access_vlan);
1902
1903
0
  if (vni->mcast_grp.s_addr != INADDR_ANY)
1904
0
    vty_out(vty, "  Mcast Group %s",
1905
0
      inet_ntop(AF_INET, &vni->mcast_grp, str, sizeof(str)));
1906
0
}
1907
1908
static void zebra_vxlan_if_vni_hash_dump_vty(struct hash_bucket *bucket,
1909
               void *ctxt)
1910
0
{
1911
0
  struct vty *vty;
1912
0
  struct zebra_vxlan_vni *vni;
1913
1914
0
  vni = (struct zebra_vxlan_vni *)bucket->data;
1915
0
  vty = (struct vty *)ctxt;
1916
1917
0
  zebra_vxlan_if_vni_dump_vty(vty, vni);
1918
0
}
1919
1920
static void zebra_vxlan_if_dump_vty(struct vty *vty, struct zebra_if *zebra_if)
1921
0
{
1922
0
  struct zebra_l2info_vxlan *vxlan_info;
1923
0
  struct zebra_vxlan_vni_info *vni_info;
1924
1925
0
  vxlan_info = &zebra_if->l2info.vxl;
1926
0
  vni_info = &vxlan_info->vni_info;
1927
1928
0
  if (vxlan_info->vtep_ip.s_addr != INADDR_ANY)
1929
0
    vty_out(vty, " VTEP IP: %pI4", &vxlan_info->vtep_ip);
1930
1931
0
  if (vxlan_info->ifindex_link && (vxlan_info->link_nsid != NS_UNKNOWN)) {
1932
0
    struct interface *ifp;
1933
1934
0
    ifp = if_lookup_by_index_per_ns(
1935
0
      zebra_ns_lookup(vxlan_info->link_nsid),
1936
0
      vxlan_info->ifindex_link);
1937
0
    vty_out(vty, " Link Interface %s",
1938
0
      ifp == NULL ? "Unknown" : ifp->name);
1939
0
  }
1940
1941
0
  if (IS_ZEBRA_VXLAN_IF_VNI(zebra_if)) {
1942
0
    zebra_vxlan_if_vni_dump_vty(vty, &vni_info->vni);
1943
0
  } else {
1944
0
    hash_iterate(vni_info->vni_table,
1945
0
           zebra_vxlan_if_vni_hash_dump_vty, vty);
1946
0
  }
1947
1948
0
  vty_out(vty, "\n");
1949
0
}
1950
1951
/* Interface's information print out to vty interface. */
1952
static void if_dump_vty(struct vty *vty, struct interface *ifp)
1953
0
{
1954
0
  struct connected *connected;
1955
0
  struct nbr_connected *nbr_connected;
1956
0
  struct listnode *node;
1957
0
  struct route_node *rn;
1958
0
  struct zebra_if *zebra_if;
1959
0
  char pd_buf[ZEBRA_PROTODOWN_RC_STR_LEN];
1960
1961
0
  zebra_if = ifp->info;
1962
1963
0
  vty_out(vty, "Interface %s is ", ifp->name);
1964
0
  if (if_is_up(ifp)) {
1965
0
    vty_out(vty, "up, line protocol ");
1966
1967
0
    if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) {
1968
0
      if (if_is_running(ifp))
1969
0
        vty_out(vty, "is up\n");
1970
0
      else
1971
0
        vty_out(vty, "is down\n");
1972
0
    } else {
1973
0
      vty_out(vty, "detection is disabled\n");
1974
0
    }
1975
0
  } else {
1976
0
    vty_out(vty, "down\n");
1977
0
  }
1978
1979
0
  vty_out(vty, "  Link ups:   %5u    last: %s\n", zebra_if->up_count,
1980
0
    zebra_if->up_last[0] ? zebra_if->up_last : "(never)");
1981
0
  vty_out(vty, "  Link downs: %5u    last: %s\n", zebra_if->down_count,
1982
0
    zebra_if->down_last[0] ? zebra_if->down_last : "(never)");
1983
1984
0
  zebra_ptm_show_status(vty, NULL, ifp);
1985
1986
0
  vty_out(vty, "  vrf: %s\n", ifp->vrf->name);
1987
1988
0
  if (ifp->desc)
1989
0
    vty_out(vty, "  Description: %s\n", ifp->desc);
1990
0
  if (zebra_if->desc)
1991
0
    vty_out(vty, "  OS Description: %s\n", zebra_if->desc);
1992
1993
0
  if (ifp->ifindex == IFINDEX_INTERNAL) {
1994
0
    vty_out(vty, "  pseudo interface\n");
1995
0
    return;
1996
0
  } else if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
1997
0
    vty_out(vty, "  index %d inactive interface\n", ifp->ifindex);
1998
0
    return;
1999
0
  }
2000
2001
0
  vty_out(vty, "  index %d metric %d mtu %d speed %u ", ifp->ifindex,
2002
0
    ifp->metric, ifp->mtu, ifp->speed);
2003
0
  if (ifp->mtu6 != ifp->mtu)
2004
0
    vty_out(vty, "mtu6 %d ", ifp->mtu6);
2005
0
  vty_out(vty, "\n  flags: %s\n", if_flag_dump(ifp->flags));
2006
2007
0
  if (zebra_if->mpls)
2008
0
    vty_out(vty, "  MPLS enabled\n");
2009
2010
0
  if (zebra_if->linkdown)
2011
0
    vty_out(vty, "  Ignore all v4 routes with linkdown\n");
2012
0
  if (zebra_if->linkdownv6)
2013
0
    vty_out(vty, "  Ignore all v6 routes with linkdown\n");
2014
2015
0
  if (zebra_if->v4mcast_on)
2016
0
    vty_out(vty, "  v4 Multicast forwarding is on\n");
2017
0
  if (zebra_if->v6mcast_on)
2018
0
    vty_out(vty, "  v6 Multicast forwarding is on\n");
2019
2020
  /* Hardware address. */
2021
0
  vty_out(vty, "  Type: %s\n", if_link_type_str(ifp->ll_type));
2022
0
  if (ifp->hw_addr_len != 0) {
2023
0
    int i;
2024
2025
0
    vty_out(vty, "  HWaddr: ");
2026
0
    for (i = 0; i < ifp->hw_addr_len; i++)
2027
0
      vty_out(vty, "%s%02x", i == 0 ? "" : ":",
2028
0
        ifp->hw_addr[i]);
2029
0
    vty_out(vty, "\n");
2030
0
  }
2031
2032
  /* Bandwidth in Mbps */
2033
0
  if (ifp->bandwidth != 0) {
2034
0
    vty_out(vty, "  bandwidth %u Mbps", ifp->bandwidth);
2035
0
    vty_out(vty, "\n");
2036
0
  }
2037
2038
0
  for (rn = route_top(zebra_if->ipv4_subnets); rn; rn = route_next(rn)) {
2039
0
    if (!rn->info)
2040
0
      continue;
2041
2042
0
    for (ALL_LIST_ELEMENTS_RO((struct list *)rn->info, node,
2043
0
            connected))
2044
0
      connected_dump_vty(vty, NULL, connected);
2045
0
  }
2046
2047
0
  for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) {
2048
0
    if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL)
2049
0
        && (connected->address->family == AF_INET6))
2050
0
      connected_dump_vty(vty, NULL, connected);
2051
0
  }
2052
2053
0
  vty_out(vty, "  Interface Type %s\n",
2054
0
    zebra_ziftype_2str(zebra_if->zif_type));
2055
0
  vty_out(vty, "  Interface Slave Type %s\n",
2056
0
    zebra_zifslavetype_2str(zebra_if->zif_slave_type));
2057
2058
0
  if (IS_ZEBRA_IF_BRIDGE(ifp)) {
2059
0
    vty_out(vty, "  Bridge VLAN-aware: %s\n",
2060
0
      IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(zebra_if) ? "yes" : "no");
2061
0
  } else if (IS_ZEBRA_IF_VLAN(ifp)) {
2062
0
    struct zebra_l2info_vlan *vlan_info;
2063
2064
0
    vlan_info = &zebra_if->l2info.vl;
2065
0
    vty_out(vty, "  VLAN Id %u\n", vlan_info->vid);
2066
0
  } else if (IS_ZEBRA_IF_VXLAN(ifp)) {
2067
0
    zebra_vxlan_if_dump_vty(vty, zebra_if);
2068
0
  } else if (IS_ZEBRA_IF_GRE(ifp)) {
2069
0
    struct zebra_l2info_gre *gre_info;
2070
2071
0
    gre_info = &zebra_if->l2info.gre;
2072
0
    if (gre_info->vtep_ip.s_addr != INADDR_ANY) {
2073
0
      vty_out(vty, "  VTEP IP: %pI4", &gre_info->vtep_ip);
2074
0
      if (gre_info->vtep_ip_remote.s_addr != INADDR_ANY)
2075
0
        vty_out(vty, " , remote %pI4",
2076
0
          &gre_info->vtep_ip_remote);
2077
0
      vty_out(vty, "\n");
2078
0
    }
2079
0
    if (gre_info->ifindex_link &&
2080
0
        (gre_info->link_nsid != NS_UNKNOWN)) {
2081
0
      struct interface *ifp;
2082
2083
0
      ifp = if_lookup_by_index_per_ns(
2084
0
          zebra_ns_lookup(gre_info->link_nsid),
2085
0
          gre_info->ifindex_link);
2086
0
      vty_out(vty, "  Link Interface %s\n",
2087
0
        ifp == NULL ? "Unknown" :
2088
0
        ifp->name);
2089
0
    }
2090
0
  }
2091
2092
0
  if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)) {
2093
0
    struct zebra_l2info_brslave *br_slave;
2094
2095
0
    br_slave = &zebra_if->brslave_info;
2096
0
    if (br_slave->bridge_ifindex != IFINDEX_INTERNAL) {
2097
0
      if (br_slave->br_if)
2098
0
        vty_out(vty, "  Master interface: %s\n",
2099
0
          br_slave->br_if->name);
2100
0
      else
2101
0
        vty_out(vty, "  Master ifindex: %u\n",
2102
0
          br_slave->bridge_ifindex);
2103
0
    }
2104
0
  }
2105
2106
0
  if (IS_ZEBRA_IF_BOND_SLAVE(ifp)) {
2107
0
    struct zebra_l2info_bondslave *bond_slave;
2108
2109
0
    bond_slave = &zebra_if->bondslave_info;
2110
0
    if (bond_slave->bond_ifindex != IFINDEX_INTERNAL) {
2111
0
      if (bond_slave->bond_if)
2112
0
        vty_out(vty, "  Master interface: %s\n",
2113
0
          bond_slave->bond_if->name);
2114
0
      else
2115
0
        vty_out(vty, "  Master ifindex: %u\n",
2116
0
          bond_slave->bond_ifindex);
2117
0
    }
2118
0
  }
2119
2120
0
  if (zebra_if->flags & ZIF_FLAG_LACP_BYPASS)
2121
0
    vty_out(vty, "  LACP bypass: on\n");
2122
2123
0
  zebra_evpn_if_es_print(vty, NULL, zebra_if);
2124
0
  vty_out(vty, "  protodown: %s %s\n",
2125
0
    (ZEBRA_IF_IS_PROTODOWN(zebra_if)) ? "on" : "off",
2126
0
    if_is_protodown_applicable(ifp) ? "" : "(n/a)");
2127
0
  if (zebra_if->protodown_rc)
2128
0
    vty_out(vty, "  protodown reasons: %s\n",
2129
0
      zebra_protodown_rc_str(zebra_if->protodown_rc, pd_buf,
2130
0
                 sizeof(pd_buf)));
2131
2132
0
  if (zebra_if->link_ifindex != IFINDEX_INTERNAL) {
2133
0
    if (zebra_if->link)
2134
0
      vty_out(vty, "  Parent interface: %s\n", zebra_if->link->name);
2135
0
    else
2136
0
      vty_out(vty, "  Parent ifindex: %d\n", zebra_if->link_ifindex);
2137
0
  }
2138
2139
0
  if (HAS_LINK_PARAMS(ifp)) {
2140
0
    int i;
2141
0
    struct if_link_params *iflp = ifp->link_params;
2142
0
    vty_out(vty, "  Traffic Engineering Link Parameters:\n");
2143
0
    if (IS_PARAM_SET(iflp, LP_TE_METRIC))
2144
0
      vty_out(vty, "    TE metric %u\n", iflp->te_metric);
2145
0
    if (IS_PARAM_SET(iflp, LP_MAX_BW))
2146
0
      vty_out(vty, "    Maximum Bandwidth %g (Byte/s)\n",
2147
0
        iflp->max_bw);
2148
0
    if (IS_PARAM_SET(iflp, LP_MAX_RSV_BW))
2149
0
      vty_out(vty,
2150
0
        "    Maximum Reservable Bandwidth %g (Byte/s)\n",
2151
0
        iflp->max_rsv_bw);
2152
0
    if (IS_PARAM_SET(iflp, LP_UNRSV_BW)) {
2153
0
      vty_out(vty,
2154
0
        "    Unreserved Bandwidth per Class Type in Byte/s:\n");
2155
0
      for (i = 0; i < MAX_CLASS_TYPE; i += 2)
2156
0
        vty_out(vty,
2157
0
          "      [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)\n",
2158
0
          i, iflp->unrsv_bw[i], i + 1,
2159
0
          iflp->unrsv_bw[i + 1]);
2160
0
    }
2161
2162
0
    if (IS_PARAM_SET(iflp, LP_ADM_GRP))
2163
0
      vty_out(vty, "    Administrative Group:%u\n",
2164
0
        iflp->admin_grp);
2165
0
    if (IS_PARAM_SET(iflp, LP_DELAY)) {
2166
0
      vty_out(vty, "    Link Delay Average: %u (micro-sec.)",
2167
0
        iflp->av_delay);
2168
0
      if (IS_PARAM_SET(iflp, LP_MM_DELAY)) {
2169
0
        vty_out(vty, " Min:  %u (micro-sec.)",
2170
0
          iflp->min_delay);
2171
0
        vty_out(vty, " Max:  %u (micro-sec.)",
2172
0
          iflp->max_delay);
2173
0
      }
2174
0
      vty_out(vty, "\n");
2175
0
    }
2176
0
    if (IS_PARAM_SET(iflp, LP_DELAY_VAR))
2177
0
      vty_out(vty,
2178
0
        "    Link Delay Variation %u (micro-sec.)\n",
2179
0
        iflp->delay_var);
2180
0
    if (IS_PARAM_SET(iflp, LP_PKT_LOSS))
2181
0
      vty_out(vty, "    Link Packet Loss %g (in %%)\n",
2182
0
        iflp->pkt_loss);
2183
0
    if (IS_PARAM_SET(iflp, LP_AVA_BW))
2184
0
      vty_out(vty, "    Available Bandwidth %g (Byte/s)\n",
2185
0
        iflp->ava_bw);
2186
0
    if (IS_PARAM_SET(iflp, LP_RES_BW))
2187
0
      vty_out(vty, "    Residual Bandwidth %g (Byte/s)\n",
2188
0
        iflp->res_bw);
2189
0
    if (IS_PARAM_SET(iflp, LP_USE_BW))
2190
0
      vty_out(vty, "    Utilized Bandwidth %g (Byte/s)\n",
2191
0
        iflp->use_bw);
2192
0
    if (IS_PARAM_SET(iflp, LP_RMT_AS))
2193
0
      vty_out(vty, "    Neighbor ASBR IP: %pI4 AS: %u \n",
2194
0
        &iflp->rmt_ip, iflp->rmt_as);
2195
0
  }
2196
2197
0
  hook_call(zebra_if_extra_info, vty, ifp);
2198
2199
0
  if (listhead(ifp->nbr_connected))
2200
0
    vty_out(vty, "  Neighbor address(s):\n");
2201
0
  for (ALL_LIST_ELEMENTS_RO(ifp->nbr_connected, node, nbr_connected))
2202
0
    nbr_connected_dump_vty(vty, NULL, nbr_connected);
2203
2204
#ifdef HAVE_PROC_NET_DEV
2205
  /* Statistics print out using proc file system. */
2206
  vty_out(vty,
2207
    "    %lu input packets (%lu multicast), %lu bytes, %lu dropped\n",
2208
    ifp->stats.rx_packets, ifp->stats.rx_multicast,
2209
    ifp->stats.rx_bytes, ifp->stats.rx_dropped);
2210
2211
  vty_out(vty,
2212
    "    %lu input errors, %lu length, %lu overrun, %lu CRC, %lu frame\n",
2213
    ifp->stats.rx_errors, ifp->stats.rx_length_errors,
2214
    ifp->stats.rx_over_errors, ifp->stats.rx_crc_errors,
2215
    ifp->stats.rx_frame_errors);
2216
2217
  vty_out(vty, "    %lu fifo, %lu missed\n", ifp->stats.rx_fifo_errors,
2218
    ifp->stats.rx_missed_errors);
2219
2220
  vty_out(vty, "    %lu output packets, %lu bytes, %lu dropped\n",
2221
    ifp->stats.tx_packets, ifp->stats.tx_bytes,
2222
    ifp->stats.tx_dropped);
2223
2224
  vty_out(vty,
2225
    "    %lu output errors, %lu aborted, %lu carrier, %lu fifo, %lu heartbeat\n",
2226
    ifp->stats.tx_errors, ifp->stats.tx_aborted_errors,
2227
    ifp->stats.tx_carrier_errors, ifp->stats.tx_fifo_errors,
2228
    ifp->stats.tx_heartbeat_errors);
2229
2230
  vty_out(vty, "    %lu window, %lu collisions\n",
2231
    ifp->stats.tx_window_errors, ifp->stats.collisions);
2232
#endif /* HAVE_PROC_NET_DEV */
2233
2234
#ifdef HAVE_NET_RT_IFLIST
2235
  /* Statistics print out using sysctl (). */
2236
  vty_out(vty,
2237
    "    input packets %llu, bytes %llu, dropped %llu, multicast packets %llu\n",
2238
    (unsigned long long)ifp->stats.ifi_ipackets,
2239
    (unsigned long long)ifp->stats.ifi_ibytes,
2240
    (unsigned long long)ifp->stats.ifi_iqdrops,
2241
    (unsigned long long)ifp->stats.ifi_imcasts);
2242
2243
  vty_out(vty, "    input errors %llu\n",
2244
    (unsigned long long)ifp->stats.ifi_ierrors);
2245
2246
  vty_out(vty,
2247
    "    output packets %llu, bytes %llu, multicast packets %llu\n",
2248
    (unsigned long long)ifp->stats.ifi_opackets,
2249
    (unsigned long long)ifp->stats.ifi_obytes,
2250
    (unsigned long long)ifp->stats.ifi_omcasts);
2251
2252
  vty_out(vty, "    output errors %llu\n",
2253
    (unsigned long long)ifp->stats.ifi_oerrors);
2254
2255
  vty_out(vty, "    collisions %llu\n",
2256
    (unsigned long long)ifp->stats.ifi_collisions);
2257
#endif /* HAVE_NET_RT_IFLIST */
2258
0
}
2259
2260
static void zebra_vxlan_if_vni_dump_vty_json(json_object *json_if,
2261
               struct zebra_vxlan_vni *vni)
2262
0
{
2263
0
  json_object_int_add(json_if, "vxlanId", vni->vni);
2264
0
  if (vni->access_vlan)
2265
0
    json_object_int_add(json_if, "accessVlanId", vni->access_vlan);
2266
0
  if (vni->mcast_grp.s_addr != INADDR_ANY)
2267
0
    json_object_string_addf(json_if, "mcastGroup", "%pI4",
2268
0
          &vni->mcast_grp);
2269
0
}
2270
2271
static void zebra_vxlan_if_vni_hash_dump_vty_json(struct hash_bucket *bucket,
2272
              void *ctxt)
2273
0
{
2274
0
  json_object *json_if;
2275
0
  struct zebra_vxlan_vni *vni;
2276
2277
0
  vni = (struct zebra_vxlan_vni *)bucket->data;
2278
0
  json_if = (json_object *)ctxt;
2279
2280
0
  zebra_vxlan_if_vni_dump_vty_json(json_if, vni);
2281
0
}
2282
2283
static void zebra_vxlan_if_dump_vty_json(json_object *json_if,
2284
           struct zebra_if *zebra_if)
2285
0
{
2286
0
  struct zebra_l2info_vxlan *vxlan_info;
2287
0
  struct zebra_vxlan_vni_info *vni_info;
2288
2289
0
  vxlan_info = &zebra_if->l2info.vxl;
2290
0
  vni_info = &vxlan_info->vni_info;
2291
2292
0
  if (vxlan_info->vtep_ip.s_addr != INADDR_ANY)
2293
0
    json_object_string_addf(json_if, "vtepIp", "%pI4",
2294
0
          &vxlan_info->vtep_ip);
2295
2296
0
  if (vxlan_info->ifindex_link && (vxlan_info->link_nsid != NS_UNKNOWN)) {
2297
0
    struct interface *ifp;
2298
2299
0
    ifp = if_lookup_by_index_per_ns(
2300
0
      zebra_ns_lookup(vxlan_info->link_nsid),
2301
0
      vxlan_info->ifindex_link);
2302
0
    json_object_string_add(json_if, "linkInterface",
2303
0
               ifp == NULL ? "Unknown" : ifp->name);
2304
0
  }
2305
0
  if (IS_ZEBRA_VXLAN_IF_VNI(zebra_if)) {
2306
0
    zebra_vxlan_if_vni_dump_vty_json(json_if, &vni_info->vni);
2307
0
  } else {
2308
0
    hash_iterate(vni_info->vni_table,
2309
0
           zebra_vxlan_if_vni_hash_dump_vty_json, json_if);
2310
0
  }
2311
0
}
2312
2313
static void if_dump_vty_json(struct vty *vty, struct interface *ifp,
2314
           json_object *json)
2315
0
{
2316
0
  struct connected *connected;
2317
0
  struct nbr_connected *nbr_connected;
2318
0
  struct listnode *node;
2319
0
  struct route_node *rn;
2320
0
  struct zebra_if *zebra_if;
2321
0
  char pd_buf[ZEBRA_PROTODOWN_RC_STR_LEN];
2322
0
  char buf[BUFSIZ];
2323
0
  json_object *json_if;
2324
0
  json_object *json_addrs;
2325
2326
0
  json_if = json_object_new_object();
2327
0
  json_object_object_add(json, ifp->name, json_if);
2328
2329
0
  if (if_is_up(ifp)) {
2330
0
    json_object_string_add(json_if, "administrativeStatus", "up");
2331
2332
0
    if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) {
2333
0
      json_object_string_add(json_if, "operationalStatus",
2334
0
                 if_is_running(ifp) ? "up"
2335
0
                  : "down");
2336
0
      json_object_boolean_add(json_if, "linkDetection", true);
2337
0
    } else {
2338
0
      json_object_boolean_add(json_if, "linkDetection",
2339
0
            false);
2340
0
    }
2341
0
  } else {
2342
0
    json_object_string_add(json_if, "administrativeStatus", "down");
2343
0
  }
2344
2345
0
  zebra_if = ifp->info;
2346
2347
0
  json_object_int_add(json_if, "linkUps", zebra_if->up_count);
2348
0
  json_object_int_add(json_if, "linkDowns", zebra_if->down_count);
2349
0
  if (zebra_if->up_last[0])
2350
0
    json_object_string_add(json_if, "lastLinkUp",
2351
0
               zebra_if->up_last);
2352
0
  if (zebra_if->down_last[0])
2353
0
    json_object_string_add(json_if, "lastLinkDown",
2354
0
               zebra_if->down_last);
2355
2356
0
  zebra_ptm_show_status(vty, json, ifp);
2357
2358
0
  json_object_string_add(json_if, "vrfName", ifp->vrf->name);
2359
2360
0
  if (ifp->desc)
2361
0
    json_object_string_add(json_if, "description", ifp->desc);
2362
0
  if (zebra_if->desc)
2363
0
    json_object_string_add(json_if, "OsDescription",
2364
0
               zebra_if->desc);
2365
2366
0
  json_object_boolean_add(json_if, "mplsEnabled", zebra_if->mpls);
2367
0
  json_object_boolean_add(json_if, "linkDown", zebra_if->linkdown);
2368
0
  json_object_boolean_add(json_if, "linkDownV6", zebra_if->linkdownv6);
2369
0
  json_object_boolean_add(json_if, "mcForwardingV4",
2370
0
        zebra_if->v4mcast_on);
2371
0
  json_object_boolean_add(json_if, "mcForwardingV6",
2372
0
        zebra_if->v6mcast_on);
2373
2374
0
  if (ifp->ifindex == IFINDEX_INTERNAL) {
2375
0
    json_object_boolean_add(json_if, "pseudoInterface", true);
2376
0
    return;
2377
0
  } else if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
2378
0
    json_object_int_add(json_if, "index", ifp->ifindex);
2379
0
    return;
2380
0
  }
2381
2382
0
  json_object_boolean_add(json_if, "pseudoInterface", false);
2383
0
  json_object_int_add(json_if, "index", ifp->ifindex);
2384
0
  json_object_int_add(json_if, "metric", ifp->metric);
2385
0
  json_object_int_add(json_if, "mtu", ifp->mtu);
2386
0
  if (ifp->mtu6 != ifp->mtu)
2387
0
    json_object_int_add(json_if, "mtu6", ifp->mtu6);
2388
0
  json_object_int_add(json_if, "speed", ifp->speed);
2389
0
  json_object_string_add(json_if, "flags", if_flag_dump(ifp->flags));
2390
2391
  /* Hardware address. */
2392
0
  json_object_string_add(json_if, "type", if_link_type_str(ifp->ll_type));
2393
0
  if (ifp->hw_addr_len != 0) {
2394
0
    char hwbuf[BUFSIZ];
2395
2396
0
    hwbuf[0] = '\0';
2397
0
    for (int i = 0; i < ifp->hw_addr_len; i++) {
2398
0
      snprintf(buf, sizeof(buf), "%s%02x", i == 0 ? "" : ":",
2399
0
         ifp->hw_addr[i]);
2400
0
      strlcat(hwbuf, buf, sizeof(hwbuf));
2401
0
    }
2402
0
    json_object_string_add(json_if, "hardwareAddress", hwbuf);
2403
0
  }
2404
2405
  /* Bandwidth in Mbps */
2406
0
  if (ifp->bandwidth != 0)
2407
0
    json_object_int_add(json_if, "bandwidth", ifp->bandwidth);
2408
2409
2410
  /* IP addresses. */
2411
0
  json_addrs = json_object_new_array();
2412
0
  json_object_object_add(json_if, "ipAddresses", json_addrs);
2413
2414
0
  for (rn = route_top(zebra_if->ipv4_subnets); rn; rn = route_next(rn)) {
2415
0
    if (!rn->info)
2416
0
      continue;
2417
2418
0
    for (ALL_LIST_ELEMENTS_RO((struct list *)rn->info, node,
2419
0
            connected))
2420
0
      connected_dump_vty(vty, json_addrs, connected);
2421
0
  }
2422
2423
0
  for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) {
2424
0
    if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL)
2425
0
        && (connected->address->family == AF_INET6))
2426
0
      connected_dump_vty(vty, json_addrs, connected);
2427
0
  }
2428
2429
0
  json_object_string_add(json_if, "interfaceType",
2430
0
             zebra_ziftype_2str(zebra_if->zif_type));
2431
0
  json_object_string_add(
2432
0
    json_if, "interfaceSlaveType",
2433
0
    zebra_zifslavetype_2str(zebra_if->zif_slave_type));
2434
2435
0
  if (IS_ZEBRA_IF_BRIDGE(ifp)) {
2436
0
    struct zebra_l2info_bridge *bridge_info;
2437
2438
0
    bridge_info = &zebra_if->l2info.br;
2439
0
    json_object_boolean_add(json_if, "bridgeVlanAware",
2440
0
          bridge_info->bridge.vlan_aware);
2441
0
  } else if (IS_ZEBRA_IF_VLAN(ifp)) {
2442
0
    struct zebra_l2info_vlan *vlan_info;
2443
2444
0
    vlan_info = &zebra_if->l2info.vl;
2445
0
    json_object_int_add(json_if, "vlanId", vlan_info->vid);
2446
0
  } else if (IS_ZEBRA_IF_VXLAN(ifp)) {
2447
0
    zebra_vxlan_if_dump_vty_json(json_if, zebra_if);
2448
2449
0
  } else if (IS_ZEBRA_IF_GRE(ifp)) {
2450
0
    struct zebra_l2info_gre *gre_info;
2451
2452
0
    gre_info = &zebra_if->l2info.gre;
2453
0
    if (gre_info->vtep_ip.s_addr != INADDR_ANY) {
2454
0
      json_object_string_addf(json_if, "vtepIp", "%pI4",
2455
0
            &gre_info->vtep_ip);
2456
0
      if (gre_info->vtep_ip_remote.s_addr != INADDR_ANY)
2457
0
        json_object_string_addf(
2458
0
          json_if, "vtepRemoteIp", "%pI4",
2459
0
          &gre_info->vtep_ip_remote);
2460
0
    }
2461
0
    if (gre_info->ifindex_link
2462
0
        && (gre_info->link_nsid != NS_UNKNOWN)) {
2463
0
      struct interface *ifp;
2464
2465
0
      ifp = if_lookup_by_index_per_ns(
2466
0
        zebra_ns_lookup(gre_info->link_nsid),
2467
0
        gre_info->ifindex_link);
2468
0
      json_object_string_add(json_if, "linkInterface",
2469
0
                 ifp == NULL ? "Unknown"
2470
0
                 : ifp->name);
2471
0
    }
2472
0
  }
2473
2474
0
  if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)) {
2475
0
    struct zebra_l2info_brslave *br_slave;
2476
2477
0
    br_slave = &zebra_if->brslave_info;
2478
0
    if (br_slave->bridge_ifindex != IFINDEX_INTERNAL) {
2479
0
      if (br_slave->br_if)
2480
0
        json_object_string_add(json_if,
2481
0
                   "masterInterface",
2482
0
                   br_slave->br_if->name);
2483
0
      else
2484
0
        json_object_int_add(json_if, "masterIfindex",
2485
0
                br_slave->bridge_ifindex);
2486
0
    }
2487
0
  }
2488
2489
0
  if (IS_ZEBRA_IF_BOND_SLAVE(ifp)) {
2490
0
    struct zebra_l2info_bondslave *bond_slave;
2491
2492
0
    bond_slave = &zebra_if->bondslave_info;
2493
0
    if (bond_slave->bond_ifindex != IFINDEX_INTERNAL) {
2494
0
      if (bond_slave->bond_if)
2495
0
        json_object_string_add(
2496
0
          json_if, "masterInterface",
2497
0
          bond_slave->bond_if->name);
2498
0
      else
2499
0
        json_object_int_add(json_if, "masterIfindex",
2500
0
                bond_slave->bond_ifindex);
2501
0
    }
2502
0
  }
2503
2504
0
  json_object_boolean_add(
2505
0
    json_if, "lacpBypass",
2506
0
    CHECK_FLAG(zebra_if->flags, ZIF_FLAG_LACP_BYPASS));
2507
2508
0
  zebra_evpn_if_es_print(vty, json_if, zebra_if);
2509
2510
0
  if (if_is_protodown_applicable(ifp)) {
2511
0
    json_object_string_add(
2512
0
      json_if, "protodown",
2513
0
      (ZEBRA_IF_IS_PROTODOWN(zebra_if)) ? "on" : "off");
2514
0
    if (zebra_if->protodown_rc)
2515
0
      json_object_string_add(
2516
0
        json_if, "protodownReason",
2517
0
        zebra_protodown_rc_str(zebra_if->protodown_rc,
2518
0
                   pd_buf, sizeof(pd_buf)));
2519
0
  }
2520
2521
0
  if (zebra_if->link_ifindex != IFINDEX_INTERNAL) {
2522
0
    if (zebra_if->link)
2523
0
      json_object_string_add(json_if, "parentInterface",
2524
0
                 zebra_if->link->name);
2525
0
    else
2526
0
      json_object_int_add(json_if, "parentIfindex",
2527
0
              zebra_if->link_ifindex);
2528
0
  }
2529
2530
0
  if (HAS_LINK_PARAMS(ifp)) {
2531
0
    struct if_link_params *iflp = ifp->link_params;
2532
0
    json_object *json_te;
2533
2534
0
    json_te = json_object_new_object();
2535
0
    json_object_object_add(
2536
0
      json_if, "trafficEngineeringLinkParameters", json_te);
2537
2538
0
    if (IS_PARAM_SET(iflp, LP_TE_METRIC))
2539
0
      json_object_int_add(json_te, "teMetric",
2540
0
              iflp->te_metric);
2541
0
    if (IS_PARAM_SET(iflp, LP_MAX_BW))
2542
0
      json_object_double_add(json_te, "maximumBandwidth",
2543
0
                 iflp->max_bw);
2544
0
    if (IS_PARAM_SET(iflp, LP_MAX_RSV_BW))
2545
0
      json_object_double_add(json_te,
2546
0
                 "maximumReservableBandwidth",
2547
0
                 iflp->max_rsv_bw);
2548
0
    if (IS_PARAM_SET(iflp, LP_UNRSV_BW)) {
2549
0
      json_object *json_bws;
2550
2551
0
      json_bws = json_object_new_object();
2552
0
      json_object_object_add(json_te, "unreservedBandwidth",
2553
0
                 json_bws);
2554
0
      for (unsigned int i = 0; i < MAX_CLASS_TYPE; ++i) {
2555
0
        char buf_ct[64];
2556
2557
0
        snprintf(buf_ct, sizeof(buf_ct), "classType%u",
2558
0
           i);
2559
0
        json_object_double_add(json_bws, buf_ct,
2560
0
                   iflp->unrsv_bw[i]);
2561
0
      }
2562
0
    }
2563
2564
0
    if (IS_PARAM_SET(iflp, LP_ADM_GRP))
2565
0
      json_object_int_add(json_te, "administrativeGroup",
2566
0
              iflp->admin_grp);
2567
0
    if (IS_PARAM_SET(iflp, LP_DELAY)) {
2568
0
      json_object_int_add(json_te, "linkDelayAverage",
2569
0
              iflp->av_delay);
2570
0
      if (IS_PARAM_SET(iflp, LP_MM_DELAY)) {
2571
0
        json_object_int_add(json_te, "linkDelayMinimum",
2572
0
                iflp->min_delay);
2573
0
        json_object_int_add(json_te, "linkDelayMaximum",
2574
0
                iflp->max_delay);
2575
0
      }
2576
0
    }
2577
0
    if (IS_PARAM_SET(iflp, LP_DELAY_VAR))
2578
0
      json_object_int_add(json_te, "linkDelayVariation",
2579
0
              iflp->delay_var);
2580
0
    if (IS_PARAM_SET(iflp, LP_PKT_LOSS))
2581
0
      json_object_double_add(json_te, "linkPacketLoss",
2582
0
                 iflp->pkt_loss);
2583
0
    if (IS_PARAM_SET(iflp, LP_AVA_BW))
2584
0
      json_object_double_add(json_te, "availableBandwidth",
2585
0
                 iflp->ava_bw);
2586
0
    if (IS_PARAM_SET(iflp, LP_RES_BW))
2587
0
      json_object_double_add(json_te, "residualBandwidth",
2588
0
                 iflp->res_bw);
2589
0
    if (IS_PARAM_SET(iflp, LP_USE_BW))
2590
0
      json_object_double_add(json_te, "utilizedBandwidth",
2591
0
                 iflp->use_bw);
2592
0
    if (IS_PARAM_SET(iflp, LP_RMT_AS))
2593
0
      json_object_string_addf(json_te, "neighborAsbrIp",
2594
0
            "%pI4", &iflp->rmt_ip);
2595
0
    json_object_int_add(json_te, "neighborAsbrAs", iflp->rmt_as);
2596
0
  }
2597
2598
0
  if (listhead(ifp->nbr_connected)) {
2599
0
    json_object *json_nbr_addrs;
2600
2601
0
    json_nbr_addrs = json_object_new_array();
2602
0
    json_object_object_add(json_if, "neighborIpAddresses",
2603
0
               json_nbr_addrs);
2604
2605
0
    for (ALL_LIST_ELEMENTS_RO(ifp->nbr_connected, node,
2606
0
            nbr_connected))
2607
0
      nbr_connected_dump_vty(vty, json_nbr_addrs,
2608
0
                 nbr_connected);
2609
0
  }
2610
2611
#ifdef HAVE_PROC_NET_DEV
2612
  json_object_int_add(json_if, "inputPackets", stats.rx_packets);
2613
  json_object_int_add(json_if, "inputBytes", ifp->stats.rx_bytes);
2614
  json_object_int_add(json_if, "inputDropped", ifp->stats.rx_dropped);
2615
  json_object_int_add(json_if, "inputMulticastPackets",
2616
          ifp->stats.rx_multicast);
2617
  json_object_int_add(json_if, "inputErrors", ifp->stats.rx_errors);
2618
  json_object_int_add(json_if, "inputLengthErrors",
2619
          ifp->stats.rx_length_errors);
2620
  json_object_int_add(json_if, "inputOverrunErrors",
2621
          ifp->stats.rx_over_errors);
2622
  json_object_int_add(json_if, "inputCrcErrors",
2623
          ifp->stats.rx_crc_errors);
2624
  json_object_int_add(json_if, "inputFrameErrors",
2625
          ifp->stats.rx_frame_errors);
2626
  json_object_int_add(json_if, "inputFifoErrors",
2627
          ifp->stats.rx_fifo_errors);
2628
  json_object_int_add(json_if, "inputMissedErrors",
2629
          ifp->stats.rx_missed_errors);
2630
  json_object_int_add(json_if, "outputPackets", ifp->stats.tx_packets);
2631
  json_object_int_add(json_if, "outputBytes", ifp->stats.tx_bytes);
2632
  json_object_int_add(json_if, "outputDroppedPackets",
2633
          ifp->stats.tx_dropped);
2634
  json_object_int_add(json_if, "outputErrors", ifp->stats.tx_errors);
2635
  json_object_int_add(json_if, "outputAbortedErrors",
2636
          ifp->stats.tx_aborted_errors);
2637
  json_object_int_add(json_if, "outputCarrierErrors",
2638
          ifp->stats.tx_carrier_errors);
2639
  json_object_int_add(json_if, "outputFifoErrors",
2640
          ifp->stats.tx_fifo_errors);
2641
  json_object_int_add(json_if, "outputHeartbeatErrors",
2642
          ifp->stats.tx_heartbeat_errors);
2643
  json_object_int_add(json_if, "outputWindowErrors",
2644
          ifp->stats.tx_window_errors);
2645
  json_object_int_add(json_if, "collisions", ifp->stats.collisions);
2646
#endif /* HAVE_PROC_NET_DEV */
2647
2648
#ifdef HAVE_NET_RT_IFLIST
2649
  json_object_int_add(json_if, "inputPackets", ifp->stats.ifi_ipackets);
2650
  json_object_int_add(json_if, "inputBytes", ifp->stats.ifi_ibytes);
2651
  json_object_int_add(json_if, "inputDropd", ifp->stats.ifi_iqdrops);
2652
  json_object_int_add(json_if, "inputMulticastPackets",
2653
          ifp->stats.ifi_imcasts);
2654
  json_object_int_add(json_if, "inputErrors", ifp->stats.ifi_ierrors);
2655
  json_object_int_add(json_if, "outputPackets", ifp->stats.ifi_opackets);
2656
  json_object_int_add(json_if, "outputBytes", ifp->stats.ifi_obytes);
2657
  json_object_int_add(json_if, "outputMulticastPackets",
2658
          ifp->stats.ifi_omcasts);
2659
  json_object_int_add(json_if, "outputErrors", ifp->stats.ifi_oerrors);
2660
  json_object_int_add(json_if, "collisions", ifp->stats.ifi_collisions);
2661
#endif /* HAVE_NET_RT_IFLIST */
2662
0
}
2663
2664
static void interface_update_stats(void)
2665
0
{
2666
#ifdef HAVE_PROC_NET_DEV
2667
  /* If system has interface statistics via proc file system, update
2668
     statistics. */
2669
  ifstat_update_proc();
2670
#endif /* HAVE_PROC_NET_DEV */
2671
#ifdef HAVE_NET_RT_IFLIST
2672
  ifstat_update_sysctl();
2673
#endif /* HAVE_NET_RT_IFLIST */
2674
0
}
2675
2676
#include "zebra/interface_clippy.c"
2677
/* Show all interfaces to vty. */
2678
DEFPY(show_interface, show_interface_cmd,
2679
      "show interface vrf NAME$vrf_name [brief$brief] [json$uj]",
2680
      SHOW_STR
2681
      "Interface status and configuration\n"
2682
      VRF_CMD_HELP_STR
2683
      "Interface status and configuration summary\n"
2684
      JSON_STR)
2685
0
{
2686
0
  struct vrf *vrf;
2687
0
  struct interface *ifp;
2688
0
  json_object *json = NULL;
2689
2690
0
  interface_update_stats();
2691
2692
0
  vrf = vrf_lookup_by_name(vrf_name);
2693
0
  if (!vrf) {
2694
0
    if (uj)
2695
0
      vty_out(vty, "{}\n");
2696
0
    else
2697
0
      vty_out(vty, "%% VRF %s not found\n", vrf_name);
2698
0
    return CMD_WARNING;
2699
0
  }
2700
2701
0
  if (uj)
2702
0
    json = json_object_new_object();
2703
2704
0
  if (brief) {
2705
0
    if (json)
2706
0
      ifs_dump_brief_vty_json(json, vrf);
2707
0
    else
2708
0
      ifs_dump_brief_vty(vty, vrf);
2709
0
  } else {
2710
0
    FOR_ALL_INTERFACES (vrf, ifp) {
2711
0
      if (json)
2712
0
        if_dump_vty_json(vty, ifp, json);
2713
0
      else
2714
0
        if_dump_vty(vty, ifp);
2715
0
    }
2716
0
  }
2717
2718
0
  if (json)
2719
0
    vty_json(vty, json);
2720
2721
0
  return CMD_SUCCESS;
2722
0
}
2723
2724
2725
/* Show all interfaces to vty. */
2726
DEFPY (show_interface_vrf_all,
2727
       show_interface_vrf_all_cmd,
2728
       "show interface [vrf all] [brief$brief] [json$uj]",
2729
       SHOW_STR
2730
       "Interface status and configuration\n"
2731
       VRF_ALL_CMD_HELP_STR
2732
       "Interface status and configuration summary\n"
2733
       JSON_STR)
2734
0
{
2735
0
  struct vrf *vrf;
2736
0
  struct interface *ifp;
2737
0
  json_object *json = NULL;
2738
2739
0
  interface_update_stats();
2740
2741
0
  if (uj)
2742
0
    json = json_object_new_object();
2743
2744
  /* All interface print. */
2745
0
  RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
2746
0
    if (brief) {
2747
0
      if (json)
2748
0
        ifs_dump_brief_vty_json(json, vrf);
2749
0
      else
2750
0
        ifs_dump_brief_vty(vty, vrf);
2751
0
    } else {
2752
0
      FOR_ALL_INTERFACES (vrf, ifp) {
2753
0
        if (json)
2754
0
          if_dump_vty_json(vty, ifp, json);
2755
0
        else
2756
0
          if_dump_vty(vty, ifp);
2757
0
      }
2758
0
    }
2759
0
  }
2760
2761
0
  if (json)
2762
0
    vty_json(vty, json);
2763
2764
0
  return CMD_SUCCESS;
2765
0
}
2766
2767
/* Show specified interface to vty. */
2768
2769
DEFPY (show_interface_name_vrf,
2770
       show_interface_name_vrf_cmd,
2771
       "show interface IFNAME$ifname vrf NAME$vrf_name [json$uj]",
2772
       SHOW_STR
2773
       "Interface status and configuration\n"
2774
       "Interface name\n"
2775
       VRF_CMD_HELP_STR
2776
       JSON_STR)
2777
0
{
2778
0
  struct interface *ifp;
2779
0
  struct vrf *vrf;
2780
0
  json_object *json = NULL;
2781
2782
0
  interface_update_stats();
2783
2784
0
  vrf = vrf_lookup_by_name(vrf_name);
2785
0
  if (!vrf) {
2786
0
    if (uj)
2787
0
      vty_out(vty, "{}\n");
2788
0
    else
2789
0
      vty_out(vty, "%% VRF %s not found\n", vrf_name);
2790
0
    return CMD_WARNING;
2791
0
  }
2792
2793
0
  ifp = if_lookup_by_name_vrf(ifname, vrf);
2794
0
  if (ifp == NULL) {
2795
0
    if (uj)
2796
0
      vty_out(vty, "{}\n");
2797
0
    else
2798
0
      vty_out(vty, "%% Can't find interface %s\n", ifname);
2799
0
    return CMD_WARNING;
2800
0
  }
2801
2802
0
  if (uj)
2803
0
    json = json_object_new_object();
2804
2805
0
  if (json)
2806
0
    if_dump_vty_json(vty, ifp, json);
2807
0
  else
2808
0
    if_dump_vty(vty, ifp);
2809
2810
0
  if (json)
2811
0
    vty_json(vty, json);
2812
2813
0
  return CMD_SUCCESS;
2814
0
}
2815
2816
/* Show specified interface to vty. */
2817
DEFPY (show_interface_name_vrf_all,
2818
       show_interface_name_vrf_all_cmd,
2819
       "show interface IFNAME$ifname [vrf all] [json$uj]",
2820
       SHOW_STR
2821
       "Interface status and configuration\n"
2822
       "Interface name\n"
2823
       VRF_ALL_CMD_HELP_STR
2824
       JSON_STR)
2825
0
{
2826
0
  struct interface *ifp = NULL;
2827
0
  struct interface *ifptmp;
2828
0
  struct vrf *vrf;
2829
0
  json_object *json = NULL;
2830
0
  int count = 0;
2831
2832
0
  interface_update_stats();
2833
2834
0
  RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
2835
0
    ifptmp = if_lookup_by_name_vrf(ifname, vrf);
2836
0
    if (ifptmp) {
2837
0
      ifp = ifptmp;
2838
0
      count++;
2839
0
      if (!vrf_is_backend_netns())
2840
0
        break;
2841
0
    }
2842
0
  }
2843
2844
0
  if (ifp == NULL) {
2845
0
    if (uj)
2846
0
      vty_out(vty, "{}\n");
2847
0
    else
2848
0
      vty_out(vty, "%% Can't find interface %s\n", ifname);
2849
0
    return CMD_WARNING;
2850
0
  }
2851
0
  if (count > 1) {
2852
0
    if (uj) {
2853
0
      vty_out(vty, "{}\n");
2854
0
    } else {
2855
0
      vty_out(vty,
2856
0
        "%% There are multiple interfaces with name %s\n",
2857
0
        ifname);
2858
0
      vty_out(vty, "%% You must specify the VRF name\n");
2859
0
    }
2860
0
    return CMD_WARNING;
2861
0
  }
2862
2863
0
  if (uj)
2864
0
    json = json_object_new_object();
2865
2866
0
  if (json)
2867
0
    if_dump_vty_json(vty, ifp, json);
2868
0
  else
2869
0
    if_dump_vty(vty, ifp);
2870
2871
0
  if (json)
2872
0
    vty_json(vty, json);
2873
2874
0
  return CMD_SUCCESS;
2875
0
}
2876
2877
static void if_show_description(struct vty *vty, struct vrf *vrf)
2878
0
{
2879
0
  struct interface *ifp;
2880
2881
0
  vty_out(vty, "Interface       Status  Protocol  Description\n");
2882
0
  FOR_ALL_INTERFACES (vrf, ifp) {
2883
0
    int len;
2884
0
    struct zebra_if *zif;
2885
0
    bool intf_desc;
2886
2887
0
    intf_desc = false;
2888
2889
0
    len = vty_out(vty, "%s", ifp->name);
2890
0
    vty_out(vty, "%*s", (16 - len), " ");
2891
2892
0
    if (if_is_up(ifp)) {
2893
0
      vty_out(vty, "up      ");
2894
0
      if (CHECK_FLAG(ifp->status,
2895
0
               ZEBRA_INTERFACE_LINKDETECTION)) {
2896
0
        if (if_is_running(ifp))
2897
0
          vty_out(vty, "up        ");
2898
0
        else
2899
0
          vty_out(vty, "down      ");
2900
0
      } else {
2901
0
        vty_out(vty, "unknown   ");
2902
0
      }
2903
0
    } else {
2904
0
      vty_out(vty, "down    down      ");
2905
0
    }
2906
2907
0
    if (ifp->desc) {
2908
0
      intf_desc = true;
2909
0
      vty_out(vty, "%s", ifp->desc);
2910
0
    }
2911
0
    zif = ifp->info;
2912
0
    if (zif && zif->desc) {
2913
0
      vty_out(vty, "%s%s",
2914
0
        intf_desc
2915
0
          ? "\n                                  "
2916
0
          : "",
2917
0
        zif->desc);
2918
0
    }
2919
2920
0
    vty_out(vty, "\n");
2921
0
  }
2922
0
}
2923
2924
DEFUN (show_interface_desc,
2925
       show_interface_desc_cmd,
2926
       "show interface description vrf NAME",
2927
       SHOW_STR
2928
       "Interface status and configuration\n"
2929
       "Interface description\n"
2930
       VRF_CMD_HELP_STR)
2931
0
{
2932
0
  struct vrf *vrf;
2933
2934
0
  vrf = vrf_lookup_by_name(argv[4]->arg);
2935
0
  if (!vrf) {
2936
0
    vty_out(vty, "%% VRF %s not found\n", argv[4]->arg);
2937
0
    return CMD_WARNING;
2938
0
  }
2939
2940
0
  if_show_description(vty, vrf);
2941
2942
0
  return CMD_SUCCESS;
2943
0
}
2944
2945
2946
DEFUN (show_interface_desc_vrf_all,
2947
       show_interface_desc_vrf_all_cmd,
2948
       "show interface description [vrf all]",
2949
       SHOW_STR
2950
       "Interface status and configuration\n"
2951
       "Interface description\n"
2952
       VRF_ALL_CMD_HELP_STR)
2953
0
{
2954
0
  struct vrf *vrf;
2955
2956
0
  RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
2957
0
    if (!RB_EMPTY(if_name_head, &vrf->ifaces_by_name)) {
2958
0
      vty_out(vty, "\n\tVRF %s(%u)\n\n", VRF_LOGNAME(vrf),
2959
0
        vrf->vrf_id);
2960
0
      if_show_description(vty, vrf);
2961
0
    }
2962
2963
0
  return CMD_SUCCESS;
2964
0
}
2965
2966
int if_multicast_set(struct interface *ifp)
2967
0
{
2968
0
  struct zebra_if *if_data;
2969
2970
0
  if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
2971
0
    if (if_set_flags(ifp, IFF_MULTICAST) < 0) {
2972
0
      zlog_debug("Can't set multicast flag on interface %s",
2973
0
           ifp->name);
2974
0
      return -1;
2975
0
    }
2976
0
    if_refresh(ifp);
2977
0
  }
2978
0
  if_data = ifp->info;
2979
0
  if_data->multicast = IF_ZEBRA_DATA_ON;
2980
2981
0
  return 0;
2982
0
}
2983
2984
DEFUN (multicast,
2985
       multicast_cmd,
2986
       "multicast",
2987
       "Set multicast flag to interface\n")
2988
0
{
2989
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
2990
0
  int ret;
2991
0
  struct zebra_if *if_data;
2992
2993
0
  if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
2994
0
    ret = if_set_flags(ifp, IFF_MULTICAST);
2995
0
    if (ret < 0) {
2996
0
      vty_out(vty, "Can't set multicast flag\n");
2997
0
      return CMD_WARNING_CONFIG_FAILED;
2998
0
    }
2999
0
    if_refresh(ifp);
3000
0
  }
3001
0
  if_data = ifp->info;
3002
0
  if_data->multicast = IF_ZEBRA_DATA_ON;
3003
3004
0
  return CMD_SUCCESS;
3005
0
}
3006
3007
DEFPY (mpls,
3008
       mpls_cmd,
3009
       "[no] mpls enable",
3010
       NO_STR
3011
       MPLS_STR
3012
       "Set mpls to be on for the interface\n")
3013
0
{
3014
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
3015
0
  struct zebra_if *if_data = ifp->info;
3016
3017
0
  if (no) {
3018
0
    dplane_intf_mpls_modify_state(ifp, false);
3019
0
    if_data->mpls = IF_ZEBRA_DATA_UNSPEC;
3020
0
  } else {
3021
0
    dplane_intf_mpls_modify_state(ifp, true);
3022
0
    if_data->mpls = IF_ZEBRA_DATA_ON;
3023
0
  }
3024
3025
0
  return CMD_SUCCESS;
3026
0
}
3027
3028
int if_multicast_unset(struct interface *ifp)
3029
0
{
3030
0
  struct zebra_if *if_data;
3031
3032
0
  if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
3033
0
    if (if_unset_flags(ifp, IFF_MULTICAST) < 0) {
3034
0
      zlog_debug("Can't unset multicast flag on interface %s",
3035
0
           ifp->name);
3036
0
      return -1;
3037
0
    }
3038
0
    if_refresh(ifp);
3039
0
  }
3040
0
  if_data = ifp->info;
3041
0
  if_data->multicast = IF_ZEBRA_DATA_OFF;
3042
3043
0
  return 0;
3044
0
}
3045
3046
DEFUN (no_multicast,
3047
       no_multicast_cmd,
3048
       "no multicast",
3049
       NO_STR
3050
       "Unset multicast flag to interface\n")
3051
0
{
3052
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
3053
0
  int ret;
3054
0
  struct zebra_if *if_data;
3055
3056
0
  if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
3057
0
    ret = if_unset_flags(ifp, IFF_MULTICAST);
3058
0
    if (ret < 0) {
3059
0
      vty_out(vty, "Can't unset multicast flag\n");
3060
0
      return CMD_WARNING_CONFIG_FAILED;
3061
0
    }
3062
0
    if_refresh(ifp);
3063
0
  }
3064
0
  if_data = ifp->info;
3065
0
  if_data->multicast = IF_ZEBRA_DATA_OFF;
3066
3067
0
  return CMD_SUCCESS;
3068
0
}
3069
3070
int if_linkdetect(struct interface *ifp, bool detect)
3071
0
{
3072
0
  int if_was_operative;
3073
3074
0
  if_was_operative = if_is_no_ptm_operative(ifp);
3075
0
  if (detect) {
3076
0
    SET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
3077
3078
    /* When linkdetection is enabled, if might come down */
3079
0
    if (!if_is_no_ptm_operative(ifp) && if_was_operative)
3080
0
      if_down(ifp);
3081
0
  } else {
3082
0
    UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
3083
3084
    /* Interface may come up after disabling link detection */
3085
0
    if (if_is_operative(ifp) && !if_was_operative)
3086
0
      if_up(ifp, true);
3087
0
  }
3088
  /* FIXME: Will defer status change forwarding if interface
3089
     does not come down! */
3090
0
  return 0;
3091
0
}
3092
3093
DEFUN(linkdetect, linkdetect_cmd, "link-detect",
3094
      "Enable link detection on interface\n")
3095
0
{
3096
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
3097
3098
0
  if_linkdetect(ifp, true);
3099
3100
0
  return CMD_SUCCESS;
3101
0
}
3102
3103
3104
DEFUN (no_linkdetect,
3105
       no_linkdetect_cmd,
3106
       "no link-detect",
3107
       NO_STR
3108
       "Disable link detection on interface\n")
3109
0
{
3110
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
3111
3112
0
  if_linkdetect(ifp, false);
3113
3114
0
  return CMD_SUCCESS;
3115
0
}
3116
3117
int if_shutdown(struct interface *ifp)
3118
0
{
3119
0
  struct zebra_if *if_data;
3120
3121
0
  if (ifp->ifindex != IFINDEX_INTERNAL) {
3122
    /* send RA lifetime of 0 before stopping. rfc4861/6.2.5 */
3123
0
    rtadv_stop_ra(ifp);
3124
0
    if (if_unset_flags(ifp, IFF_UP) < 0) {
3125
0
      zlog_debug("Can't shutdown interface %s", ifp->name);
3126
0
      return -1;
3127
0
    }
3128
0
    if_refresh(ifp);
3129
0
  }
3130
0
  if_data = ifp->info;
3131
0
  if_data->shutdown = IF_ZEBRA_DATA_ON;
3132
3133
0
  return 0;
3134
0
}
3135
3136
DEFUN (shutdown_if,
3137
       shutdown_if_cmd,
3138
       "shutdown",
3139
       "Shutdown the selected interface\n")
3140
0
{
3141
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
3142
0
  int ret;
3143
0
  struct zebra_if *if_data;
3144
3145
0
  if (ifp->ifindex != IFINDEX_INTERNAL) {
3146
    /* send RA lifetime of 0 before stopping. rfc4861/6.2.5 */
3147
0
    rtadv_stop_ra(ifp);
3148
0
    ret = if_unset_flags(ifp, IFF_UP);
3149
0
    if (ret < 0) {
3150
0
      vty_out(vty, "Can't shutdown interface\n");
3151
0
      return CMD_WARNING_CONFIG_FAILED;
3152
0
    }
3153
0
    if_refresh(ifp);
3154
0
  }
3155
0
  if_data = ifp->info;
3156
0
  if_data->shutdown = IF_ZEBRA_DATA_ON;
3157
3158
0
  return CMD_SUCCESS;
3159
0
}
3160
3161
int if_no_shutdown(struct interface *ifp)
3162
0
{
3163
0
  struct zebra_if *if_data;
3164
3165
0
  if (ifp->ifindex != IFINDEX_INTERNAL) {
3166
0
    if (if_set_flags(ifp, IFF_UP | IFF_RUNNING) < 0) {
3167
0
      zlog_debug("Can't up interface %s", ifp->name);
3168
0
      return -1;
3169
0
    }
3170
0
    if_refresh(ifp);
3171
3172
    /* Some addresses (in particular, IPv6 addresses on Linux) get
3173
     * removed when the interface goes down. They need to be
3174
     * readded.
3175
     */
3176
0
    if_addr_wakeup(ifp);
3177
0
  }
3178
3179
0
  if_data = ifp->info;
3180
0
  if_data->shutdown = IF_ZEBRA_DATA_OFF;
3181
3182
0
  return 0;
3183
0
}
3184
3185
DEFUN (no_shutdown_if,
3186
       no_shutdown_if_cmd,
3187
       "no shutdown",
3188
       NO_STR
3189
       "Shutdown the selected interface\n")
3190
0
{
3191
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
3192
0
  int ret;
3193
0
  struct zebra_if *if_data;
3194
3195
0
  if (ifp->ifindex != IFINDEX_INTERNAL) {
3196
0
    ret = if_set_flags(ifp, IFF_UP | IFF_RUNNING);
3197
0
    if (ret < 0) {
3198
0
      vty_out(vty, "Can't up interface\n");
3199
0
      return CMD_WARNING_CONFIG_FAILED;
3200
0
    }
3201
0
    if_refresh(ifp);
3202
3203
    /* Some addresses (in particular, IPv6 addresses on Linux) get
3204
     * removed when the interface goes down. They need to be
3205
     * readded.
3206
     */
3207
0
    if_addr_wakeup(ifp);
3208
0
  }
3209
3210
0
  if_data = ifp->info;
3211
0
  if_data->shutdown = IF_ZEBRA_DATA_OFF;
3212
3213
0
  return CMD_SUCCESS;
3214
0
}
3215
3216
DEFUN (bandwidth_if,
3217
       bandwidth_if_cmd,
3218
       "bandwidth (1-100000)",
3219
       "Set bandwidth informational parameter\n"
3220
       "Bandwidth in megabits\n")
3221
0
{
3222
0
  int idx_number = 1;
3223
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
3224
0
  unsigned int bandwidth;
3225
3226
0
  bandwidth = strtol(argv[idx_number]->arg, NULL, 10);
3227
3228
  /* bandwidth range is <1-100000> */
3229
0
  if (bandwidth < 1 || bandwidth > 100000) {
3230
0
    vty_out(vty, "Bandwidth is invalid\n");
3231
0
    return CMD_WARNING_CONFIG_FAILED;
3232
0
  }
3233
3234
0
  ifp->bandwidth = bandwidth;
3235
3236
  /* force protocols to recalculate routes due to cost change */
3237
0
  if (if_is_operative(ifp))
3238
0
    zebra_interface_up_update(ifp);
3239
3240
0
  return CMD_SUCCESS;
3241
0
}
3242
3243
DEFUN (no_bandwidth_if,
3244
       no_bandwidth_if_cmd,
3245
       "no bandwidth [(1-100000)]",
3246
       NO_STR
3247
       "Set bandwidth informational parameter\n"
3248
       "Bandwidth in megabits\n")
3249
0
{
3250
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
3251
3252
0
  ifp->bandwidth = 0;
3253
3254
  /* force protocols to recalculate routes due to cost change */
3255
0
  if (if_is_operative(ifp))
3256
0
    zebra_interface_up_update(ifp);
3257
3258
0
  return CMD_SUCCESS;
3259
0
}
3260
3261
3262
struct cmd_node link_params_node = {
3263
  .name = "link-params",
3264
  .node = LINK_PARAMS_NODE,
3265
  .parent_node = INTERFACE_NODE,
3266
  .prompt = "%s(config-link-params)# ",
3267
  .no_xpath = true,
3268
};
3269
3270
static void link_param_cmd_set_uint32(struct interface *ifp, uint32_t *field,
3271
              uint32_t type, uint32_t value)
3272
0
{
3273
  /* Update field as needed */
3274
0
  if (IS_PARAM_UNSET(ifp->link_params, type) || *field != value) {
3275
0
    *field = value;
3276
0
    SET_PARAM(ifp->link_params, type);
3277
3278
    /* force protocols to update LINK STATE due to parameters change
3279
     */
3280
0
    if (if_is_operative(ifp))
3281
0
      zebra_interface_parameters_update(ifp);
3282
0
  }
3283
0
}
3284
static void link_param_cmd_set_float(struct interface *ifp, float *field,
3285
             uint32_t type, float value)
3286
0
{
3287
3288
  /* Update field as needed */
3289
0
  if (IS_PARAM_UNSET(ifp->link_params, type) || *field != value) {
3290
0
    *field = value;
3291
0
    SET_PARAM(ifp->link_params, type);
3292
3293
    /* force protocols to update LINK STATE due to parameters change
3294
     */
3295
0
    if (if_is_operative(ifp))
3296
0
      zebra_interface_parameters_update(ifp);
3297
0
  }
3298
0
}
3299
3300
static void link_param_cmd_unset(struct interface *ifp, uint32_t type)
3301
0
{
3302
0
  if (ifp->link_params == NULL)
3303
0
    return;
3304
3305
  /* Unset field */
3306
0
  UNSET_PARAM(ifp->link_params, type);
3307
3308
  /* force protocols to update LINK STATE due to parameters change */
3309
0
  if (if_is_operative(ifp))
3310
0
    zebra_interface_parameters_update(ifp);
3311
0
}
3312
3313
DEFUN_NOSH (link_params,
3314
       link_params_cmd,
3315
       "link-params",
3316
       LINK_PARAMS_STR)
3317
0
{
3318
  /* vty->qobj_index stays the same @ interface pointer */
3319
0
  vty->node = LINK_PARAMS_NODE;
3320
3321
0
  return CMD_SUCCESS;
3322
0
}
3323
3324
DEFUN_NOSH (exit_link_params,
3325
       exit_link_params_cmd,
3326
       "exit-link-params",
3327
       "Exit from Link Params configuration mode\n")
3328
0
{
3329
0
  if (vty->node == LINK_PARAMS_NODE)
3330
0
    vty->node = INTERFACE_NODE;
3331
0
  return CMD_SUCCESS;
3332
0
}
3333
3334
/* Specific Traffic Engineering parameters commands */
3335
DEFUN (link_params_enable,
3336
       link_params_enable_cmd,
3337
       "enable",
3338
       "Activate link parameters on this interface\n")
3339
0
{
3340
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
3341
3342
  /* This command could be issue at startup, when activate MPLS TE */
3343
  /* on a new interface or after a ON / OFF / ON toggle */
3344
  /* In all case, TE parameters are reset to their default factory */
3345
0
  if (IS_ZEBRA_DEBUG_EVENT || IS_ZEBRA_DEBUG_MPLS)
3346
0
    zlog_debug(
3347
0
      "Link-params: enable TE link parameters on interface %s",
3348
0
      ifp->name);
3349
3350
0
  if (!if_link_params_get(ifp))
3351
0
    if_link_params_enable(ifp);
3352
3353
  /* force protocols to update LINK STATE due to parameters change */
3354
0
  if (if_is_operative(ifp))
3355
0
    zebra_interface_parameters_update(ifp);
3356
3357
0
  return CMD_SUCCESS;
3358
0
}
3359
3360
DEFUN (no_link_params_enable,
3361
       no_link_params_enable_cmd,
3362
       "no enable",
3363
       NO_STR
3364
       "Disable link parameters on this interface\n")
3365
0
{
3366
0
  char xpath[XPATH_MAXLEN];
3367
0
  int ret;
3368
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
3369
3370
0
  if (IS_ZEBRA_DEBUG_EVENT || IS_ZEBRA_DEBUG_MPLS)
3371
0
    zlog_debug("MPLS-TE: disable TE link parameters on interface %s",
3372
0
         ifp->name);
3373
3374
0
  if_link_params_free(ifp);
3375
3376
0
  snprintf(
3377
0
    xpath, sizeof(xpath),
3378
0
    "/frr-interface:lib/interface[name='%s']/frr-zebra:zebra/link-params/affinities",
3379
0
    ifp->name);
3380
0
  if (yang_dnode_exists(running_config->dnode, xpath))
3381
0
    nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
3382
3383
0
  ret = nb_cli_apply_changes(vty, NULL);
3384
3385
0
  if (ret != CMD_SUCCESS)
3386
0
    return ret;
3387
3388
  /* force protocols to update LINK STATE due to parameters change */
3389
0
  if (if_is_operative(ifp))
3390
0
    zebra_interface_parameters_update(ifp);
3391
3392
0
  return CMD_SUCCESS;
3393
0
}
3394
3395
/* STANDARD TE metrics */
3396
DEFUN (link_params_metric,
3397
       link_params_metric_cmd,
3398
       "metric (0-4294967295)",
3399
       "Link metric for MPLS-TE purpose\n"
3400
       "Metric value in decimal\n")
3401
0
{
3402
0
  int idx_number = 1;
3403
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
3404
0
  struct if_link_params *iflp = if_link_params_get(ifp);
3405
0
  uint32_t metric;
3406
3407
0
  metric = strtoul(argv[idx_number]->arg, NULL, 10);
3408
3409
0
  if (!iflp)
3410
0
    iflp = if_link_params_enable(ifp);
3411
3412
  /* Update TE metric if needed */
3413
0
  link_param_cmd_set_uint32(ifp, &iflp->te_metric, LP_TE_METRIC, metric);
3414
3415
0
  return CMD_SUCCESS;
3416
0
}
3417
3418
DEFUN (no_link_params_metric,
3419
       no_link_params_metric_cmd,
3420
       "no metric",
3421
       NO_STR
3422
       "Disable Link Metric on this interface\n")
3423
0
{
3424
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
3425
3426
  /* Unset TE Metric */
3427
0
  link_param_cmd_unset(ifp, LP_TE_METRIC);
3428
3429
0
  return CMD_SUCCESS;
3430
0
}
3431
3432
DEFUN (link_params_maxbw,
3433
       link_params_maxbw_cmd,
3434
       "max-bw BANDWIDTH",
3435
       "Maximum bandwidth that can be used\n"
3436
       "Bytes/second (IEEE floating point format)\n")
3437
0
{
3438
0
  int idx_bandwidth = 1;
3439
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
3440
0
  struct if_link_params *iflp = if_link_params_get(ifp);
3441
3442
0
  float bw;
3443
3444
0
  if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
3445
0
    vty_out(vty, "link_params_maxbw: fscanf: %s\n",
3446
0
      safe_strerror(errno));
3447
0
    return CMD_WARNING_CONFIG_FAILED;
3448
0
  }
3449
3450
  /* Check that Maximum bandwidth is not lower than other bandwidth
3451
   * parameters */
3452
0
  if (iflp && ((bw <= iflp->max_rsv_bw) || (bw <= iflp->unrsv_bw[0]) ||
3453
0
         (bw <= iflp->unrsv_bw[1]) || (bw <= iflp->unrsv_bw[2]) ||
3454
0
         (bw <= iflp->unrsv_bw[3]) || (bw <= iflp->unrsv_bw[4]) ||
3455
0
         (bw <= iflp->unrsv_bw[5]) || (bw <= iflp->unrsv_bw[6]) ||
3456
0
         (bw <= iflp->unrsv_bw[7]) || (bw <= iflp->ava_bw) ||
3457
0
         (bw <= iflp->res_bw) || (bw <= iflp->use_bw))) {
3458
0
    vty_out(vty,
3459
0
      "Maximum Bandwidth could not be lower than others bandwidth\n");
3460
0
    return CMD_WARNING_CONFIG_FAILED;
3461
0
  }
3462
3463
0
  if (!iflp)
3464
0
    iflp = if_link_params_enable(ifp);
3465
3466
  /* Update Maximum Bandwidth if needed */
3467
0
  link_param_cmd_set_float(ifp, &iflp->max_bw, LP_MAX_BW, bw);
3468
3469
0
  return CMD_SUCCESS;
3470
0
}
3471
3472
DEFUN (link_params_max_rsv_bw,
3473
       link_params_max_rsv_bw_cmd,
3474
       "max-rsv-bw BANDWIDTH",
3475
       "Maximum bandwidth that may be reserved\n"
3476
       "Bytes/second (IEEE floating point format)\n")
3477
0
{
3478
0
  int idx_bandwidth = 1;
3479
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
3480
0
  struct if_link_params *iflp = if_link_params_get(ifp);
3481
0
  float bw;
3482
3483
0
  if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
3484
0
    vty_out(vty, "link_params_max_rsv_bw: fscanf: %s\n",
3485
0
      safe_strerror(errno));
3486
0
    return CMD_WARNING_CONFIG_FAILED;
3487
0
  }
3488
3489
  /* Check that bandwidth is not greater than maximum bandwidth parameter
3490
   */
3491
0
  if (iflp && bw > iflp->max_bw) {
3492
0
    vty_out(vty,
3493
0
      "Maximum Reservable Bandwidth could not be greater than Maximum Bandwidth (%g)\n",
3494
0
      iflp->max_bw);
3495
0
    return CMD_WARNING_CONFIG_FAILED;
3496
0
  }
3497
3498
0
  if (!iflp)
3499
0
    iflp = if_link_params_enable(ifp);
3500
3501
  /* Update Maximum Reservable Bandwidth if needed */
3502
0
  link_param_cmd_set_float(ifp, &iflp->max_rsv_bw, LP_MAX_RSV_BW, bw);
3503
3504
0
  return CMD_SUCCESS;
3505
0
}
3506
3507
DEFUN (link_params_unrsv_bw,
3508
       link_params_unrsv_bw_cmd,
3509
       "unrsv-bw (0-7) BANDWIDTH",
3510
       "Unreserved bandwidth at each priority level\n"
3511
       "Priority\n"
3512
       "Bytes/second (IEEE floating point format)\n")
3513
0
{
3514
0
  int idx_number = 1;
3515
0
  int idx_bandwidth = 2;
3516
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
3517
0
  struct if_link_params *iflp = if_link_params_get(ifp);
3518
0
  int priority;
3519
0
  float bw;
3520
3521
  /* We don't have to consider about range check here. */
3522
0
  if (sscanf(argv[idx_number]->arg, "%d", &priority) != 1) {
3523
0
    vty_out(vty, "link_params_unrsv_bw: fscanf: %s\n",
3524
0
      safe_strerror(errno));
3525
0
    return CMD_WARNING_CONFIG_FAILED;
3526
0
  }
3527
3528
0
  if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
3529
0
    vty_out(vty, "link_params_unrsv_bw: fscanf: %s\n",
3530
0
      safe_strerror(errno));
3531
0
    return CMD_WARNING_CONFIG_FAILED;
3532
0
  }
3533
3534
  /* Check that bandwidth is not greater than maximum bandwidth parameter
3535
   */
3536
0
  if (iflp && bw > iflp->max_bw) {
3537
0
    vty_out(vty,
3538
0
      "UnReserved Bandwidth could not be greater than Maximum Bandwidth (%g)\n",
3539
0
      iflp->max_bw);
3540
0
    return CMD_WARNING_CONFIG_FAILED;
3541
0
  }
3542
3543
0
  if (!iflp)
3544
0
    iflp = if_link_params_enable(ifp);
3545
3546
  /* Update Unreserved Bandwidth if needed */
3547
0
  link_param_cmd_set_float(ifp, &iflp->unrsv_bw[priority], LP_UNRSV_BW,
3548
0
         bw);
3549
3550
0
  return CMD_SUCCESS;
3551
0
}
3552
3553
DEFPY_YANG(link_params_admin_grp, link_params_admin_grp_cmd,
3554
     "admin-grp BITPATTERN",
3555
     "Administrative group membership\n"
3556
     "32-bit Hexadecimal value (e.g. 0xa1)\n")
3557
0
{
3558
0
  char xpath[XPATH_MAXLEN];
3559
0
  int idx_bitpattern = 1;
3560
0
  unsigned long value;
3561
0
  char value_str[11];
3562
3563
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
3564
3565
0
  snprintf(
3566
0
    xpath, sizeof(xpath),
3567
0
    "/frr-interface:lib/interface[name='%s']/frr-zebra:zebra/link-params/affinities",
3568
0
    ifp->name);
3569
0
  if (yang_dnode_exists(running_config->dnode, xpath)) {
3570
0
    vty_out(vty,
3571
0
      "cannot use the admin-grp command when affinity is set\n");
3572
0
    return CMD_WARNING_CONFIG_FAILED;
3573
0
  }
3574
3575
0
  if (sscanf(argv[idx_bitpattern]->arg, "0x%lx", &value) != 1) {
3576
0
    vty_out(vty, "link_params_admin_grp: fscanf: %s\n",
3577
0
      safe_strerror(errno));
3578
0
    return CMD_WARNING_CONFIG_FAILED;
3579
0
  }
3580
3581
0
  if (value > 0xFFFFFFFF) {
3582
0
    vty_out(vty, "value must be not be superior to 0xFFFFFFFF\n");
3583
0
    return CMD_WARNING_CONFIG_FAILED;
3584
0
  }
3585
3586
0
  snprintf(value_str, sizeof(value_str), "%ld", value);
3587
3588
0
  nb_cli_enqueue_change(
3589
0
    vty, "./frr-zebra:zebra/link-params/legacy-admin-group",
3590
0
    NB_OP_MODIFY, value_str);
3591
3592
0
  return nb_cli_apply_changes(vty, NULL);
3593
0
}
3594
3595
DEFPY_YANG(no_link_params_admin_grp, no_link_params_admin_grp_cmd,
3596
     "no admin-grp",
3597
     NO_STR "Disable Administrative group membership on this interface\n")
3598
0
{
3599
0
  nb_cli_enqueue_change(
3600
0
    vty, "./frr-zebra:zebra/link-params/legacy-admin-group",
3601
0
    NB_OP_DESTROY, NULL);
3602
3603
0
  return nb_cli_apply_changes(vty, NULL);
3604
0
}
3605
3606
/* RFC5392 & RFC5316: INTER-AS */
3607
DEFUN (link_params_inter_as,
3608
       link_params_inter_as_cmd,
3609
       "neighbor A.B.C.D as (1-4294967295)",
3610
       "Configure remote ASBR information (Neighbor IP address and AS number)\n"
3611
       "Remote IP address in dot decimal A.B.C.D\n"
3612
       "Remote AS number\n"
3613
       "AS number in the range <1-4294967295>\n")
3614
0
{
3615
0
  int idx_ipv4 = 1;
3616
0
  int idx_number = 3;
3617
3618
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
3619
0
  struct if_link_params *iflp = if_link_params_get(ifp);
3620
0
  struct in_addr addr;
3621
0
  uint32_t as;
3622
3623
0
  if (!inet_aton(argv[idx_ipv4]->arg, &addr)) {
3624
0
    vty_out(vty, "Please specify Router-Addr by A.B.C.D\n");
3625
0
    return CMD_WARNING_CONFIG_FAILED;
3626
0
  }
3627
3628
0
  if (!iflp)
3629
0
    iflp = if_link_params_enable(ifp);
3630
3631
0
  as = strtoul(argv[idx_number]->arg, NULL, 10);
3632
3633
  /* Update Remote IP and Remote AS fields if needed */
3634
0
  if (IS_PARAM_UNSET(iflp, LP_RMT_AS) || iflp->rmt_as != as
3635
0
      || iflp->rmt_ip.s_addr != addr.s_addr) {
3636
3637
0
    iflp->rmt_as = as;
3638
0
    iflp->rmt_ip.s_addr = addr.s_addr;
3639
0
    SET_PARAM(iflp, LP_RMT_AS);
3640
3641
    /* force protocols to update LINK STATE due to parameters change
3642
     */
3643
0
    if (if_is_operative(ifp))
3644
0
      zebra_interface_parameters_update(ifp);
3645
0
  }
3646
0
  return CMD_SUCCESS;
3647
0
}
3648
3649
DEFUN (no_link_params_inter_as,
3650
       no_link_params_inter_as_cmd,
3651
       "no neighbor",
3652
       NO_STR
3653
       "Remove Neighbor IP address and AS number for Inter-AS TE\n")
3654
0
{
3655
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
3656
0
  struct if_link_params *iflp = if_link_params_get(ifp);
3657
3658
0
  if (!iflp)
3659
0
    return CMD_SUCCESS;
3660
3661
  /* Reset Remote IP and AS neighbor */
3662
0
  iflp->rmt_as = 0;
3663
0
  iflp->rmt_ip.s_addr = 0;
3664
0
  UNSET_PARAM(iflp, LP_RMT_AS);
3665
3666
  /* force protocols to update LINK STATE due to parameters change */
3667
0
  if (if_is_operative(ifp))
3668
0
    zebra_interface_parameters_update(ifp);
3669
3670
0
  return CMD_SUCCESS;
3671
0
}
3672
3673
/* RFC7471: OSPF Traffic Engineering (TE) Metric extensions &
3674
 * draft-ietf-isis-metric-extensions-07.txt */
3675
DEFUN (link_params_delay,
3676
       link_params_delay_cmd,
3677
       "delay (0-16777215) [min (0-16777215) max (0-16777215)]",
3678
       "Unidirectional Average Link Delay\n"
3679
       "Average delay in micro-second as decimal (0...16777215)\n"
3680
       "Minimum delay\n"
3681
       "Minimum delay in micro-second as decimal (0...16777215)\n"
3682
       "Maximum delay\n"
3683
       "Maximum delay in micro-second as decimal (0...16777215)\n")
3684
0
{
3685
  /* Get and Check new delay values */
3686
0
  uint32_t delay = 0, low = 0, high = 0;
3687
0
  delay = strtoul(argv[1]->arg, NULL, 10);
3688
0
  if (argc == 6) {
3689
0
    low = strtoul(argv[3]->arg, NULL, 10);
3690
0
    high = strtoul(argv[5]->arg, NULL, 10);
3691
0
  }
3692
3693
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
3694
0
  struct if_link_params *iflp = if_link_params_get(ifp);
3695
0
  uint8_t update = 0;
3696
3697
0
  if (argc == 2) {
3698
    /*
3699
     * Check new delay value against old Min and Max delays if set
3700
     *
3701
     * RFC 7471 Section 4.2.7:
3702
     *    It is possible for min delay and max delay to be
3703
     *    the same value.
3704
     *
3705
     * Therefore, it is also allowed that the average
3706
     * delay be equal to the min delay or max delay.
3707
     */
3708
0
    if (iflp && IS_PARAM_SET(iflp, LP_MM_DELAY) &&
3709
0
        (delay < iflp->min_delay || delay > iflp->max_delay)) {
3710
0
      vty_out(vty,
3711
0
        "Average delay should be in range Min (%d) - Max (%d) delay\n",
3712
0
        iflp->min_delay, iflp->max_delay);
3713
0
      return CMD_WARNING_CONFIG_FAILED;
3714
0
    }
3715
3716
0
    if (!iflp)
3717
0
      iflp = if_link_params_enable(ifp);
3718
3719
    /* Update delay if value is not set or change */
3720
0
    if (IS_PARAM_UNSET(iflp, LP_DELAY) || iflp->av_delay != delay) {
3721
0
      iflp->av_delay = delay;
3722
0
      SET_PARAM(iflp, LP_DELAY);
3723
0
      update = 1;
3724
0
    }
3725
    /* Unset Min and Max delays if already set */
3726
0
    if (IS_PARAM_SET(iflp, LP_MM_DELAY)) {
3727
0
      iflp->min_delay = 0;
3728
0
      iflp->max_delay = 0;
3729
0
      UNSET_PARAM(iflp, LP_MM_DELAY);
3730
0
      update = 1;
3731
0
    }
3732
0
  } else {
3733
    /*
3734
     * Check new delays value coherency. See above note
3735
     * regarding average delay equal to min/max allowed
3736
     */
3737
0
    if (delay < low || delay > high) {
3738
0
      vty_out(vty,
3739
0
        "Average delay should be in range Min (%d) - Max (%d) delay\n",
3740
0
        low, high);
3741
0
      return CMD_WARNING_CONFIG_FAILED;
3742
0
    }
3743
3744
0
    if (!iflp)
3745
0
      iflp = if_link_params_enable(ifp);
3746
3747
    /* Update Delays if needed */
3748
0
    if (IS_PARAM_UNSET(iflp, LP_DELAY)
3749
0
        || IS_PARAM_UNSET(iflp, LP_MM_DELAY)
3750
0
        || iflp->av_delay != delay || iflp->min_delay != low
3751
0
        || iflp->max_delay != high) {
3752
0
      iflp->av_delay = delay;
3753
0
      SET_PARAM(iflp, LP_DELAY);
3754
0
      iflp->min_delay = low;
3755
0
      iflp->max_delay = high;
3756
0
      SET_PARAM(iflp, LP_MM_DELAY);
3757
0
      update = 1;
3758
0
    }
3759
0
  }
3760
3761
  /* force protocols to update LINK STATE due to parameters change */
3762
0
  if (update == 1 && if_is_operative(ifp))
3763
0
    zebra_interface_parameters_update(ifp);
3764
3765
0
  return CMD_SUCCESS;
3766
0
}
3767
3768
DEFUN (no_link_params_delay,
3769
       no_link_params_delay_cmd,
3770
       "no delay",
3771
       NO_STR
3772
       "Disable Unidirectional Average, Min & Max Link Delay on this interface\n")
3773
0
{
3774
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
3775
0
  struct if_link_params *iflp = if_link_params_get(ifp);
3776
3777
0
  if (!iflp)
3778
0
    return CMD_SUCCESS;
3779
3780
  /* Unset Delays */
3781
0
  iflp->av_delay = 0;
3782
0
  UNSET_PARAM(iflp, LP_DELAY);
3783
0
  iflp->min_delay = 0;
3784
0
  iflp->max_delay = 0;
3785
0
  UNSET_PARAM(iflp, LP_MM_DELAY);
3786
3787
  /* force protocols to update LINK STATE due to parameters change */
3788
0
  if (if_is_operative(ifp))
3789
0
    zebra_interface_parameters_update(ifp);
3790
3791
0
  return CMD_SUCCESS;
3792
0
}
3793
3794
DEFUN (link_params_delay_var,
3795
       link_params_delay_var_cmd,
3796
       "delay-variation (0-16777215)",
3797
       "Unidirectional Link Delay Variation\n"
3798
       "delay variation in micro-second as decimal (0...16777215)\n")
3799
0
{
3800
0
  int idx_number = 1;
3801
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
3802
0
  struct if_link_params *iflp = if_link_params_get(ifp);
3803
0
  uint32_t value;
3804
3805
0
  value = strtoul(argv[idx_number]->arg, NULL, 10);
3806
3807
0
  if (!iflp)
3808
0
    iflp = if_link_params_enable(ifp);
3809
3810
  /* Update Delay Variation if needed */
3811
0
  link_param_cmd_set_uint32(ifp, &iflp->delay_var, LP_DELAY_VAR, value);
3812
3813
0
  return CMD_SUCCESS;
3814
0
}
3815
3816
DEFUN (no_link_params_delay_var,
3817
       no_link_params_delay_var_cmd,
3818
       "no delay-variation",
3819
       NO_STR
3820
       "Disable Unidirectional Delay Variation on this interface\n")
3821
0
{
3822
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
3823
3824
  /* Unset Delay Variation */
3825
0
  link_param_cmd_unset(ifp, LP_DELAY_VAR);
3826
3827
0
  return CMD_SUCCESS;
3828
0
}
3829
3830
DEFUN (link_params_pkt_loss,
3831
       link_params_pkt_loss_cmd,
3832
       "packet-loss PERCENTAGE",
3833
       "Unidirectional Link Packet Loss\n"
3834
       "percentage of total traffic by 0.000003% step and less than 50.331642%\n")
3835
0
{
3836
0
  int idx_percentage = 1;
3837
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
3838
0
  struct if_link_params *iflp = if_link_params_get(ifp);
3839
0
  float fval;
3840
3841
0
  if (sscanf(argv[idx_percentage]->arg, "%g", &fval) != 1) {
3842
0
    vty_out(vty, "link_params_pkt_loss: fscanf: %s\n",
3843
0
      safe_strerror(errno));
3844
0
    return CMD_WARNING_CONFIG_FAILED;
3845
0
  }
3846
3847
0
  if (fval > MAX_PKT_LOSS)
3848
0
    fval = MAX_PKT_LOSS;
3849
3850
0
  if (!iflp)
3851
0
    iflp = if_link_params_enable(ifp);
3852
3853
  /* Update Packet Loss if needed */
3854
0
  link_param_cmd_set_float(ifp, &iflp->pkt_loss, LP_PKT_LOSS, fval);
3855
3856
0
  return CMD_SUCCESS;
3857
0
}
3858
3859
DEFUN (no_link_params_pkt_loss,
3860
       no_link_params_pkt_loss_cmd,
3861
       "no packet-loss",
3862
       NO_STR
3863
       "Disable Unidirectional Link Packet Loss on this interface\n")
3864
0
{
3865
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
3866
3867
  /* Unset Packet Loss */
3868
0
  link_param_cmd_unset(ifp, LP_PKT_LOSS);
3869
3870
0
  return CMD_SUCCESS;
3871
0
}
3872
3873
DEFUN (link_params_res_bw,
3874
       link_params_res_bw_cmd,
3875
       "res-bw BANDWIDTH",
3876
       "Unidirectional Residual Bandwidth\n"
3877
       "Bytes/second (IEEE floating point format)\n")
3878
0
{
3879
0
  int idx_bandwidth = 1;
3880
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
3881
0
  struct if_link_params *iflp = if_link_params_get(ifp);
3882
0
  float bw;
3883
3884
0
  if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
3885
0
    vty_out(vty, "link_params_res_bw: fscanf: %s\n",
3886
0
      safe_strerror(errno));
3887
0
    return CMD_WARNING_CONFIG_FAILED;
3888
0
  }
3889
3890
  /* Check that bandwidth is not greater than maximum bandwidth parameter
3891
   */
3892
0
  if (iflp && bw > iflp->max_bw) {
3893
0
    vty_out(vty,
3894
0
      "Residual Bandwidth could not be greater than Maximum Bandwidth (%g)\n",
3895
0
      iflp->max_bw);
3896
0
    return CMD_WARNING_CONFIG_FAILED;
3897
0
  }
3898
3899
0
  if (!iflp)
3900
0
    iflp = if_link_params_enable(ifp);
3901
3902
  /* Update Residual Bandwidth if needed */
3903
0
  link_param_cmd_set_float(ifp, &iflp->res_bw, LP_RES_BW, bw);
3904
3905
0
  return CMD_SUCCESS;
3906
0
}
3907
3908
DEFUN (no_link_params_res_bw,
3909
       no_link_params_res_bw_cmd,
3910
       "no res-bw",
3911
       NO_STR
3912
       "Disable Unidirectional Residual Bandwidth on this interface\n")
3913
0
{
3914
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
3915
3916
  /* Unset Residual Bandwidth */
3917
0
  link_param_cmd_unset(ifp, LP_RES_BW);
3918
3919
0
  return CMD_SUCCESS;
3920
0
}
3921
3922
DEFUN (link_params_ava_bw,
3923
       link_params_ava_bw_cmd,
3924
       "ava-bw BANDWIDTH",
3925
       "Unidirectional Available Bandwidth\n"
3926
       "Bytes/second (IEEE floating point format)\n")
3927
0
{
3928
0
  int idx_bandwidth = 1;
3929
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
3930
0
  struct if_link_params *iflp = if_link_params_get(ifp);
3931
0
  float bw;
3932
3933
0
  if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
3934
0
    vty_out(vty, "link_params_ava_bw: fscanf: %s\n",
3935
0
      safe_strerror(errno));
3936
0
    return CMD_WARNING_CONFIG_FAILED;
3937
0
  }
3938
3939
  /* Check that bandwidth is not greater than maximum bandwidth parameter
3940
   */
3941
0
  if (iflp && bw > iflp->max_bw) {
3942
0
    vty_out(vty,
3943
0
      "Available Bandwidth could not be greater than Maximum Bandwidth (%g)\n",
3944
0
      iflp->max_bw);
3945
0
    return CMD_WARNING_CONFIG_FAILED;
3946
0
  }
3947
3948
0
  if (!iflp)
3949
0
    iflp = if_link_params_enable(ifp);
3950
3951
  /* Update Residual Bandwidth if needed */
3952
0
  link_param_cmd_set_float(ifp, &iflp->ava_bw, LP_AVA_BW, bw);
3953
3954
0
  return CMD_SUCCESS;
3955
0
}
3956
3957
DEFUN (no_link_params_ava_bw,
3958
       no_link_params_ava_bw_cmd,
3959
       "no ava-bw",
3960
       NO_STR
3961
       "Disable Unidirectional Available Bandwidth on this interface\n")
3962
0
{
3963
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
3964
3965
  /* Unset Available Bandwidth */
3966
0
  link_param_cmd_unset(ifp, LP_AVA_BW);
3967
3968
0
  return CMD_SUCCESS;
3969
0
}
3970
3971
DEFUN (link_params_use_bw,
3972
       link_params_use_bw_cmd,
3973
       "use-bw BANDWIDTH",
3974
       "Unidirectional Utilised Bandwidth\n"
3975
       "Bytes/second (IEEE floating point format)\n")
3976
0
{
3977
0
  int idx_bandwidth = 1;
3978
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
3979
0
  struct if_link_params *iflp = if_link_params_get(ifp);
3980
0
  float bw;
3981
3982
0
  if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
3983
0
    vty_out(vty, "link_params_use_bw: fscanf: %s\n",
3984
0
      safe_strerror(errno));
3985
0
    return CMD_WARNING_CONFIG_FAILED;
3986
0
  }
3987
3988
  /* Check that bandwidth is not greater than maximum bandwidth parameter
3989
   */
3990
0
  if (iflp && bw > iflp->max_bw) {
3991
0
    vty_out(vty,
3992
0
      "Utilised Bandwidth could not be greater than Maximum Bandwidth (%g)\n",
3993
0
      iflp->max_bw);
3994
0
    return CMD_WARNING_CONFIG_FAILED;
3995
0
  }
3996
3997
0
  if (!iflp)
3998
0
    iflp = if_link_params_enable(ifp);
3999
4000
  /* Update Utilized Bandwidth if needed */
4001
0
  link_param_cmd_set_float(ifp, &iflp->use_bw, LP_USE_BW, bw);
4002
4003
0
  return CMD_SUCCESS;
4004
0
}
4005
4006
DEFUN (no_link_params_use_bw,
4007
       no_link_params_use_bw_cmd,
4008
       "no use-bw",
4009
       NO_STR
4010
       "Disable Unidirectional Utilised Bandwidth on this interface\n")
4011
0
{
4012
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
4013
4014
  /* Unset Utilised Bandwidth */
4015
0
  link_param_cmd_unset(ifp, LP_USE_BW);
4016
4017
0
  return CMD_SUCCESS;
4018
0
}
4019
4020
static int ag_change(struct vty *vty, int argc, struct cmd_token **argv,
4021
         const char *xpath, bool no, int start_idx)
4022
0
{
4023
0
  for (int i = start_idx; i < argc; i++)
4024
0
    nb_cli_enqueue_change(vty, xpath,
4025
0
              no ? NB_OP_DESTROY : NB_OP_CREATE,
4026
0
              argv[i]->arg);
4027
0
  return nb_cli_apply_changes(vty, NULL);
4028
0
}
4029
4030
/*
4031
 * XPath:
4032
 * /frr-interface:lib/interface/frr-zebra:zebra/link-params/affinities/affinity
4033
 */
4034
DEFPY_YANG(link_params_affinity, link_params_affinity_cmd,
4035
     "[no] affinity NAME...",
4036
     NO_STR
4037
     "Interface affinities\n"
4038
     "Affinity names\n")
4039
0
{
4040
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
4041
0
  char xpath[XPATH_MAXLEN];
4042
4043
0
  snprintf(
4044
0
    xpath, sizeof(xpath),
4045
0
    "/frr-interface:lib/interface[name='%s']/frr-zebra:zebra/link-params/legacy-admin-group",
4046
0
    ifp->name);
4047
0
  if (yang_dnode_exists(running_config->dnode, xpath)) {
4048
0
    vty_out(vty,
4049
0
      "cannot use the affinity command when admin-grp is set\n");
4050
0
    return CMD_WARNING_CONFIG_FAILED;
4051
0
  }
4052
4053
0
  return ag_change(vty, argc, argv,
4054
0
       "./frr-zebra:zebra/link-params/affinities/affinity",
4055
0
       no, no ? 2 : 1);
4056
0
}
4057
4058
4059
/*
4060
 * XPath:
4061
 * /frr-interface:lib/interface/frr-zebra:zebra/link-params/affinities/affinity-mode
4062
 */
4063
DEFPY_YANG(link_params_affinity_mode, link_params_affinity_mode_cmd,
4064
     "affinity-mode <standard|extended|both>$affmode",
4065
     "Interface affinity mode\n"
4066
     "Standard Admin-Group only RFC3630,5305,5329 (default)\n"
4067
     "Extended Admin-Group only RFC7308\n"
4068
     "Standard and extended Admin-Group format\n")
4069
0
{
4070
0
  const char *xpath = "./frr-zebra:zebra/link-params/affinity-mode";
4071
4072
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, affmode);
4073
4074
0
  return nb_cli_apply_changes(vty, NULL);
4075
0
}
4076
4077
DEFPY_YANG(no_link_params_affinity_mode, no_link_params_affinity_mode_cmd,
4078
     "no affinity-mode [<standard|extended|both>]",
4079
     NO_STR
4080
     "Interface affinity mode\n"
4081
     "Standard Admin-Group only RFC3630,5305,5329 (default)\n"
4082
     "Extended Admin-Group only RFC7308\n"
4083
     "Standard and extended Admin-Group format\n")
4084
0
{
4085
0
  const char *xpath = "./frr-zebra:zebra/link-params/affinity-mode";
4086
4087
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, "standard");
4088
4089
0
  return nb_cli_apply_changes(vty, NULL);
4090
0
}
4091
4092
static int ag_iter_cb(const struct lyd_node *dnode, void *arg)
4093
0
{
4094
0
  struct vty *vty = (struct vty *)arg;
4095
4096
0
  vty_out(vty, " %s", yang_dnode_get_string(dnode, "."));
4097
0
  return YANG_ITER_CONTINUE;
4098
0
}
4099
4100
void cli_show_legacy_admin_group(struct vty *vty, const struct lyd_node *dnode,
4101
         bool show_defaults)
4102
0
{
4103
0
  if (!yang_dnode_exists(dnode, "./legacy-admin-group"))
4104
0
    return;
4105
4106
0
  vty_out(vty, "  admin-group 0x%x\n",
4107
0
    yang_dnode_get_uint32(dnode, "./legacy-admin-group"));
4108
0
}
4109
4110
void cli_show_affinity_mode(struct vty *vty, const struct lyd_node *dnode,
4111
          bool show_defaults)
4112
0
{
4113
0
  enum affinity_mode affinity_mode = yang_dnode_get_enum(dnode, ".");
4114
4115
0
  if (affinity_mode == AFFINITY_MODE_STANDARD)
4116
0
    vty_out(vty, "  affinity-mode standard\n");
4117
0
  else if (affinity_mode == AFFINITY_MODE_BOTH)
4118
0
    vty_out(vty, "  affinity-mode both\n");
4119
0
}
4120
4121
void cli_show_affinity(struct vty *vty, const struct lyd_node *dnode,
4122
           bool show_defaults)
4123
0
{
4124
0
  if (!yang_dnode_exists(dnode, "./affinity"))
4125
0
    return;
4126
4127
0
  vty_out(vty, "  affinity");
4128
0
  yang_dnode_iterate(ag_iter_cb, vty, dnode, "./affinity");
4129
0
  vty_out(vty, "\n");
4130
0
}
4131
4132
int if_ip_address_install(struct interface *ifp, struct prefix *prefix,
4133
        const char *label, struct prefix *pp)
4134
0
{
4135
0
  struct zebra_if *if_data;
4136
0
  struct prefix_ipv4 lp;
4137
0
  struct prefix_ipv4 *p;
4138
0
  struct connected *ifc;
4139
0
  enum zebra_dplane_result dplane_res;
4140
4141
0
  if_data = ifp->info;
4142
4143
0
  lp.family = prefix->family;
4144
0
  lp.prefix = prefix->u.prefix4;
4145
0
  lp.prefixlen = prefix->prefixlen;
4146
0
  apply_mask_ipv4(&lp);
4147
4148
0
  ifc = connected_check_ptp(ifp, &lp, pp ? pp : NULL);
4149
0
  if (!ifc) {
4150
0
    ifc = connected_new();
4151
0
    ifc->ifp = ifp;
4152
4153
    /* Address. */
4154
0
    p = prefix_ipv4_new();
4155
0
    *p = lp;
4156
0
    ifc->address = (struct prefix *)p;
4157
4158
0
    if (pp) {
4159
0
      SET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
4160
0
      p = prefix_ipv4_new();
4161
0
      *p = *(struct prefix_ipv4 *)pp;
4162
0
      ifc->destination = (struct prefix *)p;
4163
0
    }
4164
4165
    /* Label. */
4166
0
    if (label)
4167
0
      ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
4168
4169
    /* Add to linked list. */
4170
0
    listnode_add(ifp->connected, ifc);
4171
0
  }
4172
4173
  /* This address is configured from zebra. */
4174
0
  if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
4175
0
    SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
4176
4177
  /* In case of this route need to install kernel. */
4178
0
  if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) &&
4179
0
      CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE) &&
4180
0
      !(if_data && if_data->shutdown == IF_ZEBRA_DATA_ON)) {
4181
    /* Some system need to up the interface to set IP address. */
4182
0
    if (!if_is_up(ifp)) {
4183
0
      if_set_flags(ifp, IFF_UP | IFF_RUNNING);
4184
0
      if_refresh(ifp);
4185
0
    }
4186
4187
0
    dplane_res = dplane_intf_addr_set(ifp, ifc);
4188
0
    if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) {
4189
0
      zlog_debug(
4190
0
        "dplane can't set interface IP address: %s.",
4191
0
        dplane_res2str(dplane_res));
4192
0
      return NB_ERR;
4193
0
    }
4194
4195
0
    SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
4196
    /* The address will be advertised to zebra clients when the
4197
     * notification
4198
     * from the kernel has been received.
4199
     * It will also be added to the subnet chain list, then. */
4200
0
  }
4201
4202
0
  return 0;
4203
0
}
4204
4205
static int ip_address_install(struct vty *vty, struct interface *ifp,
4206
            const char *addr_str, const char *peer_str,
4207
            const char *label)
4208
0
{
4209
0
  struct zebra_if *if_data;
4210
0
  struct prefix_ipv4 lp, pp;
4211
0
  struct connected *ifc;
4212
0
  struct prefix_ipv4 *p;
4213
0
  int ret;
4214
0
  enum zebra_dplane_result dplane_res;
4215
4216
0
  if_data = ifp->info;
4217
4218
0
  ret = str2prefix_ipv4(addr_str, &lp);
4219
0
  if (ret <= 0) {
4220
0
    vty_out(vty, "%% Malformed address \n");
4221
0
    return CMD_WARNING_CONFIG_FAILED;
4222
0
  }
4223
4224
0
  if (ipv4_martian(&lp.prefix)) {
4225
0
    vty_out(vty, "%% Invalid address\n");
4226
0
    return CMD_WARNING_CONFIG_FAILED;
4227
0
  }
4228
4229
0
  if (peer_str) {
4230
0
    if (lp.prefixlen != IPV4_MAX_BITLEN) {
4231
0
      vty_out(vty,
4232
0
        "%% Local prefix length for P-t-P address must be /32\n");
4233
0
      return CMD_WARNING_CONFIG_FAILED;
4234
0
    }
4235
4236
0
    ret = str2prefix_ipv4(peer_str, &pp);
4237
0
    if (ret <= 0) {
4238
0
      vty_out(vty, "%% Malformed peer address\n");
4239
0
      return CMD_WARNING_CONFIG_FAILED;
4240
0
    }
4241
0
  }
4242
4243
0
  ifc = connected_check_ptp(ifp, &lp, peer_str ? &pp : NULL);
4244
0
  if (!ifc) {
4245
0
    ifc = connected_new();
4246
0
    ifc->ifp = ifp;
4247
4248
    /* Address. */
4249
0
    p = prefix_ipv4_new();
4250
0
    *p = lp;
4251
0
    ifc->address = (struct prefix *)p;
4252
4253
0
    if (peer_str) {
4254
0
      SET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
4255
0
      p = prefix_ipv4_new();
4256
0
      *p = pp;
4257
0
      ifc->destination = (struct prefix *)p;
4258
0
    }
4259
4260
    /* Label. */
4261
0
    if (label)
4262
0
      ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
4263
4264
    /* Add to linked list. */
4265
0
    listnode_add(ifp->connected, ifc);
4266
0
  }
4267
4268
  /* This address is configured from zebra. */
4269
0
  if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
4270
0
    SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
4271
4272
  /* In case of this route need to install kernel. */
4273
0
  if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) &&
4274
0
      CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE) &&
4275
0
      !(if_data && if_data->shutdown == IF_ZEBRA_DATA_ON)) {
4276
    /* Some system need to up the interface to set IP address. */
4277
0
    if (!if_is_up(ifp)) {
4278
0
      if_set_flags(ifp, IFF_UP | IFF_RUNNING);
4279
0
      if_refresh(ifp);
4280
0
    }
4281
4282
0
    dplane_res = dplane_intf_addr_set(ifp, ifc);
4283
0
    if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) {
4284
0
      vty_out(vty, "%% Can't set interface IP address: %s.\n",
4285
0
        dplane_res2str(dplane_res));
4286
0
      return CMD_WARNING_CONFIG_FAILED;
4287
0
    }
4288
4289
0
    SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
4290
    /* The address will be advertised to zebra clients when the
4291
     * notification
4292
     * from the kernel has been received.
4293
     * It will also be added to the subnet chain list, then. */
4294
0
  }
4295
4296
0
  return CMD_SUCCESS;
4297
0
}
4298
4299
int if_ip_address_uinstall(struct interface *ifp, struct prefix *prefix)
4300
0
{
4301
0
  struct connected *ifc = NULL;
4302
0
  enum zebra_dplane_result dplane_res;
4303
4304
0
  if (prefix->family == AF_INET) {
4305
    /* Check current interface address. */
4306
0
    ifc = connected_check_ptp(ifp, prefix, NULL);
4307
0
    if (!ifc) {
4308
0
      zlog_debug("interface %s Can't find address",
4309
0
           ifp->name);
4310
0
      return -1;
4311
0
    }
4312
4313
0
  } else if (prefix->family == AF_INET6) {
4314
    /* Check current interface address. */
4315
0
    ifc = connected_check(ifp, prefix);
4316
0
  }
4317
4318
0
  if (!ifc) {
4319
0
    zlog_debug("interface %s Can't find address", ifp->name);
4320
0
    return -1;
4321
0
  }
4322
0
  UNSET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
4323
4324
  /* This is not real address or interface is not active. */
4325
0
  if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)
4326
0
      || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
4327
0
    listnode_delete(ifp->connected, ifc);
4328
0
    connected_free(&ifc);
4329
0
    return CMD_WARNING_CONFIG_FAILED;
4330
0
  }
4331
4332
  /* This is real route. */
4333
0
  dplane_res = dplane_intf_addr_unset(ifp, ifc);
4334
0
  if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) {
4335
0
    zlog_debug("Can't unset interface IP address: %s.",
4336
0
         dplane_res2str(dplane_res));
4337
0
    return -1;
4338
0
  }
4339
0
  UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
4340
4341
0
  return 0;
4342
0
}
4343
4344
static int ip_address_uninstall(struct vty *vty, struct interface *ifp,
4345
        const char *addr_str, const char *peer_str,
4346
        const char *label)
4347
0
{
4348
0
  struct prefix_ipv4 lp, pp;
4349
0
  struct connected *ifc;
4350
0
  int ret;
4351
0
  enum zebra_dplane_result dplane_res;
4352
4353
  /* Convert to prefix structure. */
4354
0
  ret = str2prefix_ipv4(addr_str, &lp);
4355
0
  if (ret <= 0) {
4356
0
    vty_out(vty, "%% Malformed address \n");
4357
0
    return CMD_WARNING_CONFIG_FAILED;
4358
0
  }
4359
4360
0
  if (peer_str) {
4361
0
    if (lp.prefixlen != IPV4_MAX_BITLEN) {
4362
0
      vty_out(vty,
4363
0
        "%% Local prefix length for P-t-P address must be /32\n");
4364
0
      return CMD_WARNING_CONFIG_FAILED;
4365
0
    }
4366
4367
0
    ret = str2prefix_ipv4(peer_str, &pp);
4368
0
    if (ret <= 0) {
4369
0
      vty_out(vty, "%% Malformed peer address\n");
4370
0
      return CMD_WARNING_CONFIG_FAILED;
4371
0
    }
4372
0
  }
4373
4374
  /* Check current interface address. */
4375
0
  ifc = connected_check_ptp(ifp, &lp, peer_str ? &pp : NULL);
4376
0
  if (!ifc) {
4377
0
    vty_out(vty, "%% Can't find address\n");
4378
0
    return CMD_WARNING_CONFIG_FAILED;
4379
0
  }
4380
4381
  /* This is not configured address. */
4382
0
  if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
4383
0
    return CMD_WARNING_CONFIG_FAILED;
4384
4385
0
  UNSET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
4386
4387
  /* This is not real address or interface is not active. */
4388
0
  if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)
4389
0
      || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
4390
0
    listnode_delete(ifp->connected, ifc);
4391
0
    connected_free(&ifc);
4392
0
    return CMD_WARNING_CONFIG_FAILED;
4393
0
  }
4394
4395
  /* This is real route. */
4396
0
  dplane_res = dplane_intf_addr_unset(ifp, ifc);
4397
0
  if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) {
4398
0
    vty_out(vty, "%% Can't unset interface IP address: %s.\n",
4399
0
      dplane_res2str(dplane_res));
4400
0
    return CMD_WARNING_CONFIG_FAILED;
4401
0
  }
4402
0
  UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
4403
  /* we will receive a kernel notification about this route being removed.
4404
   * this will trigger its removal from the connected list. */
4405
0
  return CMD_SUCCESS;
4406
0
}
4407
4408
DEFUN (ip_address,
4409
       ip_address_cmd,
4410
       "ip address A.B.C.D/M",
4411
       "Interface Internet Protocol config commands\n"
4412
       "Set the IP address of an interface\n"
4413
       "IP address (e.g. 10.0.0.1/8)\n")
4414
0
{
4415
0
  int idx_ipv4_prefixlen = 2;
4416
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
4417
0
  return ip_address_install(vty, ifp, argv[idx_ipv4_prefixlen]->arg, NULL,
4418
0
          NULL);
4419
0
}
4420
4421
DEFUN (no_ip_address,
4422
       no_ip_address_cmd,
4423
       "no ip address A.B.C.D/M",
4424
       NO_STR
4425
       "Interface Internet Protocol config commands\n"
4426
       "Set the IP address of an interface\n"
4427
       "IP Address (e.g. 10.0.0.1/8)\n")
4428
0
{
4429
0
  int idx_ipv4_prefixlen = 3;
4430
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
4431
0
  return ip_address_uninstall(vty, ifp, argv[idx_ipv4_prefixlen]->arg,
4432
0
            NULL, NULL);
4433
0
}
4434
4435
DEFUN(ip_address_peer,
4436
      ip_address_peer_cmd,
4437
      "ip address A.B.C.D peer A.B.C.D/M",
4438
      "Interface Internet Protocol config commands\n"
4439
      "Set the IP address of an interface\n"
4440
      "Local IP (e.g. 10.0.0.1) for P-t-P address\n"
4441
      "Specify P-t-P address\n"
4442
      "Peer IP address (e.g. 10.0.0.1/8)\n")
4443
0
{
4444
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
4445
0
  return ip_address_install(vty, ifp, argv[2]->arg, argv[4]->arg, NULL);
4446
0
}
4447
4448
DEFUN(no_ip_address_peer,
4449
      no_ip_address_peer_cmd,
4450
      "no ip address A.B.C.D peer A.B.C.D/M",
4451
      NO_STR
4452
      "Interface Internet Protocol config commands\n"
4453
      "Set the IP address of an interface\n"
4454
      "Local IP (e.g. 10.0.0.1) for P-t-P address\n"
4455
      "Specify P-t-P address\n"
4456
      "Peer IP address (e.g. 10.0.0.1/8)\n")
4457
0
{
4458
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
4459
0
  return ip_address_uninstall(vty, ifp, argv[3]->arg, argv[5]->arg, NULL);
4460
0
}
4461
4462
#ifdef HAVE_NETLINK
4463
DEFUN (ip_address_label,
4464
       ip_address_label_cmd,
4465
       "ip address A.B.C.D/M label LINE",
4466
       "Interface Internet Protocol config commands\n"
4467
       "Set the IP address of an interface\n"
4468
       "IP address (e.g. 10.0.0.1/8)\n"
4469
       "Label of this address\n"
4470
       "Label\n")
4471
0
{
4472
0
  int idx_ipv4_prefixlen = 2;
4473
0
  int idx_line = 4;
4474
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
4475
0
  return ip_address_install(vty, ifp, argv[idx_ipv4_prefixlen]->arg, NULL,
4476
0
          argv[idx_line]->arg);
4477
0
}
4478
4479
DEFUN (no_ip_address_label,
4480
       no_ip_address_label_cmd,
4481
       "no ip address A.B.C.D/M label LINE",
4482
       NO_STR
4483
       "Interface Internet Protocol config commands\n"
4484
       "Set the IP address of an interface\n"
4485
       "IP address (e.g. 10.0.0.1/8)\n"
4486
       "Label of this address\n"
4487
       "Label\n")
4488
0
{
4489
0
  int idx_ipv4_prefixlen = 3;
4490
0
  int idx_line = 5;
4491
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
4492
0
  return ip_address_uninstall(vty, ifp, argv[idx_ipv4_prefixlen]->arg,
4493
0
            NULL, argv[idx_line]->arg);
4494
0
}
4495
#endif /* HAVE_NETLINK */
4496
4497
int if_ipv6_address_install(struct interface *ifp, struct prefix *prefix,
4498
          const char *label)
4499
0
{
4500
0
  struct zebra_if *if_data;
4501
0
  struct prefix_ipv6 cp;
4502
0
  struct connected *ifc;
4503
0
  struct prefix_ipv6 *p;
4504
0
  enum zebra_dplane_result dplane_res;
4505
4506
0
  if_data = ifp->info;
4507
4508
0
  cp.family = prefix->family;
4509
0
  cp.prefixlen = prefix->prefixlen;
4510
0
  cp.prefix = prefix->u.prefix6;
4511
0
  apply_mask_ipv6(&cp);
4512
4513
0
  ifc = connected_check(ifp, (struct prefix *)&cp);
4514
0
  if (!ifc) {
4515
0
    ifc = connected_new();
4516
0
    ifc->ifp = ifp;
4517
4518
    /* Address. */
4519
0
    p = prefix_ipv6_new();
4520
0
    *p = cp;
4521
0
    ifc->address = (struct prefix *)p;
4522
4523
    /* Label. */
4524
0
    if (label)
4525
0
      ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
4526
4527
    /* Add to linked list. */
4528
0
    listnode_add(ifp->connected, ifc);
4529
0
  }
4530
4531
  /* This address is configured from zebra. */
4532
0
  if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
4533
0
    SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
4534
4535
  /* In case of this route need to install kernel. */
4536
0
  if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) &&
4537
0
      CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE) &&
4538
0
      !(if_data && if_data->shutdown == IF_ZEBRA_DATA_ON)) {
4539
    /* Some system need to up the interface to set IP address. */
4540
0
    if (!if_is_up(ifp)) {
4541
0
      if_set_flags(ifp, IFF_UP | IFF_RUNNING);
4542
0
      if_refresh(ifp);
4543
0
    }
4544
4545
0
    dplane_res = dplane_intf_addr_set(ifp, ifc);
4546
0
    if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) {
4547
0
      zlog_debug(
4548
0
        "dplane can't set interface IP address: %s.",
4549
0
        dplane_res2str(dplane_res));
4550
0
      return NB_ERR;
4551
0
    }
4552
4553
0
    SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
4554
    /* The address will be advertised to zebra clients when the
4555
     * notification
4556
     * from the kernel has been received. */
4557
0
  }
4558
4559
0
  return 0;
4560
0
}
4561
4562
static int ipv6_address_install(struct vty *vty, struct interface *ifp,
4563
        const char *addr_str, const char *peer_str,
4564
        const char *label)
4565
0
{
4566
0
  struct zebra_if *if_data;
4567
0
  struct prefix_ipv6 cp;
4568
0
  struct connected *ifc;
4569
0
  struct prefix_ipv6 *p;
4570
0
  int ret;
4571
0
  enum zebra_dplane_result dplane_res;
4572
4573
0
  if_data = ifp->info;
4574
4575
0
  ret = str2prefix_ipv6(addr_str, &cp);
4576
0
  if (ret <= 0) {
4577
0
    vty_out(vty, "%% Malformed address \n");
4578
0
    return CMD_WARNING_CONFIG_FAILED;
4579
0
  }
4580
4581
0
  if (ipv6_martian(&cp.prefix)) {
4582
0
    vty_out(vty, "%% Invalid address\n");
4583
0
    return CMD_WARNING_CONFIG_FAILED;
4584
0
  }
4585
4586
0
  ifc = connected_check(ifp, (struct prefix *)&cp);
4587
0
  if (!ifc) {
4588
0
    ifc = connected_new();
4589
0
    ifc->ifp = ifp;
4590
4591
    /* Address. */
4592
0
    p = prefix_ipv6_new();
4593
0
    *p = cp;
4594
0
    ifc->address = (struct prefix *)p;
4595
4596
    /* Label. */
4597
0
    if (label)
4598
0
      ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
4599
4600
    /* Add to linked list. */
4601
0
    listnode_add(ifp->connected, ifc);
4602
0
  }
4603
4604
  /* This address is configured from zebra. */
4605
0
  if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
4606
0
    SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
4607
4608
  /* In case of this route need to install kernel. */
4609
0
  if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) &&
4610
0
      CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE) &&
4611
0
      !(if_data && if_data->shutdown == IF_ZEBRA_DATA_ON)) {
4612
    /* Some system need to up the interface to set IP address. */
4613
0
    if (!if_is_up(ifp)) {
4614
0
      if_set_flags(ifp, IFF_UP | IFF_RUNNING);
4615
0
      if_refresh(ifp);
4616
0
    }
4617
4618
0
    dplane_res = dplane_intf_addr_set(ifp, ifc);
4619
0
    if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) {
4620
0
      vty_out(vty, "%% Can't set interface IP address: %s.\n",
4621
0
        dplane_res2str(dplane_res));
4622
0
      return CMD_WARNING_CONFIG_FAILED;
4623
0
    }
4624
4625
0
    SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
4626
    /* The address will be advertised to zebra clients when the
4627
     * notification
4628
     * from the kernel has been received. */
4629
0
  }
4630
4631
0
  return CMD_SUCCESS;
4632
0
}
4633
4634
/* Return true if an ipv6 address is configured on ifp */
4635
int ipv6_address_configured(struct interface *ifp)
4636
0
{
4637
0
  struct connected *connected;
4638
0
  struct listnode *node;
4639
4640
0
  for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected))
4641
0
    if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL)
4642
0
        && (connected->address->family == AF_INET6))
4643
0
      return 1;
4644
4645
0
  return 0;
4646
0
}
4647
4648
static int ipv6_address_uninstall(struct vty *vty, struct interface *ifp,
4649
          const char *addr_str, const char *peer_str,
4650
          const char *label)
4651
0
{
4652
0
  struct prefix_ipv6 cp;
4653
0
  struct connected *ifc;
4654
0
  int ret;
4655
0
  enum zebra_dplane_result dplane_res;
4656
4657
  /* Convert to prefix structure. */
4658
0
  ret = str2prefix_ipv6(addr_str, &cp);
4659
0
  if (ret <= 0) {
4660
0
    vty_out(vty, "%% Malformed address \n");
4661
0
    return CMD_WARNING_CONFIG_FAILED;
4662
0
  }
4663
4664
  /* Check current interface address. */
4665
0
  ifc = connected_check(ifp, (struct prefix *)&cp);
4666
0
  if (!ifc) {
4667
0
    vty_out(vty, "%% Can't find address\n");
4668
0
    return CMD_WARNING_CONFIG_FAILED;
4669
0
  }
4670
4671
  /* This is not configured address. */
4672
0
  if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
4673
0
    return CMD_WARNING_CONFIG_FAILED;
4674
4675
0
  UNSET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
4676
4677
  /* This is not real address or interface is not active. */
4678
0
  if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)
4679
0
      || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
4680
0
    listnode_delete(ifp->connected, ifc);
4681
0
    connected_free(&ifc);
4682
0
    return CMD_WARNING_CONFIG_FAILED;
4683
0
  }
4684
4685
  /* This is real route. */
4686
0
  dplane_res = dplane_intf_addr_unset(ifp, ifc);
4687
0
  if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) {
4688
0
    vty_out(vty, "%% Can't unset interface IP address: %s.\n",
4689
0
      dplane_res2str(dplane_res));
4690
0
    return CMD_WARNING_CONFIG_FAILED;
4691
0
  }
4692
4693
0
  UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
4694
  /* This information will be propagated to the zclients when the
4695
   * kernel notification is received. */
4696
0
  return CMD_SUCCESS;
4697
0
}
4698
4699
DEFUN (ipv6_address,
4700
       ipv6_address_cmd,
4701
       "ipv6 address X:X::X:X/M",
4702
       "Interface IPv6 config commands\n"
4703
       "Set the IP address of an interface\n"
4704
       "IPv6 address (e.g. 3ffe:506::1/48)\n")
4705
0
{
4706
0
  int idx_ipv6_prefixlen = 2;
4707
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
4708
0
  return ipv6_address_install(vty, ifp, argv[idx_ipv6_prefixlen]->arg,
4709
0
            NULL, NULL);
4710
0
}
4711
4712
DEFUN (no_ipv6_address,
4713
       no_ipv6_address_cmd,
4714
       "no ipv6 address X:X::X:X/M",
4715
       NO_STR
4716
       "Interface IPv6 config commands\n"
4717
       "Set the IP address of an interface\n"
4718
       "IPv6 address (e.g. 3ffe:506::1/48)\n")
4719
0
{
4720
0
  int idx_ipv6_prefixlen = 3;
4721
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
4722
0
  return ipv6_address_uninstall(vty, ifp, argv[idx_ipv6_prefixlen]->arg,
4723
0
              NULL, NULL);
4724
0
}
4725
4726
static int link_params_config_write(struct vty *vty, struct interface *ifp)
4727
0
{
4728
0
  const struct lyd_node *dnode;
4729
0
  char xpath[XPATH_MAXLEN];
4730
0
  int i;
4731
4732
0
  if ((ifp == NULL) || !HAS_LINK_PARAMS(ifp))
4733
0
    return -1;
4734
4735
0
  struct if_link_params *iflp = ifp->link_params;
4736
4737
0
  vty_out(vty, " link-params\n");
4738
0
  vty_out(vty, "  enable\n");
4739
0
  if (IS_PARAM_SET(iflp, LP_TE_METRIC) && iflp->te_metric != ifp->metric)
4740
0
    vty_out(vty, "  metric %u\n", iflp->te_metric);
4741
0
  if (IS_PARAM_SET(iflp, LP_MAX_BW) && iflp->max_bw != iflp->default_bw)
4742
0
    vty_out(vty, "  max-bw %g\n", iflp->max_bw);
4743
0
  if (IS_PARAM_SET(iflp, LP_MAX_RSV_BW)
4744
0
      && iflp->max_rsv_bw != iflp->default_bw)
4745
0
    vty_out(vty, "  max-rsv-bw %g\n", iflp->max_rsv_bw);
4746
0
  if (IS_PARAM_SET(iflp, LP_UNRSV_BW)) {
4747
0
    for (i = 0; i < 8; i++)
4748
0
      if (iflp->unrsv_bw[i] != iflp->default_bw)
4749
0
        vty_out(vty, "  unrsv-bw %d %g\n", i,
4750
0
          iflp->unrsv_bw[i]);
4751
0
  }
4752
4753
0
  snprintf(
4754
0
    xpath, sizeof(xpath),
4755
0
    "/frr-interface:lib/interface[name='%s']/frr-zebra:zebra/link-params",
4756
0
    ifp->name);
4757
0
  dnode = yang_dnode_get(running_config->dnode, xpath);
4758
0
  if (dnode)
4759
0
    nb_cli_show_dnode_cmds(vty, dnode, false);
4760
4761
0
  if (IS_PARAM_SET(iflp, LP_DELAY)) {
4762
0
    vty_out(vty, "  delay %u", iflp->av_delay);
4763
0
    if (IS_PARAM_SET(iflp, LP_MM_DELAY)) {
4764
0
      vty_out(vty, " min %u", iflp->min_delay);
4765
0
      vty_out(vty, " max %u", iflp->max_delay);
4766
0
    }
4767
0
    vty_out(vty, "\n");
4768
0
  }
4769
0
  if (IS_PARAM_SET(iflp, LP_DELAY_VAR))
4770
0
    vty_out(vty, "  delay-variation %u\n", iflp->delay_var);
4771
0
  if (IS_PARAM_SET(iflp, LP_PKT_LOSS))
4772
0
    vty_out(vty, "  packet-loss %g\n", iflp->pkt_loss);
4773
0
  if (IS_PARAM_SET(iflp, LP_AVA_BW))
4774
0
    vty_out(vty, "  ava-bw %g\n", iflp->ava_bw);
4775
0
  if (IS_PARAM_SET(iflp, LP_RES_BW))
4776
0
    vty_out(vty, "  res-bw %g\n", iflp->res_bw);
4777
0
  if (IS_PARAM_SET(iflp, LP_USE_BW))
4778
0
    vty_out(vty, "  use-bw %g\n", iflp->use_bw);
4779
0
  if (IS_PARAM_SET(iflp, LP_RMT_AS))
4780
0
    vty_out(vty, "  neighbor %pI4 as %u\n", &iflp->rmt_ip,
4781
0
      iflp->rmt_as);
4782
4783
0
  vty_out(vty, " exit-link-params\n");
4784
0
  return 0;
4785
0
}
4786
4787
static int if_config_write(struct vty *vty)
4788
0
{
4789
0
  struct vrf *vrf;
4790
0
  struct interface *ifp;
4791
4792
0
  zebra_ptm_write(vty);
4793
4794
0
  RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
4795
0
    FOR_ALL_INTERFACES (vrf, ifp) {
4796
0
      struct zebra_if *if_data;
4797
0
      struct listnode *addrnode;
4798
0
      struct connected *ifc;
4799
0
      struct prefix *p;
4800
4801
0
      if_data = ifp->info;
4802
4803
0
      if_vty_config_start(vty, ifp);
4804
4805
0
      if (if_data) {
4806
0
        if (if_data->shutdown == IF_ZEBRA_DATA_ON)
4807
0
          vty_out(vty, " shutdown\n");
4808
4809
0
        zebra_ptm_if_write(vty, if_data);
4810
0
      }
4811
4812
0
      if (ifp->desc)
4813
0
        vty_out(vty, " description %s\n", ifp->desc);
4814
4815
      /* Assign bandwidth here to avoid unnecessary interface
4816
         flap
4817
         while processing config script */
4818
0
      if (ifp->bandwidth != 0)
4819
0
        vty_out(vty, " bandwidth %u\n", ifp->bandwidth);
4820
4821
0
      if (!CHECK_FLAG(ifp->status,
4822
0
          ZEBRA_INTERFACE_LINKDETECTION))
4823
0
        vty_out(vty, " no link-detect\n");
4824
4825
0
      for (ALL_LIST_ELEMENTS_RO(ifp->connected, addrnode,
4826
0
              ifc)) {
4827
0
        if (CHECK_FLAG(ifc->conf,
4828
0
                 ZEBRA_IFC_CONFIGURED)) {
4829
0
          char buf[INET6_ADDRSTRLEN];
4830
0
          p = ifc->address;
4831
0
          vty_out(vty, " ip%s address %s",
4832
0
            p->family == AF_INET ? ""
4833
0
                     : "v6",
4834
0
            inet_ntop(p->family,
4835
0
                &p->u.prefix, buf,
4836
0
                sizeof(buf)));
4837
0
          if (CONNECTED_PEER(ifc)) {
4838
0
            p = ifc->destination;
4839
0
            vty_out(vty, " peer %s",
4840
0
              inet_ntop(p->family,
4841
0
                  &p->u.prefix,
4842
0
                  buf,
4843
0
                  sizeof(buf)));
4844
0
          }
4845
0
          vty_out(vty, "/%d", p->prefixlen);
4846
4847
0
          if (ifc->label)
4848
0
            vty_out(vty, " label %s",
4849
0
              ifc->label);
4850
4851
0
          vty_out(vty, "\n");
4852
0
        }
4853
0
      }
4854
4855
0
      if (if_data) {
4856
0
        if (if_data->multicast != IF_ZEBRA_DATA_UNSPEC)
4857
0
          vty_out(vty, " %smulticast\n",
4858
0
            if_data->multicast ==
4859
0
                IF_ZEBRA_DATA_ON
4860
0
              ? ""
4861
0
              : "no ");
4862
0
        if (if_data->mpls == IF_ZEBRA_DATA_ON)
4863
0
          vty_out(vty, " mpls enable\n");
4864
0
      }
4865
4866
0
      hook_call(zebra_if_config_wr, vty, ifp);
4867
0
      zebra_evpn_mh_if_write(vty, ifp);
4868
0
      link_params_config_write(vty, ifp);
4869
4870
0
      if_vty_config_end(vty);
4871
0
    }
4872
0
  return 0;
4873
0
}
4874
4875
/* Allocate and initialize interface vector. */
4876
void zebra_if_init(void)
4877
1
{
4878
  /* Initialize interface and new hook. */
4879
1
  hook_register_prio(if_add, 0, if_zebra_new_hook);
4880
1
  hook_register_prio(if_del, 0, if_zebra_delete_hook);
4881
4882
  /* Install configuration write function. */
4883
1
  if_cmd_init(if_config_write);
4884
1
  install_node(&link_params_node);
4885
  /*
4886
   * This is *intentionally* setting this to NULL, signaling
4887
   * that interface creation for zebra acts differently
4888
   */
4889
1
  if_zapi_callbacks(NULL, NULL, NULL, NULL);
4890
4891
1
  install_element(VIEW_NODE, &show_interface_cmd);
4892
1
  install_element(VIEW_NODE, &show_interface_vrf_all_cmd);
4893
1
  install_element(VIEW_NODE, &show_interface_name_vrf_cmd);
4894
1
  install_element(VIEW_NODE, &show_interface_name_vrf_all_cmd);
4895
4896
1
  install_element(ENABLE_NODE, &show_interface_desc_cmd);
4897
1
  install_element(ENABLE_NODE, &show_interface_desc_vrf_all_cmd);
4898
1
  install_element(INTERFACE_NODE, &multicast_cmd);
4899
1
  install_element(INTERFACE_NODE, &no_multicast_cmd);
4900
1
  install_element(INTERFACE_NODE, &mpls_cmd);
4901
1
  install_element(INTERFACE_NODE, &linkdetect_cmd);
4902
1
  install_element(INTERFACE_NODE, &no_linkdetect_cmd);
4903
1
  install_element(INTERFACE_NODE, &shutdown_if_cmd);
4904
1
  install_element(INTERFACE_NODE, &no_shutdown_if_cmd);
4905
1
  install_element(INTERFACE_NODE, &bandwidth_if_cmd);
4906
1
  install_element(INTERFACE_NODE, &no_bandwidth_if_cmd);
4907
1
  install_element(INTERFACE_NODE, &ip_address_cmd);
4908
1
  install_element(INTERFACE_NODE, &no_ip_address_cmd);
4909
1
  install_element(INTERFACE_NODE, &ip_address_peer_cmd);
4910
1
  install_element(INTERFACE_NODE, &no_ip_address_peer_cmd);
4911
1
  install_element(INTERFACE_NODE, &ipv6_address_cmd);
4912
1
  install_element(INTERFACE_NODE, &no_ipv6_address_cmd);
4913
1
#ifdef HAVE_NETLINK
4914
1
  install_element(INTERFACE_NODE, &ip_address_label_cmd);
4915
1
  install_element(INTERFACE_NODE, &no_ip_address_label_cmd);
4916
1
#endif /* HAVE_NETLINK */
4917
1
  install_element(INTERFACE_NODE, &link_params_cmd);
4918
1
  install_default(LINK_PARAMS_NODE);
4919
1
  install_element(LINK_PARAMS_NODE, &link_params_enable_cmd);
4920
1
  install_element(LINK_PARAMS_NODE, &no_link_params_enable_cmd);
4921
1
  install_element(LINK_PARAMS_NODE, &link_params_metric_cmd);
4922
1
  install_element(LINK_PARAMS_NODE, &no_link_params_metric_cmd);
4923
1
  install_element(LINK_PARAMS_NODE, &link_params_maxbw_cmd);
4924
1
  install_element(LINK_PARAMS_NODE, &link_params_max_rsv_bw_cmd);
4925
1
  install_element(LINK_PARAMS_NODE, &link_params_unrsv_bw_cmd);
4926
1
  install_element(LINK_PARAMS_NODE, &link_params_admin_grp_cmd);
4927
1
  install_element(LINK_PARAMS_NODE, &no_link_params_admin_grp_cmd);
4928
1
  install_element(LINK_PARAMS_NODE, &link_params_inter_as_cmd);
4929
1
  install_element(LINK_PARAMS_NODE, &no_link_params_inter_as_cmd);
4930
1
  install_element(LINK_PARAMS_NODE, &link_params_delay_cmd);
4931
1
  install_element(LINK_PARAMS_NODE, &no_link_params_delay_cmd);
4932
1
  install_element(LINK_PARAMS_NODE, &link_params_delay_var_cmd);
4933
1
  install_element(LINK_PARAMS_NODE, &no_link_params_delay_var_cmd);
4934
1
  install_element(LINK_PARAMS_NODE, &link_params_pkt_loss_cmd);
4935
1
  install_element(LINK_PARAMS_NODE, &no_link_params_pkt_loss_cmd);
4936
1
  install_element(LINK_PARAMS_NODE, &link_params_ava_bw_cmd);
4937
1
  install_element(LINK_PARAMS_NODE, &no_link_params_ava_bw_cmd);
4938
1
  install_element(LINK_PARAMS_NODE, &link_params_res_bw_cmd);
4939
1
  install_element(LINK_PARAMS_NODE, &no_link_params_res_bw_cmd);
4940
1
  install_element(LINK_PARAMS_NODE, &link_params_use_bw_cmd);
4941
1
  install_element(LINK_PARAMS_NODE, &no_link_params_use_bw_cmd);
4942
1
  install_element(LINK_PARAMS_NODE, &link_params_affinity_cmd);
4943
1
  install_element(LINK_PARAMS_NODE, &link_params_affinity_mode_cmd);
4944
1
  install_element(LINK_PARAMS_NODE, &no_link_params_affinity_mode_cmd);
4945
1
  install_element(LINK_PARAMS_NODE, &exit_link_params_cmd);
4946
4947
  /* setup EVPN MH elements */
4948
1
  zebra_evpn_interface_init();
4949
1
}