Coverage Report

Created: 2026-01-13 06:56

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/frr/bgpd/rfapi/rfapi_vty.c
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
 *
4
 * Copyright 2009-2016, LabN Consulting, L.L.C.
5
 *
6
 */
7
8
#include "lib/zebra.h"
9
#include "lib/prefix.h"
10
#include "lib/agg_table.h"
11
#include "lib/vty.h"
12
#include "lib/memory.h"
13
#include "lib/routemap.h"
14
#include "lib/log.h"
15
#include "lib/linklist.h"
16
#include "lib/command.h"
17
18
#include "bgpd/bgpd.h"
19
#include "bgpd/bgp_ecommunity.h"
20
#include "bgpd/bgp_attr.h"
21
#include "bgpd/bgp_route.h"
22
#include "bgpd/bgp_mplsvpn.h"
23
24
#include "bgpd/rfapi/bgp_rfapi_cfg.h"
25
#include "bgpd/rfapi/rfapi.h"
26
#include "bgpd/rfapi/rfapi_backend.h"
27
28
#include "bgpd/bgp_route.h"
29
#include "bgpd/bgp_aspath.h"
30
#include "bgpd/bgp_community.h"
31
#include "bgpd/bgp_vnc_types.h"
32
#include "bgpd/bgp_label.h"
33
34
#include "bgpd/rfapi/rfapi_import.h"
35
#include "bgpd/rfapi/rfapi_private.h"
36
#include "bgpd/rfapi/rfapi_monitor.h"
37
#include "bgpd/rfapi/rfapi_rib.h"
38
#include "bgpd/rfapi/rfapi_vty.h"
39
#include "bgpd/rfapi/rfapi_ap.h"
40
#include "bgpd/rfapi/rfapi_encap_tlv.h"
41
#include "bgpd/rfapi/vnc_debug.h"
42
43
#define DEBUG_L2_EXTRA 0
44
#define DEBUG_SHOW_EXTRA 0
45
46
#define VNC_SHOW_STR "VNC information\n"
47
48
/* format related utilies */
49
50
51
0
#define FMT_MIN      60         /* seconds */
52
0
#define FMT_HOUR    (60  * FMT_MIN)
53
0
#define FMT_DAY     (24  * FMT_HOUR)
54
0
#define FMT_YEAR    (365 * FMT_DAY)
55
56
char *rfapiFormatSeconds(uint32_t seconds, char *buf, size_t len)
57
0
{
58
0
  int year, day, hour, min;
59
60
0
  if (seconds >= FMT_YEAR) {
61
0
    year = seconds / FMT_YEAR;
62
0
    seconds -= year * FMT_YEAR;
63
0
  } else
64
0
    year = 0;
65
66
0
  if (seconds >= FMT_DAY) {
67
0
    day = seconds / FMT_DAY;
68
0
    seconds -= day * FMT_DAY;
69
0
  } else
70
0
    day = 0;
71
72
0
  if (seconds >= FMT_HOUR) {
73
0
    hour = seconds / FMT_HOUR;
74
0
    seconds -= hour * FMT_HOUR;
75
0
  } else
76
0
    hour = 0;
77
78
0
  if (seconds >= FMT_MIN) {
79
0
    min = seconds / FMT_MIN;
80
0
    seconds -= min * FMT_MIN;
81
0
  } else
82
0
    min = 0;
83
84
0
  if (year > 0) {
85
0
    snprintf(buf, len, "%dy%dd%dh", year, day, hour);
86
0
  } else if (day > 0) {
87
0
    snprintf(buf, len, "%dd%dh%dm", day, hour, min);
88
0
  } else {
89
0
    snprintf(buf, len, "%02d:%02d:%02d", hour, min, seconds);
90
0
  }
91
92
0
  return buf;
93
0
}
94
95
char *rfapiFormatAge(time_t age, char *buf, size_t len)
96
0
{
97
0
  time_t now, age_adjusted;
98
99
0
  now = monotime(NULL);
100
0
  age_adjusted = now - age;
101
102
0
  return rfapiFormatSeconds(age_adjusted, buf, len);
103
0
}
104
105
106
/*
107
 * Reimplementation of quagga/lib/prefix.c function, but
108
 * for RFAPI-style prefixes
109
 */
110
void rfapiRprefixApplyMask(struct rfapi_ip_prefix *rprefix)
111
0
{
112
0
  uint8_t *pnt;
113
0
  int index;
114
0
  int offset;
115
116
0
  static const uint8_t maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0,
117
0
            0xf8, 0xfc, 0xfe, 0xff};
118
119
0
  switch (rprefix->prefix.addr_family) {
120
0
  case AF_INET:
121
0
    index = rprefix->length / 8;
122
0
    if (index < 4) {
123
0
      pnt = (uint8_t *)&rprefix->prefix.addr.v4;
124
0
      offset = rprefix->length % 8;
125
0
      pnt[index] &= maskbit[offset];
126
0
      index++;
127
0
      while (index < 4)
128
0
        pnt[index++] = 0;
129
0
    }
130
0
    break;
131
132
0
  case AF_INET6:
133
0
    index = rprefix->length / 8;
134
0
    if (index < 16) {
135
0
      pnt = (uint8_t *)&rprefix->prefix.addr.v6;
136
0
      offset = rprefix->length % 8;
137
0
      pnt[index] &= maskbit[offset];
138
0
      index++;
139
0
      while (index < 16)
140
0
        pnt[index++] = 0;
141
0
    }
142
0
    break;
143
144
0
  default:
145
0
    assert(0);
146
0
  }
147
0
}
148
149
/*
150
 * translate a quagga prefix into a rfapi IP address. The
151
 * prefix is REQUIRED to be 32 bits for IPv4 and 128 bits for IPv6
152
 *
153
 * RETURNS:
154
 *
155
 *  0 Success
156
 *  <0  Error
157
 */
158
int rfapiQprefix2Raddr(struct prefix *qprefix, struct rfapi_ip_addr *raddr)
159
0
{
160
0
  memset(raddr, 0, sizeof(struct rfapi_ip_addr));
161
0
  raddr->addr_family = qprefix->family;
162
0
  switch (qprefix->family) {
163
0
  case AF_INET:
164
0
    if (qprefix->prefixlen != IPV4_MAX_BITLEN)
165
0
      return -1;
166
0
    raddr->addr.v4 = qprefix->u.prefix4;
167
0
    break;
168
0
  case AF_INET6:
169
0
    if (qprefix->prefixlen != IPV6_MAX_BITLEN)
170
0
      return -1;
171
0
    raddr->addr.v6 = qprefix->u.prefix6;
172
0
    break;
173
0
  default:
174
0
    return -1;
175
0
  }
176
0
  return 0;
177
0
}
178
179
/*
180
 * Translate Quagga prefix to RFAPI prefix
181
 */
182
/* rprefix->cost set to 0 */
183
void rfapiQprefix2Rprefix(const struct prefix *qprefix,
184
        struct rfapi_ip_prefix *rprefix)
185
0
{
186
0
  memset(rprefix, 0, sizeof(struct rfapi_ip_prefix));
187
0
  rprefix->length = qprefix->prefixlen;
188
0
  rprefix->prefix.addr_family = qprefix->family;
189
0
  switch (qprefix->family) {
190
0
  case AF_INET:
191
0
    rprefix->prefix.addr.v4 = qprefix->u.prefix4;
192
0
    break;
193
0
  case AF_INET6:
194
0
    rprefix->prefix.addr.v6 = qprefix->u.prefix6;
195
0
    break;
196
0
  default:
197
0
    assert(0);
198
0
  }
199
0
}
200
201
int rfapiRprefix2Qprefix(struct rfapi_ip_prefix *rprefix,
202
       struct prefix *qprefix)
203
0
{
204
0
  memset(qprefix, 0, sizeof(struct prefix));
205
0
  qprefix->prefixlen = rprefix->length;
206
0
  qprefix->family = rprefix->prefix.addr_family;
207
208
0
  switch (rprefix->prefix.addr_family) {
209
0
  case AF_INET:
210
0
    qprefix->u.prefix4 = rprefix->prefix.addr.v4;
211
0
    break;
212
0
  case AF_INET6:
213
0
    qprefix->u.prefix6 = rprefix->prefix.addr.v6;
214
0
    break;
215
0
  default:
216
0
    return EAFNOSUPPORT;
217
0
  }
218
0
  return 0;
219
0
}
220
221
/*
222
 * returns 1 if prefixes have same addr family, prefix len, and address
223
 * Note that host bits matter in this comparison!
224
 *
225
 * For paralellism with quagga/lib/prefix.c. if we need a comparison
226
 * where host bits are ignored, call that function rfapiRprefixCmp.
227
 */
228
int rfapiRprefixSame(struct rfapi_ip_prefix *hp1, struct rfapi_ip_prefix *hp2)
229
0
{
230
0
  if (hp1->prefix.addr_family != hp2->prefix.addr_family)
231
0
    return 0;
232
0
  if (hp1->length != hp2->length)
233
0
    return 0;
234
0
  if (hp1->prefix.addr_family == AF_INET)
235
0
    if (IPV4_ADDR_SAME(&hp1->prefix.addr.v4, &hp2->prefix.addr.v4))
236
0
      return 1;
237
0
  if (hp1->prefix.addr_family == AF_INET6)
238
0
    if (IPV6_ADDR_SAME(&hp1->prefix.addr.v6, &hp2->prefix.addr.v6))
239
0
      return 1;
240
0
  return 0;
241
0
}
242
243
int rfapiRaddr2Qprefix(struct rfapi_ip_addr *hia, struct prefix *pfx)
244
0
{
245
0
  memset(pfx, 0, sizeof(struct prefix));
246
0
  pfx->family = hia->addr_family;
247
248
0
  switch (hia->addr_family) {
249
0
  case AF_INET:
250
0
    pfx->prefixlen = IPV4_MAX_BITLEN;
251
0
    pfx->u.prefix4 = hia->addr.v4;
252
0
    break;
253
0
  case AF_INET6:
254
0
    pfx->prefixlen = IPV6_MAX_BITLEN;
255
0
    pfx->u.prefix6 = hia->addr.v6;
256
0
    break;
257
0
  default:
258
0
    return EAFNOSUPPORT;
259
0
  }
260
0
  return 0;
261
0
}
262
263
void rfapiL2o2Qprefix(struct rfapi_l2address_option *l2o, struct prefix *pfx)
264
0
{
265
0
  memset(pfx, 0, sizeof(struct prefix));
266
0
  pfx->family = AF_ETHERNET;
267
0
  pfx->prefixlen = 48;
268
0
  pfx->u.prefix_eth = l2o->macaddr;
269
0
}
270
271
char *rfapiEthAddr2Str(const struct ethaddr *ea, char *buf, int bufsize)
272
0
{
273
0
  return prefix_mac2str(ea, buf, bufsize);
274
0
}
275
276
int rfapiStr2EthAddr(const char *str, struct ethaddr *ea)
277
0
{
278
0
  unsigned int a[6];
279
0
  int i;
280
281
0
  if (sscanf(str, "%2x:%2x:%2x:%2x:%2x:%2x", a + 0, a + 1, a + 2, a + 3,
282
0
       a + 4, a + 5)
283
0
      != 6) {
284
285
0
    return EINVAL;
286
0
  }
287
288
0
  for (i = 0; i < 6; ++i)
289
0
    ea->octet[i] = a[i] & 0xff;
290
291
0
  return 0;
292
0
}
293
294
const char *rfapi_ntop(int af, const void *src, char *buf, socklen_t size)
295
0
{
296
0
  if (af == AF_ETHERNET) {
297
0
    return rfapiEthAddr2Str((const struct ethaddr *)src, buf, size);
298
0
  }
299
300
0
  return inet_ntop(af, src, buf, size);
301
0
}
302
303
int rfapiDebugPrintf(void *dummy, const char *format, ...)
304
0
{
305
0
  va_list args;
306
0
  va_start(args, format);
307
0
  vzlog(LOG_DEBUG, format, args);
308
0
  va_end(args);
309
0
  return 0;
310
0
}
311
312
PRINTFRR(2, 3)
313
static int rfapiStdioPrintf(void *stream, const char *format, ...)
314
0
{
315
0
  FILE *file = NULL;
316
317
0
  va_list args;
318
0
  va_start(args, format);
319
320
0
  switch ((uintptr_t)stream) {
321
0
  case 1:
322
0
    file = stdout;
323
0
    break;
324
0
  case 2:
325
0
    file = stderr;
326
0
    break;
327
0
  default:
328
0
    assert(0);
329
0
  }
330
331
0
  vfprintf(file, format, args);
332
0
  va_end(args);
333
0
  return 0;
334
0
}
335
336
/* Fake out for debug logging */
337
static struct vty vty_dummy_zlog;
338
static struct vty vty_dummy_stdio;
339
0
#define HVTYNL ((vty == &vty_dummy_zlog)? "": "\n")
340
341
static const char *str_vty_newline(struct vty *vty)
342
0
{
343
0
  if (vty == &vty_dummy_zlog)
344
0
    return "";
345
0
  return "\n";
346
0
}
347
348
int rfapiStream2Vty(void *stream,        /* input */
349
        int (**fp)(void *, const char *, ...), /* output */
350
        struct vty **vty,        /* output */
351
        void **outstream,        /* output */
352
        const char **vty_newline)      /* output */
353
0
{
354
355
0
  if (!stream) {
356
0
    vty_dummy_zlog.type = VTY_SHELL; /* for VTYNL */
357
0
    *vty = &vty_dummy_zlog;
358
0
    *fp = (int (*)(void *, const char *, ...))rfapiDebugPrintf;
359
0
    *outstream = NULL;
360
0
    *vty_newline = str_vty_newline(*vty);
361
0
    return 1;
362
0
  }
363
364
0
  if (((uintptr_t)stream == (uintptr_t)1)
365
0
      || ((uintptr_t)stream == (uintptr_t)2)) {
366
367
0
    vty_dummy_stdio.type = VTY_SHELL; /* for VTYNL */
368
0
    *vty = &vty_dummy_stdio;
369
0
    *fp = (int (*)(void *, const char *, ...))rfapiStdioPrintf;
370
0
    *outstream = stream;
371
0
    *vty_newline = str_vty_newline(*vty);
372
0
    return 1;
373
0
  }
374
375
0
  *vty = stream; /* VTYNL requires vty to be legit */
376
0
  *fp = (int (*)(void *, const char *, ...))vty_out;
377
0
  *outstream = stream;
378
0
  *vty_newline = str_vty_newline(*vty);
379
0
  return 1;
380
0
}
381
382
/* called from bgpd/bgp_vty.c'route_vty_out() */
383
void rfapi_vty_out_vncinfo(struct vty *vty, const struct prefix *p,
384
         struct bgp_path_info *bpi, safi_t safi)
385
0
{
386
0
  char *s;
387
0
  uint32_t lifetime;
388
389
  /*
390
   * Print, on an indented line:
391
   *  UN address [if VPN route and VNC UN addr subtlv]
392
   *  EC list
393
   *  VNC lifetime
394
   */
395
0
  vty_out(vty, "    ");
396
397
0
  if (safi == SAFI_MPLS_VPN) {
398
0
    struct prefix pfx_un;
399
400
0
    if (!rfapiGetVncTunnelUnAddr(bpi->attr, &pfx_un)) {
401
0
      char buf[BUFSIZ];
402
403
0
      vty_out(vty, "UN=%s",
404
0
        inet_ntop(pfx_un.family, pfx_un.u.val, buf,
405
0
            sizeof(buf)));
406
0
    }
407
0
  }
408
409
0
  if (bgp_attr_get_ecommunity(bpi->attr)) {
410
0
    s = ecommunity_ecom2str(bgp_attr_get_ecommunity(bpi->attr),
411
0
          ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
412
0
    vty_out(vty, " EC{%s}", s);
413
0
    XFREE(MTYPE_ECOMMUNITY_STR, s);
414
0
  }
415
416
0
  if (bpi->extra != NULL) {
417
0
    if (bpi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
418
0
      vty_out(vty, " label=VRF2VRF");
419
0
    else
420
0
      vty_out(vty, " label=%u",
421
0
        decode_label(&bpi->extra->label[0]));
422
423
0
    if (bpi->extra->num_sids) {
424
0
      vty_out(vty, " sid=%pI6", &bpi->extra->sid[0].sid);
425
426
0
      if (bpi->extra->sid[0].loc_block_len != 0) {
427
0
        vty_out(vty, " sid_structure=[%d,%d,%d,%d]",
428
0
          bpi->extra->sid[0].loc_block_len,
429
0
          bpi->extra->sid[0].loc_node_len,
430
0
          bpi->extra->sid[0].func_len,
431
0
          bpi->extra->sid[0].arg_len);
432
0
      }
433
0
    }
434
0
  }
435
436
0
  if (!rfapiGetVncLifetime(bpi->attr, &lifetime)) {
437
0
    vty_out(vty, " life=%d", lifetime);
438
0
  }
439
440
0
  vty_out(vty, " type=%s, subtype=%d", zebra_route_string(bpi->type),
441
0
    bpi->sub_type);
442
443
0
  vty_out(vty, "%s", HVTYNL);
444
0
}
445
446
void rfapiPrintAttrPtrs(void *stream, struct attr *attr)
447
0
{
448
0
  int (*fp)(void *, const char *, ...);
449
0
  struct vty *vty;
450
0
  void *out;
451
0
  const char *vty_newline;
452
0
  struct transit *transit;
453
0
  struct cluster_list *cluster;
454
0
  struct ecommunity *ecomm;
455
0
  struct community *comm;
456
457
0
  if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
458
0
    return;
459
460
0
  fp(out, "Attr[%p]:%s", attr, HVTYNL);
461
0
  if (!attr)
462
0
    return;
463
464
  /* IPv4 Nexthop */
465
0
  fp(out, "  nexthop=%pI4%s", &attr->nexthop, HVTYNL);
466
467
0
  fp(out, "  aspath=%p, refcnt=%d%s", attr->aspath,
468
0
     (attr->aspath ? attr->aspath->refcnt : 0), HVTYNL);
469
470
0
  comm = bgp_attr_get_community(attr);
471
0
  fp(out, "  community=%p, refcnt=%d%s", comm, (comm ? comm->refcnt : 0),
472
0
     HVTYNL);
473
474
0
  ecomm = bgp_attr_get_ecommunity(attr);
475
0
  fp(out, "  ecommunity=%p, refcnt=%d%s", ecomm,
476
0
     (ecomm ? ecomm->refcnt : 0), HVTYNL);
477
478
0
  cluster = bgp_attr_get_cluster(attr);
479
0
  fp(out, "  cluster=%p, refcnt=%d%s", cluster,
480
0
     (cluster ? cluster->refcnt : 0), HVTYNL);
481
482
0
  transit = bgp_attr_get_transit(attr);
483
0
  fp(out, "  transit=%p, refcnt=%d%s", transit,
484
0
     (transit ? transit->refcnt : 0), HVTYNL);
485
0
}
486
487
/*
488
 * Print BPI in an Import Table
489
 */
490
void rfapiPrintBi(void *stream, struct bgp_path_info *bpi)
491
0
{
492
0
  char buf[BUFSIZ];
493
0
  char *s;
494
495
0
  int (*fp)(void *, const char *, ...);
496
0
  struct vty *vty;
497
0
  void *out;
498
0
  const char *vty_newline;
499
500
0
  char line[BUFSIZ];
501
0
  char *p = line;
502
0
  int r;
503
0
  int has_macaddr = 0;
504
0
  struct ethaddr macaddr = {{0}};
505
0
  struct rfapi_l2address_option l2o_buf;
506
0
  uint8_t l2hid = 0; /* valid if has_macaddr */
507
508
0
#define REMAIN (BUFSIZ - (p-line))
509
0
#define INCP {p += (r > REMAIN)? REMAIN: r;}
510
511
0
  if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
512
0
    return;
513
514
0
  if (!bpi)
515
0
    return;
516
517
0
  if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED) && bpi->extra
518
0
      && bpi->extra->vnc.import.timer) {
519
0
    struct event *t = (struct event *)bpi->extra->vnc.import.timer;
520
521
0
    r = snprintf(p, REMAIN, " [%4lu] ",
522
0
           event_timer_remain_second(t));
523
0
    INCP;
524
525
0
  } else {
526
0
    r = snprintf(p, REMAIN, "        ");
527
0
    INCP;
528
0
  }
529
530
0
  if (bpi->extra) {
531
    /* TBD This valid only for SAFI_MPLS_VPN, but not for encap */
532
0
    if (decode_rd_type(bpi->extra->vnc.import.rd.val)
533
0
        == RD_TYPE_VNC_ETH) {
534
0
      has_macaddr = 1;
535
0
      memcpy(macaddr.octet, bpi->extra->vnc.import.rd.val + 2,
536
0
             6);
537
0
      l2hid = bpi->extra->vnc.import.rd.val[1];
538
0
    }
539
0
  }
540
541
  /*
542
   * Print these items:
543
   *          type/subtype
544
   *          nexthop address
545
   *          lifetime
546
   *          RFP option sizes (they are opaque values)
547
   *          extended communities (RTs)
548
   */
549
0
  uint32_t lifetime;
550
0
  int printed_1st_gol = 0;
551
0
  struct bgp_attr_encap_subtlv *pEncap;
552
0
  struct prefix pfx_un;
553
0
  int af = BGP_MP_NEXTHOP_FAMILY(bpi->attr->mp_nexthop_len);
554
555
  /* Nexthop */
556
0
  if (af == AF_INET) {
557
0
    r = snprintfrr(p, REMAIN, "%pI4",
558
0
             &bpi->attr->mp_nexthop_global_in);
559
0
    INCP;
560
0
  } else if (af == AF_INET6) {
561
0
    r = snprintfrr(p, REMAIN, "%pI6",
562
0
             &bpi->attr->mp_nexthop_global);
563
0
    INCP;
564
0
  } else {
565
0
    r = snprintf(p, REMAIN, "?");
566
0
    INCP;
567
0
  }
568
569
  /*
570
   * VNC tunnel subtlv, if present, contains UN address
571
   */
572
0
  if (!rfapiGetVncTunnelUnAddr(bpi->attr, &pfx_un)) {
573
0
    r = snprintf(p, REMAIN, " un=%s",
574
0
           inet_ntop(pfx_un.family, pfx_un.u.val, buf,
575
0
               sizeof(buf)));
576
0
    INCP;
577
0
  }
578
579
  /* Lifetime */
580
0
  if (rfapiGetVncLifetime(bpi->attr, &lifetime)) {
581
0
    r = snprintf(p, REMAIN, " nolife");
582
0
    INCP;
583
0
  } else {
584
0
    if (lifetime == 0xffffffff)
585
0
      r = snprintf(p, REMAIN, " %6s", "infini");
586
0
    else
587
0
      r = snprintf(p, REMAIN, " %6u", lifetime);
588
0
    INCP;
589
0
  }
590
591
  /* RFP option lengths */
592
0
  for (pEncap = bgp_attr_get_vnc_subtlvs(bpi->attr); pEncap;
593
0
       pEncap = pEncap->next) {
594
595
0
    if (pEncap->type == BGP_VNC_SUBTLV_TYPE_RFPOPTION) {
596
0
      if (printed_1st_gol) {
597
0
        r = snprintf(p, REMAIN, ",");
598
0
        INCP;
599
0
      } else {
600
0
        r = snprintf(p, REMAIN,
601
0
               " "); /* leading space */
602
0
        INCP;
603
0
      }
604
0
      r = snprintf(p, REMAIN, "%d", pEncap->length);
605
0
      INCP;
606
0
      printed_1st_gol = 1;
607
0
    }
608
0
  }
609
610
  /* RT list */
611
0
  if (bgp_attr_get_ecommunity(bpi->attr)) {
612
0
    s = ecommunity_ecom2str(bgp_attr_get_ecommunity(bpi->attr),
613
0
          ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
614
0
    r = snprintf(p, REMAIN, " %s", s);
615
0
    INCP;
616
0
    XFREE(MTYPE_ECOMMUNITY_STR, s);
617
0
  }
618
619
0
  r = snprintf(p, REMAIN, " bpi@%p", bpi);
620
0
  INCP;
621
622
0
  r = snprintf(p, REMAIN, " p@%p", bpi->peer);
623
0
  INCP;
624
625
0
  if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
626
0
    r = snprintf(p, REMAIN, " HD=yes");
627
0
    INCP;
628
0
  } else {
629
0
    r = snprintf(p, REMAIN, " HD=no");
630
0
    INCP;
631
0
  }
632
633
0
  if (bpi->attr->weight) {
634
0
    r = snprintf(p, REMAIN, " W=%d", bpi->attr->weight);
635
0
    INCP;
636
0
  }
637
638
0
  if (bpi->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
639
0
    r = snprintf(p, REMAIN, " LP=%d", bpi->attr->local_pref);
640
0
    INCP;
641
0
  } else {
642
0
    r = snprintf(p, REMAIN, " LP=unset");
643
0
    INCP;
644
0
  }
645
646
0
  r = snprintf(p, REMAIN, " %c:%u", zebra_route_char(bpi->type),
647
0
         bpi->sub_type);
648
0
  INCP;
649
650
0
  fp(out, "%s%s", line, HVTYNL);
651
652
0
  if (has_macaddr) {
653
0
    fp(out, "        RD HID=%d ETH=%02x:%02x:%02x:%02x:%02x:%02x%s",
654
0
       l2hid, macaddr.octet[0], macaddr.octet[1], macaddr.octet[2],
655
0
       macaddr.octet[3], macaddr.octet[4], macaddr.octet[5],
656
0
       HVTYNL);
657
0
  }
658
659
0
  if (!rfapiGetL2o(bpi->attr, &l2o_buf)) {
660
0
    fp(out,
661
0
       "        L2O ETH=%02x:%02x:%02x:%02x:%02x:%02x LBL=%d LNI=%d LHI=%hhu%s",
662
0
       l2o_buf.macaddr.octet[0], l2o_buf.macaddr.octet[1],
663
0
       l2o_buf.macaddr.octet[2], l2o_buf.macaddr.octet[3],
664
0
       l2o_buf.macaddr.octet[4], l2o_buf.macaddr.octet[5],
665
0
       l2o_buf.label, l2o_buf.logical_net_id, l2o_buf.local_nve_id,
666
0
       HVTYNL);
667
0
  }
668
0
  if (bpi->extra && bpi->extra->vnc.import.aux_prefix.family) {
669
0
    const char *sp;
670
671
0
    sp = rfapi_ntop(bpi->extra->vnc.import.aux_prefix.family,
672
0
        &bpi->extra->vnc.import.aux_prefix.u.prefix,
673
0
        buf, BUFSIZ);
674
0
    buf[BUFSIZ - 1] = 0;
675
0
    if (sp) {
676
0
      fp(out, "        IP: %s%s", sp, HVTYNL);
677
0
    }
678
0
  }
679
0
  {
680
0
    struct rfapi_un_option *uo =
681
0
      rfapi_encap_tlv_to_un_option(bpi->attr);
682
0
    if (uo) {
683
0
      rfapi_print_tunneltype_option(stream, 8, &uo->v.tunnel);
684
0
      rfapi_un_options_free(uo);
685
0
    }
686
0
  }
687
0
}
688
689
char *rfapiMonitorVpn2Str(struct rfapi_monitor_vpn *m, char *buf, int size)
690
0
{
691
0
  char buf_pfx[BUFSIZ];
692
0
  char buf_vn[BUFSIZ];
693
0
  char buf_un[BUFSIZ];
694
0
  int rc;
695
696
0
  rfapiRfapiIpAddr2Str(&m->rfd->un_addr, buf_vn, BUFSIZ);
697
0
  rfapiRfapiIpAddr2Str(&m->rfd->vn_addr, buf_un, BUFSIZ);
698
699
0
  rc = snprintf(buf, size,
700
0
          "m=%p, next=%p, rfd=%p(vn=%s un=%s), p=%s/%d, node=%p", m,
701
0
          m->next, m->rfd, buf_vn, buf_un,
702
0
          inet_ntop(m->p.family, &m->p.u.prefix, buf_pfx,
703
0
        sizeof(buf_pfx)),
704
0
          m->p.prefixlen, m->node);
705
0
  buf[size - 1] = 0;
706
0
  if (rc >= size)
707
0
    return NULL;
708
0
  return buf;
709
0
}
710
711
static void rfapiDebugPrintMonitorVpn(void *stream, struct rfapi_monitor_vpn *m)
712
0
{
713
0
  char buf[BUFSIZ];
714
715
0
  int (*fp)(void *, const char *, ...);
716
0
  struct vty *vty;
717
0
  void *out;
718
0
  const char *vty_newline;
719
720
0
  if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
721
0
    return;
722
723
0
  rfapiMonitorVpn2Str(m, buf, BUFSIZ);
724
0
  fp(out, "    Mon %s%s", buf, HVTYNL);
725
0
}
726
727
static void rfapiDebugPrintMonitorEncap(void *stream,
728
          struct rfapi_monitor_encap *m)
729
0
{
730
0
  int (*fp)(void *, const char *, ...);
731
0
  struct vty *vty;
732
0
  void *out = NULL;
733
0
  const char *vty_newline;
734
735
0
  if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
736
0
    return;
737
738
0
  fp(out, "    Mon m=%p, next=%p, node=%p, bpi=%p%s", m, m->next, m->node,
739
0
     m->bpi, HVTYNL);
740
0
}
741
742
void rfapiShowItNode(void *stream, struct agg_node *rn)
743
0
{
744
0
  struct bgp_path_info *bpi;
745
746
0
  int (*fp)(void *, const char *, ...);
747
0
  struct vty *vty;
748
0
  void *out;
749
0
  const char *vty_newline;
750
751
0
  if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
752
0
    return;
753
754
0
  fp(out, "%pRN @%p #%d%s", rn, rn, agg_node_get_lock_count(rn), HVTYNL);
755
756
0
  for (bpi = rn->info; bpi; bpi = bpi->next) {
757
0
    rfapiPrintBi(stream, bpi);
758
0
  }
759
760
  /* doesn't show montors */
761
0
}
762
763
void rfapiShowImportTable(void *stream, const char *label, struct agg_table *rt,
764
        int isvpn)
765
0
{
766
0
  struct agg_node *rn;
767
0
  char buf[BUFSIZ];
768
769
0
  int (*fp)(void *, const char *, ...);
770
0
  struct vty *vty;
771
0
  void *out;
772
0
  const char *vty_newline;
773
774
0
  if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
775
0
    return;
776
777
0
  fp(out, "Import Table [%s]%s", label, HVTYNL);
778
779
0
  for (rn = agg_route_top(rt); rn; rn = agg_route_next(rn)) {
780
0
    struct bgp_path_info *bpi;
781
0
    const struct prefix *p = agg_node_get_prefix(rn);
782
783
0
    if (p->family == AF_ETHERNET) {
784
0
      rfapiEthAddr2Str(&p->u.prefix_eth, buf, sizeof(buf));
785
0
    } else {
786
0
      inet_ntop(p->family, &p->u.prefix, buf, sizeof(buf));
787
0
    }
788
789
0
    fp(out, "%s/%d @%p #%d%s", buf, p->prefixlen, rn,
790
0
       agg_node_get_lock_count(rn)
791
0
         - 1, /* account for loop iterator locking */
792
0
       HVTYNL);
793
794
0
    for (bpi = rn->info; bpi; bpi = bpi->next) {
795
0
      rfapiPrintBi(stream, bpi);
796
0
    }
797
798
0
    if (isvpn) {
799
0
      struct rfapi_monitor_vpn *m;
800
0
      for (m = RFAPI_MONITOR_VPN(rn); m; m = m->next) {
801
0
        rfapiDebugPrintMonitorVpn(stream, m);
802
0
      }
803
0
    } else {
804
0
      struct rfapi_monitor_encap *m;
805
0
      for (m = RFAPI_MONITOR_ENCAP(rn); m; m = m->next) {
806
0
        rfapiDebugPrintMonitorEncap(stream, m);
807
0
      }
808
0
    }
809
0
  }
810
0
}
811
812
int rfapiShowVncQueries(void *stream, struct prefix *pfx_match)
813
0
{
814
0
  struct bgp *bgp;
815
0
  struct rfapi *h;
816
0
  struct listnode *node;
817
0
  struct rfapi_descriptor *rfd;
818
819
0
  int (*fp)(void *, const char *, ...);
820
0
  struct vty *vty;
821
0
  void *out;
822
0
  const char *vty_newline;
823
824
0
  int printedheader = 0;
825
0
  int queries_total = 0;
826
0
  int queries_displayed = 0;
827
828
0
  if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
829
0
    return CMD_WARNING;
830
831
0
  bgp = bgp_get_default(); /* assume 1 instance for now */
832
0
  if (!bgp) {
833
0
    vty_out(vty, "No BGP instance\n");
834
0
    return CMD_WARNING;
835
0
  }
836
837
0
  h = bgp->rfapi;
838
0
  if (!h) {
839
0
    vty_out(vty, "No RFAPI instance\n");
840
0
    return CMD_WARNING;
841
0
  }
842
843
0
  for (ALL_LIST_ELEMENTS_RO(&h->descriptors, node, rfd)) {
844
845
0
    struct agg_node *rn;
846
0
    int printedquerier = 0;
847
848
0
    if (!rfd->mon &&
849
0
        !(rfd->mon_eth && skiplist_count(rfd->mon_eth)))
850
0
      continue;
851
852
    /*
853
     * IP Queries
854
     */
855
0
    if (rfd->mon) {
856
0
      for (rn = agg_route_top(rfd->mon); rn;
857
0
           rn = agg_route_next(rn)) {
858
0
        const struct prefix *p =
859
0
          agg_node_get_prefix(rn);
860
0
        struct rfapi_monitor_vpn *m;
861
0
        char buf_remain[BUFSIZ];
862
0
        char buf_pfx[BUFSIZ];
863
864
0
        if (!rn->info)
865
0
          continue;
866
867
0
        m = rn->info;
868
869
0
        ++queries_total;
870
871
0
        if (pfx_match && !prefix_match(pfx_match, p)
872
0
            && !prefix_match(p, pfx_match))
873
0
          continue;
874
875
0
        ++queries_displayed;
876
877
0
        if (!printedheader) {
878
0
          ++printedheader;
879
0
          fp(out, "\n");
880
0
          fp(out, "%-15s %-15s %-15s %-10s\n",
881
0
             "VN Address", "UN Address", "Target",
882
0
             "Remaining");
883
0
        }
884
885
0
        if (!printedquerier) {
886
0
          char buf_vn[BUFSIZ];
887
0
          char buf_un[BUFSIZ];
888
889
0
          rfapiRfapiIpAddr2Str(&rfd->un_addr,
890
0
                   buf_un, BUFSIZ);
891
0
          rfapiRfapiIpAddr2Str(&rfd->vn_addr,
892
0
                   buf_vn, BUFSIZ);
893
894
0
          fp(out, "%-15s %-15s", buf_vn, buf_un);
895
0
          printedquerier = 1;
896
0
        } else
897
0
          fp(out, "%-15s %-15s", "", "");
898
0
        buf_remain[0] = 0;
899
0
        rfapiFormatSeconds(
900
0
          event_timer_remain_second(m->timer),
901
0
          buf_remain, BUFSIZ);
902
0
        fp(out, " %-15s %-10s\n",
903
0
           inet_ntop(m->p.family, &m->p.u.prefix,
904
0
               buf_pfx, sizeof(buf_pfx)),
905
0
           buf_remain);
906
0
      }
907
0
    }
908
909
    /*
910
     * Ethernet Queries
911
     */
912
0
    if (rfd->mon_eth && skiplist_count(rfd->mon_eth)) {
913
914
0
      int rc;
915
0
      void *cursor;
916
0
      struct rfapi_monitor_eth *mon_eth;
917
918
0
      for (cursor = NULL,
919
0
          rc = skiplist_next(rfd->mon_eth, NULL,
920
0
                 (void **)&mon_eth, &cursor);
921
0
           rc == 0;
922
0
           rc = skiplist_next(rfd->mon_eth, NULL,
923
0
            (void **)&mon_eth, &cursor)) {
924
925
0
        char buf_remain[BUFSIZ];
926
0
        char buf_pfx[BUFSIZ];
927
0
        struct prefix pfx_mac;
928
929
0
        ++queries_total;
930
931
0
        vnc_zlog_debug_verbose(
932
0
          "%s: checking rfd=%p mon_eth=%p",
933
0
          __func__, rfd, mon_eth);
934
935
0
        memset((void *)&pfx_mac, 0,
936
0
               sizeof(struct prefix));
937
0
        pfx_mac.family = AF_ETHERNET;
938
0
        pfx_mac.prefixlen = 48;
939
0
        pfx_mac.u.prefix_eth = mon_eth->macaddr;
940
941
0
        if (pfx_match
942
0
            && !prefix_match(pfx_match, &pfx_mac)
943
0
            && !prefix_match(&pfx_mac, pfx_match))
944
0
          continue;
945
946
0
        ++queries_displayed;
947
948
0
        if (!printedheader) {
949
0
          ++printedheader;
950
0
          fp(out, "\n");
951
0
          fp(out,
952
0
             "%-15s %-15s %-17s %10s %-10s\n",
953
0
             "VN Address", "UN Address", "Target",
954
0
             "LNI", "Remaining");
955
0
        }
956
957
0
        if (!printedquerier) {
958
0
          char buf_vn[BUFSIZ];
959
0
          char buf_un[BUFSIZ];
960
961
0
          rfapiRfapiIpAddr2Str(&rfd->un_addr,
962
0
                   buf_un, BUFSIZ);
963
0
          rfapiRfapiIpAddr2Str(&rfd->vn_addr,
964
0
                   buf_vn, BUFSIZ);
965
966
0
          fp(out, "%-15s %-15s", buf_vn, buf_un);
967
0
          printedquerier = 1;
968
0
        } else
969
0
          fp(out, "%-15s %-15s", "", "");
970
0
        buf_remain[0] = 0;
971
0
        rfapiFormatSeconds(event_timer_remain_second(
972
0
                 mon_eth->timer),
973
0
               buf_remain, BUFSIZ);
974
0
        fp(out, " %-17s %10d %-10s\n",
975
0
           rfapi_ntop(pfx_mac.family, &pfx_mac.u.prefix,
976
0
                buf_pfx, BUFSIZ),
977
0
           mon_eth->logical_net_id, buf_remain);
978
0
      }
979
0
    }
980
0
  }
981
982
0
  if (queries_total) {
983
0
    fp(out, "\n");
984
0
    fp(out, "Displayed %d out of %d total queries\n",
985
0
       queries_displayed, queries_total);
986
0
  }
987
0
  return CMD_SUCCESS;
988
0
}
989
990
static int rfapiPrintRemoteRegBi(struct bgp *bgp, void *stream,
991
         struct agg_node *rn, struct bgp_path_info *bpi)
992
0
{
993
0
  int (*fp)(void *, const char *, ...);
994
0
  struct vty *vty;
995
0
  void *out;
996
0
  const char *vty_newline;
997
0
  struct prefix pfx_un;
998
0
  struct prefix pfx_vn;
999
0
  uint8_t cost;
1000
0
  uint32_t lifetime;
1001
0
  bgp_encap_types tun_type = BGP_ENCAP_TYPE_MPLS;/*Default tunnel type*/
1002
1003
0
  char buf_pfx[BUFSIZ];
1004
0
  char buf_ntop[BUFSIZ];
1005
0
  char buf_un[BUFSIZ];
1006
0
  char buf_vn[BUFSIZ];
1007
0
  char buf_lifetime[BUFSIZ];
1008
0
  int nlines = 0;
1009
0
  const struct prefix *p = agg_node_get_prefix(rn);
1010
1011
0
  if (!stream)
1012
0
    return 0; /* for debug log, print into buf & call output once */
1013
1014
0
  if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
1015
0
    return 0;
1016
1017
  /*
1018
   * Prefix
1019
   */
1020
0
  buf_pfx[0] = 0;
1021
0
  snprintf(
1022
0
    buf_pfx, sizeof(buf_pfx), "%s/%d",
1023
0
    rfapi_ntop(p->family, &p->u.prefix, buf_ntop, sizeof(buf_ntop)),
1024
0
    p->prefixlen);
1025
0
  buf_pfx[BUFSIZ - 1] = 0;
1026
0
  nlines++;
1027
1028
  /*
1029
   * UN addr
1030
   */
1031
0
  buf_un[0] = 0;
1032
0
  if (!rfapiGetUnAddrOfVpnBi(bpi, &pfx_un)) {
1033
0
    snprintf(buf_un, sizeof(buf_un), "%s",
1034
0
       inet_ntop(pfx_un.family, &pfx_un.u.prefix, buf_ntop,
1035
0
           sizeof(buf_ntop)));
1036
0
  }
1037
1038
0
  bgp_attr_extcom_tunnel_type(bpi->attr, &tun_type);
1039
  /*
1040
   * VN addr
1041
   */
1042
0
  buf_vn[0] = 0;
1043
0
  rfapiNexthop2Prefix(bpi->attr, &pfx_vn);
1044
0
  if (tun_type == BGP_ENCAP_TYPE_MPLS) {
1045
    /* MPLS carries un in nrli next hop (same as vn for IP tunnels)
1046
     */
1047
0
    snprintf(buf_un, sizeof(buf_un), "%s",
1048
0
       inet_ntop(pfx_vn.family, &pfx_vn.u.prefix, buf_ntop,
1049
0
           sizeof(buf_ntop)));
1050
0
    if (bpi->extra) {
1051
0
      uint32_t l = decode_label(&bpi->extra->label[0]);
1052
0
      snprintf(buf_vn, sizeof(buf_vn), "Label: %d", l);
1053
0
    } else /* should never happen */
1054
0
    {
1055
0
      snprintf(buf_vn, sizeof(buf_vn), "Label: N/A");
1056
0
    }
1057
0
  } else {
1058
0
    snprintf(buf_vn, sizeof(buf_vn), "%s",
1059
0
       inet_ntop(pfx_vn.family, &pfx_vn.u.prefix, buf_ntop,
1060
0
           sizeof(buf_ntop)));
1061
0
  }
1062
0
  buf_vn[BUFSIZ - 1] = 0;
1063
0
  buf_un[BUFSIZ - 1] = 0;
1064
1065
  /*
1066
   * Cost is encoded in local_pref as (255-cost)
1067
   * See rfapi_import.c'rfapiRouteInfo2NextHopEntry() for conversion
1068
   * back to cost.
1069
   */
1070
0
  uint32_t local_pref;
1071
1072
0
  if (bpi->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
1073
0
    local_pref = bpi->attr->local_pref;
1074
0
  else
1075
0
    local_pref = 0;
1076
0
  cost = (local_pref > 255) ? 0 : 255 - local_pref;
1077
1078
0
  fp(out, "%-20s ", buf_pfx);
1079
0
  fp(out, "%-15s ", buf_vn);
1080
0
  fp(out, "%-15s ", buf_un);
1081
0
  fp(out, "%-4d ", cost);
1082
1083
  /* Lifetime */
1084
  /* NB rfapiGetVncLifetime sets infinite value when returning !0 */
1085
0
  if (rfapiGetVncLifetime(bpi->attr, &lifetime)
1086
0
      || (lifetime == RFAPI_INFINITE_LIFETIME)) {
1087
1088
0
    fp(out, "%-10s ", "infinite");
1089
0
  } else {
1090
0
    time_t t_lifetime = lifetime;
1091
0
    rfapiFormatSeconds(t_lifetime, buf_lifetime, BUFSIZ);
1092
0
    fp(out, "%-10s ", buf_lifetime);
1093
0
  }
1094
1095
0
  if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED) && bpi->extra
1096
0
      && bpi->extra->vnc.import.timer) {
1097
1098
0
    uint32_t remaining;
1099
0
    time_t age;
1100
0
    char buf_age[BUFSIZ];
1101
1102
0
    struct event *t = (struct event *)bpi->extra->vnc.import.timer;
1103
0
    remaining = event_timer_remain_second(t);
1104
1105
#ifdef RFAPI_REGISTRATIONS_REPORT_AGE
1106
    /*
1107
     * Calculate when the timer started. Doing so here saves
1108
     * us a timestamp field in "struct bgp_path_info".
1109
     *
1110
     * See rfapi_import.c'rfapiBiStartWithdrawTimer() for the
1111
     * original calculation.
1112
     */
1113
    age = rfapiGetHolddownFromLifetime(lifetime, factor)
1114
          - remaining;
1115
#else /* report remaining time */
1116
0
    age = remaining;
1117
0
#endif
1118
0
    rfapiFormatSeconds(age, buf_age, BUFSIZ);
1119
1120
0
    fp(out, "%-10s ", buf_age);
1121
1122
0
  } else if (RFAPI_LOCAL_BI(bpi)) {
1123
1124
0
    char buf_age[BUFSIZ];
1125
1126
0
    if (bpi->extra && bpi->extra->vnc.import.create_time) {
1127
0
      rfapiFormatAge(bpi->extra->vnc.import.create_time,
1128
0
               buf_age, BUFSIZ);
1129
0
    } else {
1130
0
      buf_age[0] = '?';
1131
0
      buf_age[1] = 0;
1132
0
    }
1133
0
    fp(out, "%-10s ", buf_age);
1134
0
  }
1135
0
  fp(out, "%s", HVTYNL);
1136
1137
0
  if (p->family == AF_ETHERNET) {
1138
    /*
1139
     * If there is a corresponding IP address && != VN address,
1140
     * print that on the next line
1141
     */
1142
1143
0
    if (bpi->extra && bpi->extra->vnc.import.aux_prefix.family) {
1144
0
      const char *sp;
1145
1146
0
      sp = rfapi_ntop(
1147
0
        bpi->extra->vnc.import.aux_prefix.family,
1148
0
        &bpi->extra->vnc.import.aux_prefix.u.prefix,
1149
0
        buf_ntop, BUFSIZ);
1150
0
      buf_ntop[BUFSIZ - 1] = 0;
1151
1152
0
      if (sp && strcmp(buf_vn, sp) != 0) {
1153
0
        fp(out, "  IP: %s", sp);
1154
0
        if (nlines == 1)
1155
0
          nlines++;
1156
0
      }
1157
0
    }
1158
0
  }
1159
0
  if (tun_type != BGP_ENCAP_TYPE_MPLS && bpi->extra) {
1160
0
    uint32_t l = decode_label(&bpi->extra->label[0]);
1161
1162
0
    if (!MPLS_LABEL_IS_NULL(l)) {
1163
0
      fp(out, "  Label: %d", l);
1164
0
      if (nlines == 1)
1165
0
        nlines++;
1166
0
    }
1167
0
  }
1168
0
  if (nlines > 1)
1169
0
    fp(out, "%s", HVTYNL);
1170
1171
0
  return 1;
1172
0
}
1173
1174
static int rfapiShowRemoteRegistrationsIt(struct bgp *bgp, void *stream,
1175
            struct rfapi_import_table *it,
1176
            struct prefix *prefix_only,
1177
            int show_expiring, /* either/or */
1178
            int show_local, int show_remote,
1179
            int show_imported, /* either/or */
1180
            uint32_t *pLni) /* AFI_L2VPN only */
1181
0
{
1182
0
  afi_t afi;
1183
0
  int printed_rtlist_hdr = 0;
1184
1185
0
  int (*fp)(void *, const char *, ...);
1186
0
  struct vty *vty;
1187
0
  void *out;
1188
0
  const char *vty_newline;
1189
0
  int total = 0;
1190
0
  int printed = 0;
1191
1192
0
  if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
1193
0
    return printed;
1194
1195
0
  for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
1196
1197
0
    struct agg_node *rn;
1198
1199
0
    if (!it->imported_vpn[afi])
1200
0
      continue;
1201
1202
0
    for (rn = agg_route_top(it->imported_vpn[afi]); rn;
1203
0
         rn = agg_route_next(rn)) {
1204
0
      const struct prefix *p = agg_node_get_prefix(rn);
1205
0
      struct bgp_path_info *bpi;
1206
0
      int count_only;
1207
1208
      /* allow for wider or more narrow mask from user */
1209
0
      if (prefix_only && !prefix_match(prefix_only, p)
1210
0
          && !prefix_match(p, prefix_only))
1211
0
        count_only = 1;
1212
0
      else
1213
0
        count_only = 0;
1214
1215
0
      for (bpi = rn->info; bpi; bpi = bpi->next) {
1216
1217
0
        if (!show_local && RFAPI_LOCAL_BI(bpi)) {
1218
1219
          /* local route from RFP */
1220
0
          continue;
1221
0
        }
1222
1223
0
        if (!show_remote && !RFAPI_LOCAL_BI(bpi)) {
1224
1225
          /* remote route */
1226
0
          continue;
1227
0
        }
1228
1229
0
        if (show_expiring
1230
0
            && !CHECK_FLAG(bpi->flags,
1231
0
               BGP_PATH_REMOVED))
1232
0
          continue;
1233
1234
0
        if (!show_expiring
1235
0
            && CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
1236
0
          continue;
1237
1238
0
        if (bpi->type == ZEBRA_ROUTE_BGP_DIRECT
1239
0
            || bpi->type
1240
0
                 == ZEBRA_ROUTE_BGP_DIRECT_EXT) {
1241
0
          if (!show_imported)
1242
0
            continue;
1243
0
        } else {
1244
0
          if (show_imported)
1245
0
            continue;
1246
0
        }
1247
1248
0
        total++;
1249
0
        if (count_only == 1)
1250
0
          continue;
1251
0
        if (!printed_rtlist_hdr) {
1252
0
          const char *agetype = "";
1253
0
          char *s;
1254
0
          const char *type = "";
1255
0
          if (show_imported) {
1256
0
            type = "Imported";
1257
0
          } else {
1258
0
            if (show_expiring) {
1259
0
              type = "Holddown";
1260
0
            } else {
1261
0
              if (RFAPI_LOCAL_BI(
1262
0
                    bpi)) {
1263
0
                type = "Local";
1264
0
              } else {
1265
0
                type = "Remote";
1266
0
              }
1267
0
            }
1268
0
          }
1269
1270
0
          s = ecommunity_ecom2str(
1271
0
            it->rt_import_list,
1272
0
            ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
1273
1274
0
          if (pLni) {
1275
0
            fp(out,
1276
0
               "%s[%s] L2VPN Network 0x%x (%u) RT={%s}",
1277
0
               HVTYNL, type, *pLni,
1278
0
               (*pLni & 0xfff), s);
1279
0
          } else {
1280
0
            fp(out, "%s[%s] Prefix RT={%s}",
1281
0
               HVTYNL, type, s);
1282
0
          }
1283
0
          XFREE(MTYPE_ECOMMUNITY_STR, s);
1284
1285
0
          if (it->rfg && it->rfg->name) {
1286
0
            fp(out, " %s \"%s\"",
1287
0
               (it->rfg->type == RFAPI_GROUP_CFG_VRF
1288
0
                  ? "VRF"
1289
0
                  : "NVE group"),
1290
0
               it->rfg->name);
1291
0
          }
1292
0
          fp(out, "%s", HVTYNL);
1293
0
          if (show_expiring) {
1294
#ifdef RFAPI_REGISTRATIONS_REPORT_AGE
1295
            agetype = "Age";
1296
#else
1297
0
            agetype = "Remaining";
1298
0
#endif
1299
0
          } else if (show_local) {
1300
0
            agetype = "Age";
1301
0
          }
1302
1303
0
          printed_rtlist_hdr = 1;
1304
1305
0
          fp(out,
1306
0
             "%-20s %-15s %-15s %4s %-10s %-10s%s",
1307
0
             (pLni ? "L2 Address/IP" : "Prefix"),
1308
0
             "VN Address", "UN Address", "Cost",
1309
0
             "Lifetime", agetype, HVTYNL);
1310
0
        }
1311
0
        printed += rfapiPrintRemoteRegBi(bgp, stream,
1312
0
                 rn, bpi);
1313
0
      }
1314
0
    }
1315
0
  }
1316
1317
0
  if (printed > 0) {
1318
1319
0
    const char *type = "prefixes";
1320
1321
0
    if (show_imported) {
1322
0
      type = "imported prefixes";
1323
0
    } else {
1324
0
      if (show_expiring) {
1325
0
        type = "prefixes in holddown";
1326
0
      } else {
1327
0
        if (show_local && !show_remote) {
1328
0
          type = "locally registered prefixes";
1329
0
        } else if (!show_local && show_remote) {
1330
0
          type = "remotely registered prefixes";
1331
0
        }
1332
0
      }
1333
0
    }
1334
1335
0
    fp(out, "Displayed %d out of %d %s%s", printed, total, type,
1336
0
       HVTYNL);
1337
#if DEBUG_SHOW_EXTRA
1338
    fp(out, "IT table above: it=%p%s", it, HVTYNL);
1339
#endif
1340
0
  }
1341
0
  return printed;
1342
0
}
1343
1344
1345
/*
1346
 * rfapiShowRemoteRegistrations
1347
 *
1348
 * Similar to rfapiShowImportTable() above. This function
1349
 * is mean to produce the "remote" portion of the output
1350
 * of "show vnc registrations".
1351
 */
1352
int rfapiShowRemoteRegistrations(void *stream, struct prefix *prefix_only,
1353
         int show_expiring, int show_local,
1354
         int show_remote, int show_imported)
1355
0
{
1356
0
  struct bgp *bgp;
1357
0
  struct rfapi *h;
1358
0
  struct rfapi_import_table *it;
1359
0
  int printed = 0;
1360
1361
0
  bgp = bgp_get_default();
1362
0
  if (!bgp) {
1363
0
    return printed;
1364
0
  }
1365
1366
0
  h = bgp->rfapi;
1367
0
  if (!h) {
1368
0
    return printed;
1369
0
  }
1370
1371
0
  for (it = h->imports; it; it = it->next) {
1372
0
    printed += rfapiShowRemoteRegistrationsIt(
1373
0
      bgp, stream, it, prefix_only, show_expiring, show_local,
1374
0
      show_remote, show_imported, NULL);
1375
0
  }
1376
1377
0
  if (h->import_mac) {
1378
0
    void *cursor = NULL;
1379
0
    int rc;
1380
0
    uintptr_t lni_as_ptr;
1381
0
    uint32_t lni;
1382
0
    uint32_t *pLni;
1383
1384
0
    for (rc = skiplist_next(h->import_mac, (void **)&lni_as_ptr,
1385
0
          (void **)&it, &cursor);
1386
0
         !rc;
1387
0
         rc = skiplist_next(h->import_mac, (void **)&lni_as_ptr,
1388
0
          (void **)&it, &cursor)) {
1389
0
      pLni = NULL;
1390
0
      if ((lni_as_ptr & 0xffffffff) == lni_as_ptr) {
1391
0
        lni = (uint32_t)(lni_as_ptr & 0xffffffff);
1392
0
        pLni = &lni;
1393
0
      }
1394
1395
0
      printed += rfapiShowRemoteRegistrationsIt(
1396
0
        bgp, stream, it, prefix_only, show_expiring,
1397
0
        show_local, show_remote, show_imported, pLni);
1398
0
    }
1399
0
  }
1400
1401
0
  return printed;
1402
0
}
1403
1404
/*------------------------------------------
1405
 * rfapiRfapiIpAddr2Str
1406
 *
1407
 * UI helper: generate string from rfapi_ip_addr
1408
 *
1409
 * input:
1410
 *  a     IP v4/v6 address
1411
 *
1412
 * output
1413
 *  buf     put string here
1414
 *  bufsize     max space to write
1415
 *
1416
 * return value:
1417
 *  NULL      conversion failed
1418
 *  non-NULL    pointer to buf
1419
 --------------------------------------------*/
1420
const char *rfapiRfapiIpAddr2Str(struct rfapi_ip_addr *a, char *buf,
1421
         int bufsize)
1422
0
{
1423
0
  const char *rc = NULL;
1424
1425
0
  switch (a->addr_family) {
1426
0
  case AF_INET:
1427
0
    rc = inet_ntop(a->addr_family, &a->addr.v4, buf, bufsize);
1428
0
    break;
1429
0
  case AF_INET6:
1430
0
    rc = inet_ntop(a->addr_family, &a->addr.v6, buf, bufsize);
1431
0
    break;
1432
0
  }
1433
0
  return rc;
1434
0
}
1435
1436
void rfapiPrintRfapiIpAddr(void *stream, struct rfapi_ip_addr *a)
1437
0
{
1438
0
  char buf[BUFSIZ];
1439
0
  const char *rc = NULL;
1440
1441
0
  int (*fp)(void *, const char *, ...);
1442
0
  struct vty *vty;
1443
0
  void *out = NULL;
1444
0
  const char *vty_newline;
1445
1446
0
  if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
1447
0
    return;
1448
1449
0
  rc = rfapiRfapiIpAddr2Str(a, buf, BUFSIZ);
1450
1451
0
  if (rc)
1452
0
    fp(out, "%s", buf);
1453
0
}
1454
1455
const char *rfapiRfapiIpPrefix2Str(struct rfapi_ip_prefix *p, char *buf,
1456
           int bufsize)
1457
0
{
1458
0
  struct rfapi_ip_addr *a = &p->prefix;
1459
0
  const char *rc = NULL;
1460
1461
0
  switch (a->addr_family) {
1462
0
  case AF_INET:
1463
0
    rc = inet_ntop(a->addr_family, &a->addr.v4, buf, bufsize);
1464
0
    break;
1465
0
  case AF_INET6:
1466
0
    rc = inet_ntop(a->addr_family, &a->addr.v6, buf, bufsize);
1467
0
    break;
1468
0
  }
1469
1470
0
  if (rc) {
1471
0
    int alen = strlen(buf);
1472
0
    int remaining = bufsize - alen - 1;
1473
0
    int slen;
1474
1475
0
    if (remaining > 0) {
1476
0
      slen = snprintf(buf + alen, remaining, "/%u",
1477
0
          p->length);
1478
0
      if (slen < remaining) /* see man page for snprintf(3) */
1479
0
        return rc;
1480
0
    }
1481
0
  }
1482
1483
0
  return NULL;
1484
0
}
1485
1486
void rfapiPrintRfapiIpPrefix(void *stream, struct rfapi_ip_prefix *p)
1487
0
{
1488
0
  char buf[BUFSIZ];
1489
0
  const char *rc;
1490
1491
0
  int (*fp)(void *, const char *, ...);
1492
0
  struct vty *vty;
1493
0
  void *out = NULL;
1494
0
  const char *vty_newline;
1495
1496
0
  if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
1497
0
    return;
1498
1499
0
  rc = rfapiRfapiIpPrefix2Str(p, buf, BUFSIZ);
1500
1501
0
  if (rc)
1502
0
    fp(out, "%s:%u", buf, p->cost);
1503
0
  else
1504
0
    fp(out, "?/?:?");
1505
0
}
1506
1507
void rfapiPrintAdvertisedInfo(struct vty *vty, struct rfapi_descriptor *rfd,
1508
            safi_t safi, struct prefix *p)
1509
0
{
1510
0
  afi_t afi; /* of the VN address */
1511
0
  struct bgp_dest *bd;
1512
0
  struct bgp_path_info *bpi;
1513
0
  uint8_t type = ZEBRA_ROUTE_BGP;
1514
0
  struct bgp *bgp;
1515
0
  int printed = 0;
1516
0
  struct prefix_rd prd0;
1517
0
  struct prefix_rd *prd;
1518
1519
  /*
1520
   * Find the bgp_path in the RIB corresponding to this
1521
   * prefix and rfd
1522
   */
1523
1524
0
  afi = family2afi(p->family);
1525
0
  assert(afi == AFI_IP || afi == AFI_IP6);
1526
1527
0
  bgp = bgp_get_default(); /* assume 1 instance for now */
1528
0
  assert(bgp);
1529
1530
0
  if (safi == SAFI_ENCAP) {
1531
0
    memset(&prd0, 0, sizeof(prd0));
1532
0
    prd0.family = AF_UNSPEC;
1533
0
    prd0.prefixlen = 64;
1534
0
    prd = &prd0;
1535
0
  } else {
1536
0
    prd = &rfd->rd;
1537
0
  }
1538
0
  bd = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
1539
1540
0
  vty_out(vty, "  bd=%p%s", bd, HVTYNL);
1541
1542
0
  for (bpi = bgp_dest_get_bgp_path_info(bd); bpi; bpi = bpi->next) {
1543
0
    if (bpi->peer == rfd->peer && bpi->type == type
1544
0
        && bpi->sub_type == BGP_ROUTE_RFP && bpi->extra
1545
0
        && bpi->extra->vnc.export.rfapi_handle == (void *)rfd) {
1546
1547
0
      rfapiPrintBi(vty, bpi);
1548
0
      printed = 1;
1549
0
    }
1550
0
  }
1551
1552
0
  if (!printed) {
1553
0
    vty_out(vty, "    --?--%s", HVTYNL);
1554
0
    return;
1555
0
  }
1556
0
}
1557
1558
void rfapiPrintDescriptor(struct vty *vty, struct rfapi_descriptor *rfd)
1559
0
{
1560
  /* pHD un-addr vn-addr pCB cookie rd lifetime */
1561
  /* RT export list */
1562
  /* RT import list */
1563
  /* list of advertised prefixes */
1564
  /* dump import table */
1565
1566
0
  char *s;
1567
0
  void *cursor;
1568
0
  int rc;
1569
0
  afi_t afi;
1570
0
  struct rfapi_adb *adb;
1571
1572
0
  vty_out(vty, "%-10p ", rfd);
1573
0
  rfapiPrintRfapiIpAddr(vty, &rfd->un_addr);
1574
0
  vty_out(vty, " ");
1575
0
  rfapiPrintRfapiIpAddr(vty, &rfd->vn_addr);
1576
0
  vty_out(vty, " %p %p ", rfd->response_cb, rfd->cookie);
1577
0
  vty_out(vty, "%pRDP", &rfd->rd);
1578
0
  vty_out(vty, " %d", rfd->response_lifetime);
1579
0
  vty_out(vty, " %s", (rfd->rfg ? rfd->rfg->name : "<orphaned>"));
1580
0
  vty_out(vty, "%s", HVTYNL);
1581
1582
0
  vty_out(vty, " Peer %p #%d%s", rfd->peer, rfd->peer->lock, HVTYNL);
1583
1584
  /* export RT list */
1585
0
  if (rfd->rt_export_list) {
1586
0
    s = ecommunity_ecom2str(rfd->rt_export_list,
1587
0
          ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
1588
0
    vty_out(vty, " Export %s%s", s, HVTYNL);
1589
0
    XFREE(MTYPE_ECOMMUNITY_STR, s);
1590
0
  } else {
1591
0
    vty_out(vty, " Export (nil)%s", HVTYNL);
1592
0
  }
1593
1594
  /* import RT list */
1595
0
  if (rfd->import_table) {
1596
0
    s = ecommunity_ecom2str(rfd->import_table->rt_import_list,
1597
0
          ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
1598
0
    vty_out(vty, " Import %s%s", s, HVTYNL);
1599
0
    XFREE(MTYPE_ECOMMUNITY_STR, s);
1600
0
  } else {
1601
0
    vty_out(vty, " Import (nil)%s", HVTYNL);
1602
0
  }
1603
1604
0
  for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
1605
0
    uint8_t family;
1606
1607
0
    family = afi2family(afi);
1608
0
    if (!family)
1609
0
      continue;
1610
1611
0
    cursor = NULL;
1612
0
    for (rc = skiplist_next(rfd->advertised.ipN_by_prefix, NULL,
1613
0
          (void **)&adb, &cursor);
1614
0
         rc == 0;
1615
0
         rc = skiplist_next(rfd->advertised.ipN_by_prefix, NULL,
1616
0
          (void **)&adb, &cursor)) {
1617
1618
      /* group like family prefixes together in output */
1619
0
      if (family != adb->u.s.prefix_ip.family)
1620
0
        continue;
1621
1622
0
      vty_out(vty, "  Adv Pfx: %pFX%s", &adb->u.s.prefix_ip,
1623
0
        HVTYNL);
1624
0
      rfapiPrintAdvertisedInfo(vty, rfd, SAFI_MPLS_VPN,
1625
0
             &adb->u.s.prefix_ip);
1626
0
    }
1627
0
  }
1628
0
  for (rc = skiplist_next(rfd->advertised.ip0_by_ether, NULL,
1629
0
        (void **)&adb, &cursor);
1630
0
       rc == 0; rc = skiplist_next(rfd->advertised.ip0_by_ether, NULL,
1631
0
           (void **)&adb, &cursor)) {
1632
0
    vty_out(vty, "  Adv Pfx: %pFX%s", &adb->u.s.prefix_eth, HVTYNL);
1633
1634
    /* TBD update the following function to print ethernet info */
1635
    /* Also need to pass/use rd */
1636
0
    rfapiPrintAdvertisedInfo(vty, rfd, SAFI_MPLS_VPN,
1637
0
           &adb->u.s.prefix_ip);
1638
0
  }
1639
0
  vty_out(vty, "%s", HVTYNL);
1640
0
}
1641
1642
/*
1643
 * test scripts rely on first line for each nve starting in 1st column,
1644
 * leading whitespace for additional detail of that nve
1645
 */
1646
void rfapiPrintMatchingDescriptors(struct vty *vty, struct prefix *vn_prefix,
1647
           struct prefix *un_prefix)
1648
0
{
1649
0
  struct bgp *bgp;
1650
0
  struct rfapi *h;
1651
0
  struct listnode *ln;
1652
0
  struct rfapi_descriptor *rfd;
1653
0
  int printed = 0;
1654
1655
0
  bgp = bgp_get_default(); /* assume 1 instance for now */
1656
0
  if (!bgp)
1657
0
    return;
1658
1659
0
  h = bgp->rfapi;
1660
0
  assert(h);
1661
1662
0
  for (ln = listhead(&h->descriptors); ln; ln = listnextnode(ln)) {
1663
0
    rfd = listgetdata(ln);
1664
1665
0
    struct prefix pfx;
1666
1667
0
    if (vn_prefix) {
1668
0
      assert(!rfapiRaddr2Qprefix(&rfd->vn_addr, &pfx));
1669
0
      if (!prefix_match(vn_prefix, &pfx))
1670
0
        continue;
1671
0
    }
1672
1673
0
    if (un_prefix) {
1674
0
      assert(!rfapiRaddr2Qprefix(&rfd->un_addr, &pfx));
1675
0
      if (!prefix_match(un_prefix, &pfx))
1676
0
        continue;
1677
0
    }
1678
1679
0
    if (!printed) {
1680
      /* print column header */
1681
0
      vty_out(vty, "%s %s %s %s %s %s %s %s%s", "descriptor",
1682
0
        "un-addr", "vn-addr", "callback", "cookie",
1683
0
        "RD", "lifetime", "group", HVTYNL);
1684
0
    }
1685
0
    rfapiPrintDescriptor(vty, rfd);
1686
0
    printed = 1;
1687
0
  }
1688
0
}
1689
1690
1691
/*
1692
 * Parse an address and put into a struct prefix
1693
 */
1694
int rfapiCliGetPrefixAddr(struct vty *vty, const char *str, struct prefix *p)
1695
0
{
1696
0
  if (!str2prefix(str, p)) {
1697
0
    vty_out(vty, "Malformed address \"%s\"%s", str ? str : "null",
1698
0
      HVTYNL);
1699
0
    return CMD_WARNING;
1700
0
  }
1701
0
  switch (p->family) {
1702
0
  case AF_INET:
1703
0
    if (p->prefixlen != IPV4_MAX_BITLEN) {
1704
0
      vty_out(vty, "Not a host address: \"%s\"%s", str,
1705
0
        HVTYNL);
1706
0
      return CMD_WARNING;
1707
0
    }
1708
0
    break;
1709
0
  case AF_INET6:
1710
0
    if (p->prefixlen != IPV6_MAX_BITLEN) {
1711
0
      vty_out(vty, "Not a host address: \"%s\"%s", str,
1712
0
        HVTYNL);
1713
0
      return CMD_WARNING;
1714
0
    }
1715
0
    break;
1716
0
  default:
1717
0
    vty_out(vty, "Invalid address \"%s\"%s", str, HVTYNL);
1718
0
    return CMD_WARNING;
1719
0
  }
1720
0
  return 0;
1721
0
}
1722
1723
int rfapiCliGetRfapiIpAddr(struct vty *vty, const char *str,
1724
         struct rfapi_ip_addr *hai)
1725
0
{
1726
0
  struct prefix pfx;
1727
0
  int rc;
1728
1729
0
  rc = rfapiCliGetPrefixAddr(vty, str, &pfx);
1730
0
  if (rc)
1731
0
    return rc;
1732
1733
0
  hai->addr_family = pfx.family;
1734
0
  if (pfx.family == AF_INET)
1735
0
    hai->addr.v4 = pfx.u.prefix4;
1736
0
  else
1737
0
    hai->addr.v6 = pfx.u.prefix6;
1738
1739
0
  return 0;
1740
0
}
1741
1742
/*
1743
 * Note: this function does not flush vty output, so if it is called
1744
 * with a stream pointing to a vty, the user will have to type something
1745
 * before the callback output shows up
1746
 */
1747
void rfapiPrintNhl(void *stream, struct rfapi_next_hop_entry *next_hops)
1748
0
{
1749
0
  struct rfapi_next_hop_entry *nh;
1750
0
  int count;
1751
1752
0
  int (*fp)(void *, const char *, ...);
1753
0
  struct vty *vty;
1754
0
  void *out;
1755
0
  const char *vty_newline;
1756
1757
0
#define REMAIN (BUFSIZ - (p-line))
1758
0
#define INCP {p += (r > REMAIN)? REMAIN: r;}
1759
1760
0
  if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
1761
0
    return;
1762
1763
0
  for (nh = next_hops, count = 1; nh; nh = nh->next, ++count) {
1764
1765
0
    char line[BUFSIZ];
1766
0
    char *p = line;
1767
0
    int r;
1768
1769
0
    r = snprintf(p, REMAIN, "%3d  pfx=", count);
1770
0
    INCP;
1771
1772
0
    if (rfapiRfapiIpPrefix2Str(&nh->prefix, p, REMAIN)) {
1773
      /* it fit, so count length */
1774
0
      r = strlen(p);
1775
0
    } else {
1776
      /* didn't fit */
1777
0
      goto truncate;
1778
0
    }
1779
0
    INCP;
1780
1781
0
    r = snprintf(p, REMAIN, ", un=");
1782
0
    INCP;
1783
1784
0
    if (rfapiRfapiIpAddr2Str(&nh->un_address, p, REMAIN)) {
1785
      /* it fit, so count length */
1786
0
      r = strlen(p);
1787
0
    } else {
1788
      /* didn't fit */
1789
0
      goto truncate;
1790
0
    }
1791
0
    INCP;
1792
1793
0
    r = snprintf(p, REMAIN, ", vn=");
1794
0
    INCP;
1795
1796
0
    if (rfapiRfapiIpAddr2Str(&nh->vn_address, p, REMAIN)) {
1797
      /* it fit, so count length */
1798
0
      r = strlen(p);
1799
0
    } else {
1800
      /* didn't fit */
1801
0
      goto truncate;
1802
0
    }
1803
0
    INCP;
1804
1805
0
  truncate:
1806
0
    line[BUFSIZ - 1] = 0;
1807
0
    fp(out, "%s%s", line, HVTYNL);
1808
1809
    /*
1810
     * options
1811
     */
1812
0
    if (nh->vn_options) {
1813
0
      struct rfapi_vn_option *vo;
1814
0
      char offset[] = "     ";
1815
1816
0
      for (vo = nh->vn_options; vo; vo = vo->next) {
1817
0
        char pbuf[100];
1818
1819
0
        switch (vo->type) {
1820
0
        case RFAPI_VN_OPTION_TYPE_L2ADDR:
1821
0
          rfapiEthAddr2Str(&vo->v.l2addr.macaddr,
1822
0
               pbuf, sizeof(pbuf));
1823
0
          fp(out,
1824
0
             "%sL2 %s LBL=0x%06x NETID=0x%06x NVEID=%d%s",
1825
0
             offset, pbuf,
1826
0
             (vo->v.l2addr.label & 0x00ffffff),
1827
0
             (vo->v.l2addr.logical_net_id
1828
0
              & 0x00ffffff),
1829
0
             vo->v.l2addr.local_nve_id, HVTYNL);
1830
0
          break;
1831
1832
0
        case RFAPI_VN_OPTION_TYPE_LOCAL_NEXTHOP:
1833
0
          fp(out, "%sLNH %pFX cost=%d%s", offset,
1834
0
             &vo->v.local_nexthop.addr,
1835
0
             vo->v.local_nexthop.cost, HVTYNL);
1836
0
          break;
1837
1838
0
        case RFAPI_VN_OPTION_TYPE_INTERNAL_RD:
1839
0
          fp(out,
1840
0
             "%svn option type %d (unknown)%s",
1841
0
             offset, vo->type, HVTYNL);
1842
0
          break;
1843
0
        }
1844
0
      }
1845
0
    }
1846
0
    if (nh->un_options) {
1847
0
      struct rfapi_un_option *uo;
1848
0
      char offset[] = "     ";
1849
1850
0
      for (uo = nh->un_options; uo; uo = uo->next) {
1851
0
        switch (uo->type) {
1852
0
        case RFAPI_UN_OPTION_TYPE_TUNNELTYPE:
1853
0
          rfapi_print_tunneltype_option(
1854
0
            stream, 8, &uo->v.tunnel);
1855
0
          break;
1856
0
        case RFAPI_UN_OPTION_TYPE_PROVISIONAL:
1857
0
          fp(out, "%sUN Option type %d%s", offset,
1858
0
             uo->type, vty_newline);
1859
0
          break;
1860
0
        }
1861
0
      }
1862
0
    }
1863
0
  }
1864
0
}
1865
1866
/***********************************************************************
1867
 *      STATIC ROUTES
1868
 ***********************************************************************/
1869
1870
/*
1871
 * Add another nexthop to the NHL
1872
 */
1873
static void rfapiAddDeleteLocalRfpPrefix(struct rfapi_ip_addr *un_addr,
1874
           struct rfapi_ip_addr *vn_addr,
1875
           struct rfapi_ip_prefix *rprefix,
1876
           int is_add,
1877
           uint32_t lifetime, /* add only */
1878
           struct rfapi_vn_option *vn_options,
1879
           struct rfapi_next_hop_entry **head,
1880
           struct rfapi_next_hop_entry **tail)
1881
0
{
1882
0
  struct rfapi_next_hop_entry *new;
1883
1884
  /*
1885
   * construct NHL
1886
   */
1887
1888
0
  new = XCALLOC(MTYPE_RFAPI_NEXTHOP, sizeof(struct rfapi_next_hop_entry));
1889
0
  new->prefix = *rprefix;
1890
0
  new->un_address = *un_addr;
1891
0
  new->vn_address = *vn_addr;
1892
1893
0
  new->vn_options = vn_options;
1894
0
  if (is_add) {
1895
0
    new->lifetime = lifetime;
1896
0
  } else {
1897
0
    new->lifetime = RFAPI_REMOVE_RESPONSE_LIFETIME;
1898
0
  }
1899
1900
0
  if (*tail)
1901
0
    (*tail)->next = new;
1902
0
  *tail = new;
1903
0
  if (!*head) {
1904
0
    *head = new;
1905
0
  }
1906
0
}
1907
1908
1909
static int
1910
register_add(struct vty *vty, struct cmd_token *carg_prefix,
1911
       struct cmd_token *carg_vn, struct cmd_token *carg_un,
1912
       struct cmd_token *carg_cost,     /* optional */
1913
       struct cmd_token *carg_lifetime, /* optional */
1914
       struct cmd_token *carg_macaddr,  /* optional */
1915
       struct cmd_token
1916
         *carg_vni, /* mac present=>mandatory Virtual Network ID */
1917
       int argc, struct cmd_token **argv)
1918
0
{
1919
0
  const char *arg_prefix = carg_prefix ? carg_prefix->arg : NULL;
1920
0
  const char *arg_vn = carg_vn ? carg_vn->arg : NULL;
1921
0
  const char *arg_un = carg_un ? carg_un->arg : NULL;
1922
0
  const char *arg_cost = carg_cost ? carg_cost->arg : NULL;
1923
0
  const char *arg_lifetime = carg_lifetime ? carg_lifetime->arg : NULL;
1924
0
  const char *arg_macaddr = carg_macaddr ? carg_macaddr->arg : NULL;
1925
0
  const char *arg_vni = carg_vni ? carg_vni->arg : NULL;
1926
0
  struct rfapi_ip_addr vn_address;
1927
0
  struct rfapi_ip_addr un_address;
1928
0
  struct prefix pfx;
1929
0
  struct rfapi_ip_prefix rpfx;
1930
0
  uint32_t cost;
1931
0
  uint32_t lnh_cost;
1932
0
  uint32_t lifetime;
1933
0
  rfapi_handle rfd;
1934
0
  struct rfapi_vn_option optary[10]; /* XXX must be big enough */
1935
0
  struct rfapi_vn_option *opt = NULL;
1936
0
  int opt_next = 0;
1937
1938
0
  int rc = CMD_WARNING_CONFIG_FAILED;
1939
0
  char *endptr;
1940
0
  struct bgp *bgp;
1941
0
  struct rfapi *h;
1942
0
  struct rfapi_cfg *rfapi_cfg;
1943
1944
0
  const char *arg_lnh = NULL;
1945
0
  const char *arg_lnh_cost = NULL;
1946
1947
0
  bgp = bgp_get_default(); /* assume 1 instance for now */
1948
0
  if (!bgp) {
1949
0
    if (vty)
1950
0
      vty_out(vty, "BGP not configured\n");
1951
0
    return CMD_WARNING_CONFIG_FAILED;
1952
0
  }
1953
1954
0
  h = bgp->rfapi;
1955
0
  rfapi_cfg = bgp->rfapi_cfg;
1956
0
  if (!h || !rfapi_cfg) {
1957
0
    if (vty)
1958
0
      vty_out(vty, "RFAPI not configured\n");
1959
0
    return CMD_WARNING_CONFIG_FAILED;
1960
0
  }
1961
1962
0
  for (; argc; --argc, ++argv) {
1963
0
    if (strmatch(argv[0]->text, "local-next-hop")) {
1964
0
      if (arg_lnh) {
1965
0
        vty_out(vty,
1966
0
          "local-next-hop specified more than once\n");
1967
0
        return CMD_WARNING_CONFIG_FAILED;
1968
0
      }
1969
0
      if (argc <= 1) {
1970
0
        vty_out(vty,
1971
0
          "Missing parameter for local-next-hop\n");
1972
0
        return CMD_WARNING_CONFIG_FAILED;
1973
0
      }
1974
0
      ++argv;
1975
0
      --argc;
1976
0
      arg_lnh = argv[0]->arg;
1977
0
    }
1978
0
    if (strmatch(argv[0]->text, "local-cost")) {
1979
0
      if (arg_lnh_cost) {
1980
0
        vty_out(vty,
1981
0
          "local-cost specified more than once\n");
1982
0
        return CMD_WARNING_CONFIG_FAILED;
1983
0
      }
1984
0
      if (argc <= 1) {
1985
0
        vty_out(vty,
1986
0
          "Missing parameter for local-cost\n");
1987
0
        return CMD_WARNING_CONFIG_FAILED;
1988
0
      }
1989
0
      ++argv;
1990
0
      --argc;
1991
0
      arg_lnh_cost = argv[0]->arg;
1992
0
    }
1993
0
  }
1994
1995
0
  if ((rc = rfapiCliGetRfapiIpAddr(vty, arg_vn, &vn_address)))
1996
0
    goto fail;
1997
0
  if ((rc = rfapiCliGetRfapiIpAddr(vty, arg_un, &un_address)))
1998
0
    goto fail;
1999
2000
  /* arg_prefix is optional if mac address is given */
2001
0
  if (arg_macaddr && !arg_prefix) {
2002
    /*
2003
     * fake up a 0/32 or 0/128 prefix
2004
     */
2005
0
    switch (vn_address.addr_family) {
2006
0
    case AF_INET:
2007
0
      arg_prefix = "0.0.0.0/32";
2008
0
      break;
2009
0
    case AF_INET6:
2010
0
      arg_prefix = "0::0/128";
2011
0
      break;
2012
0
    default:
2013
0
      vty_out(vty,
2014
0
        "Internal error, unknown VN address family\n");
2015
0
      return CMD_WARNING_CONFIG_FAILED;
2016
0
    }
2017
0
  }
2018
2019
0
  if (!str2prefix(arg_prefix, &pfx)) {
2020
0
    vty_out(vty, "Malformed prefix \"%s\"\n", arg_prefix);
2021
0
    goto fail;
2022
0
  }
2023
0
  if (pfx.family != AF_INET && pfx.family != AF_INET6) {
2024
0
    vty_out(vty, "prefix \"%s\" has invalid address family\n",
2025
0
      arg_prefix);
2026
0
    goto fail;
2027
0
  }
2028
2029
2030
0
  memset(optary, 0, sizeof(optary));
2031
2032
0
  if (arg_cost) {
2033
0
    endptr = NULL;
2034
0
    cost = strtoul(arg_cost, &endptr, 10);
2035
0
    if (*endptr != '\0' || cost > 255) {
2036
0
      vty_out(vty, "%% Invalid %s value\n", "cost");
2037
0
      goto fail;
2038
0
    }
2039
0
  } else {
2040
0
    cost = 255;
2041
0
  }
2042
2043
0
  if (arg_lifetime) {
2044
0
    if (!strcmp(arg_lifetime, "infinite")) {
2045
0
      lifetime = RFAPI_INFINITE_LIFETIME;
2046
0
    } else {
2047
0
      endptr = NULL;
2048
0
      lifetime = strtoul(arg_lifetime, &endptr, 10);
2049
0
      if (*endptr != '\0') {
2050
0
        vty_out(vty, "%% Invalid %s value\n",
2051
0
          "lifetime");
2052
0
        goto fail;
2053
0
      }
2054
0
    }
2055
0
  } else {
2056
0
    lifetime = RFAPI_INFINITE_LIFETIME; /* default infinite */
2057
0
  }
2058
2059
0
  if (arg_lnh_cost) {
2060
0
    if (!arg_lnh) {
2061
0
      vty_out(vty,
2062
0
        "%% %s may only be specified with local-next-hop\n",
2063
0
        "local-cost");
2064
0
      goto fail;
2065
0
    }
2066
0
    endptr = NULL;
2067
0
    lnh_cost = strtoul(arg_lnh_cost, &endptr, 10);
2068
0
    if (*endptr != '\0' || lnh_cost > 255) {
2069
0
      vty_out(vty, "%% Invalid %s value\n", "local-cost");
2070
0
      goto fail;
2071
0
    }
2072
0
  } else {
2073
0
    lnh_cost = 255;
2074
0
  }
2075
2076
0
  if (arg_lnh) {
2077
0
    if (!arg_prefix) {
2078
0
      vty_out(vty,
2079
0
        "%% %s may only be specified with prefix\n",
2080
0
        "local-next-hop");
2081
0
      goto fail;
2082
0
    }
2083
0
    if ((rc = rfapiCliGetPrefixAddr(
2084
0
           vty, arg_lnh,
2085
0
           &optary[opt_next].v.local_nexthop.addr))) {
2086
2087
0
      goto fail;
2088
0
    }
2089
2090
0
    optary[opt_next].v.local_nexthop.cost = lnh_cost;
2091
0
    optary[opt_next].type = RFAPI_VN_OPTION_TYPE_LOCAL_NEXTHOP;
2092
2093
0
    if (opt_next) {
2094
0
      optary[opt_next - 1].next = optary + opt_next;
2095
0
    } else {
2096
0
      opt = optary;
2097
0
    }
2098
0
    ++opt_next;
2099
0
  }
2100
2101
0
  if (arg_vni && !arg_macaddr) {
2102
0
    vty_out(vty, "%% %s may only be specified with mac address\n",
2103
0
      "virtual-network-identifier");
2104
0
    goto fail;
2105
0
  }
2106
2107
0
  if (arg_macaddr) {
2108
0
    if (!arg_vni) {
2109
0
      vty_out(vty,
2110
0
        "Missing \"vni\" parameter (mandatory with mac)\n");
2111
0
      return CMD_WARNING_CONFIG_FAILED;
2112
0
    }
2113
0
    optary[opt_next].v.l2addr.logical_net_id =
2114
0
      strtoul(arg_vni, NULL, 10);
2115
2116
0
    if ((rc = rfapiStr2EthAddr(
2117
0
           arg_macaddr,
2118
0
           &optary[opt_next].v.l2addr.macaddr))) {
2119
0
      vty_out(vty, "Invalid %s value\n", "mac address");
2120
0
      goto fail;
2121
0
    }
2122
    /* TBD label, NVE ID */
2123
2124
0
    optary[opt_next].type = RFAPI_VN_OPTION_TYPE_L2ADDR;
2125
2126
0
    if (opt_next) {
2127
0
      optary[opt_next - 1].next = optary + opt_next;
2128
0
    } else {
2129
0
      opt = optary;
2130
0
    }
2131
0
    ++opt_next;
2132
0
  }
2133
2134
0
  vnc_zlog_debug_verbose(
2135
0
    "%s: vn=%s, un=%s, prefix=%s, cost=%s, lifetime=%s, lnh=%s",
2136
0
    __func__, arg_vn, arg_un, arg_prefix,
2137
0
    (arg_cost ? arg_cost : "NULL"),
2138
0
    (arg_lifetime ? arg_lifetime : "NULL"),
2139
0
    (arg_lnh ? arg_lnh : "NULL"));
2140
2141
0
  rfapiQprefix2Rprefix(&pfx, &rpfx);
2142
2143
0
  rpfx.cost = cost & 255;
2144
2145
  /* look up rf descriptor, call open if it doesn't exist  */
2146
0
  rc = rfapi_find_rfd(bgp, &vn_address, &un_address,
2147
0
          (struct rfapi_descriptor **)&rfd);
2148
0
  if (rc) {
2149
0
    if (ENOENT == rc) {
2150
0
      struct rfapi_un_option uo;
2151
2152
      /*
2153
       * flag descriptor as provisionally opened for static
2154
       * route
2155
       * registration so that we can fix up the other
2156
       * parameters
2157
       * when the real open comes along
2158
       */
2159
0
      memset(&uo, 0, sizeof(uo));
2160
0
      uo.type = RFAPI_UN_OPTION_TYPE_PROVISIONAL;
2161
2162
0
      rc = rfapi_open(rfapi_get_rfp_start_val_by_bgp(bgp),
2163
0
          &vn_address, &un_address,
2164
0
          &uo,  /* flags */
2165
0
          NULL, NULL, /* no userdata */
2166
0
          &rfd);
2167
0
      if (rc) {
2168
0
        vty_out(vty,
2169
0
          "Can't open session for this NVE: %s\n",
2170
0
          rfapi_error_str(rc));
2171
0
        rc = CMD_WARNING_CONFIG_FAILED;
2172
0
        goto fail;
2173
0
      }
2174
0
    } else {
2175
0
      vty_out(vty, "Can't find session for this NVE: %s\n",
2176
0
        rfapi_error_str(rc));
2177
0
      goto fail;
2178
0
    }
2179
0
  }
2180
2181
0
  rc = rfapi_register(rfd, &rpfx, lifetime, NULL, opt,
2182
0
          RFAPI_REGISTER_ADD);
2183
0
  if (!rc) {
2184
0
    struct rfapi_next_hop_entry *head = NULL;
2185
0
    struct rfapi_next_hop_entry *tail = NULL;
2186
0
    struct rfapi_vn_option *vn_opt_new;
2187
2188
0
    vnc_zlog_debug_verbose(
2189
0
      "%s: rfapi_register succeeded, returning 0", __func__);
2190
2191
0
    if (h->rfp_methods.local_cb) {
2192
0
      struct rfapi_descriptor *r =
2193
0
        (struct rfapi_descriptor *)rfd;
2194
0
      vn_opt_new = rfapi_vn_options_dup(opt);
2195
2196
0
      rfapiAddDeleteLocalRfpPrefix(&r->un_addr, &r->vn_addr,
2197
0
                 &rpfx, 1, lifetime,
2198
0
                 vn_opt_new, &head, &tail);
2199
0
      if (head) {
2200
0
        h->flags |= RFAPI_INCALLBACK;
2201
0
        (*h->rfp_methods.local_cb)(head, r->cookie);
2202
0
        h->flags &= ~RFAPI_INCALLBACK;
2203
0
      }
2204
0
      head = tail = NULL;
2205
0
    }
2206
0
    return 0;
2207
0
  }
2208
2209
0
  vnc_zlog_debug_verbose("%s: rfapi_register failed", __func__);
2210
0
  vty_out(vty, "\n");
2211
0
  vty_out(vty, "Registration failed.\n");
2212
0
  vty_out(vty,
2213
0
    "Confirm that either the VN or UN address matches a configured NVE group.\n");
2214
0
  return CMD_WARNING_CONFIG_FAILED;
2215
2216
0
fail:
2217
0
  vnc_zlog_debug_verbose("%s: fail, rc=%d", __func__, rc);
2218
0
  return rc;
2219
0
}
2220
2221
/************************************************************************
2222
 *    Add prefix With LNH_OPTIONS...
2223
 ************************************************************************/
2224
DEFUN (add_vnc_prefix_cost_life_lnh,
2225
       add_vnc_prefix_cost_life_lnh_cmd,
2226
       "add vnc prefix <A.B.C.D/M|X:X::X:X/M> vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> cost (0-255) lifetime (1-4294967295) LNH_OPTIONS...",
2227
       "Add registration\n"
2228
       "VNC Information\n"
2229
       "Add/modify prefix related information\n"
2230
       "IPv4 prefix\n"
2231
       "IPv6 prefix\n"
2232
       "VN address of NVE\n"
2233
       "VN IPv4 interface address\n"
2234
       "VN IPv6 interface address\n"
2235
       "UN address of NVE\n"
2236
       "UN IPv4 interface address\n"
2237
       "UN IPv6 interface address\n"
2238
       "Administrative cost   [default: 255]\n"
2239
       "Administrative cost\n"
2240
       "Registration lifetime [default: infinite]\n"
2241
       "Lifetime value in seconds\n"
2242
       "[local-next-hop (A.B.C.D|X:X::X:X)] [local-cost <0-255>]\n")
2243
0
{
2244
  /*                       pfx      vn       un       cost     life */
2245
0
  return register_add(vty, argv[3], argv[5], argv[7], argv[9], argv[11],
2246
          /* mac vni */
2247
0
          NULL, NULL, argc - 12, argv + 12);
2248
0
}
2249
2250
DEFUN (add_vnc_prefix_life_cost_lnh,
2251
       add_vnc_prefix_life_cost_lnh_cmd,
2252
       "add vnc prefix <A.B.C.D/M|X:X::X:X/M> vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> lifetime (1-4294967295) cost (0-255) LNH_OPTIONS...",
2253
       "Add registration\n"
2254
       "VNC Information\n"
2255
       "Add/modify prefix related information\n"
2256
       "IPv4 prefix\n"
2257
       "IPv6 prefix\n"
2258
       "VN address of NVE\n"
2259
       "VN IPv4 interface address\n"
2260
       "VN IPv6 interface address\n"
2261
       "UN address of NVE\n"
2262
       "UN IPv4 interface address\n"
2263
       "UN IPv6 interface address\n"
2264
       "Registration lifetime [default: infinite]\n"
2265
       "Lifetime value in seconds\n"
2266
       "Administrative cost   [default: 255]\n"
2267
       "Administrative cost\n"
2268
       "[local-next-hop (A.B.C.D|X:X::X:X)] [local-cost <0-255>]\n")
2269
0
{
2270
  /*                       pfx      vn       un       cost     life */
2271
0
  return register_add(vty, argv[3], argv[5], argv[7], argv[11], argv[9],
2272
          /* mac vni */
2273
0
          NULL, NULL, argc - 12, argv + 12);
2274
0
}
2275
2276
DEFUN (add_vnc_prefix_cost_lnh,
2277
       add_vnc_prefix_cost_lnh_cmd,
2278
       "add vnc prefix <A.B.C.D/M|X:X::X:X/M> vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> cost (0-255) LNH_OPTIONS...",
2279
       "Add registration\n"
2280
       "VNC Information\n"
2281
       "Add/modify prefix related information\n"
2282
       "IPv4 prefix\n"
2283
       "IPv6 prefix\n"
2284
       "VN address of NVE\n"
2285
       "VN IPv4 interface address\n"
2286
       "VN IPv6 interface address\n"
2287
       "UN address of NVE\n"
2288
       "UN IPv4 interface address\n"
2289
       "UN IPv6 interface address\n"
2290
       "Administrative cost   [default: 255]\n"
2291
       "Administrative cost\n"
2292
       "[local-next-hop (A.B.C.D|X:X::X:X)] [local-cost <0-255>]\n")
2293
0
{
2294
  /*                       pfx      vn       un       cost     life */
2295
0
  return register_add(vty, argv[3], argv[5], argv[7], argv[9], NULL,
2296
          /* mac vni */
2297
0
          NULL, NULL, argc - 10, argv + 10);
2298
0
}
2299
2300
DEFUN (add_vnc_prefix_life_lnh,
2301
       add_vnc_prefix_life_lnh_cmd,
2302
       "add vnc prefix <A.B.C.D/M|X:X::X:X/M> vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> lifetime (1-4294967295) LNH_OPTIONS...",
2303
       "Add registration\n"
2304
       "VNC Information\n"
2305
       "Add/modify prefix related information\n"
2306
       "IPv4 prefix\n"
2307
       "IPv6 prefix\n"
2308
       "VN address of NVE\n"
2309
       "VN IPv4 interface address\n"
2310
       "VN IPv6 interface address\n"
2311
       "UN address of NVE\n"
2312
       "UN IPv4 interface address\n"
2313
       "UN IPv6 interface address\n"
2314
       "Registration lifetime [default: infinite]\n"
2315
       "Lifetime value in seconds\n"
2316
       "[local-next-hop (A.B.C.D|X:X::X:X)] [local-cost <0-255>]\n")
2317
0
{
2318
  /*                       pfx      vn       un       cost     life */
2319
0
  return register_add(vty, argv[3], argv[5], argv[7], NULL, argv[9],
2320
          /* mac vni */
2321
0
          NULL, NULL, argc - 10, argv + 10);
2322
0
}
2323
2324
DEFUN (add_vnc_prefix_lnh,
2325
       add_vnc_prefix_lnh_cmd,
2326
       "add vnc prefix <A.B.C.D/M|X:X::X:X/M> vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> LNH_OPTIONS...",
2327
       "Add registration\n"
2328
       "VNC Information\n"
2329
       "Add/modify prefix related information\n"
2330
       "IPv4 prefix\n"
2331
       "IPv6 prefix\n"
2332
       "VN address of NVE\n"
2333
       "VN IPv4 interface address\n"
2334
       "VN IPv6 interface address\n"
2335
       "UN address of NVE\n"
2336
       "UN IPv4 interface address\n"
2337
       "UN IPv6 interface address\n"
2338
       "[local-next-hop (A.B.C.D|X:X::X:X)] [local-cost <0-255>]\n")
2339
0
{
2340
  /*                       pfx      vn       un       cost     life */
2341
0
  return register_add(vty, argv[3], argv[5], argv[7], NULL, NULL,
2342
          /* mac vni */
2343
0
          NULL, NULL, argc - 8, argv + 8);
2344
0
}
2345
2346
/************************************************************************
2347
 *    Add prefix Without LNH_OPTIONS...
2348
 ************************************************************************/
2349
DEFUN (add_vnc_prefix_cost_life,
2350
       add_vnc_prefix_cost_life_cmd,
2351
       "add vnc prefix <A.B.C.D/M|X:X::X:X/M> vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> cost (0-255) lifetime (1-4294967295)",
2352
       "Add registration\n"
2353
       "VNC Information\n"
2354
       "Add/modify prefix related information\n"
2355
       "IPv4 prefix\n"
2356
       "IPv6 prefix\n"
2357
       "VN address of NVE\n"
2358
       "VN IPv4 interface address\n"
2359
       "VN IPv6 interface address\n"
2360
       "UN address of NVE\n"
2361
       "UN IPv4 interface address\n"
2362
       "UN IPv6 interface address\n"
2363
       "Administrative cost   [default: 255]\n"
2364
       "Administrative cost\n"
2365
       "Registration lifetime [default: infinite]\n"
2366
       "Lifetime value in seconds\n")
2367
0
{
2368
  /*                       pfx      vn       un       cost     life */
2369
0
  return register_add(vty, argv[3], argv[5], argv[7], argv[9], argv[11],
2370
          /* mac vni */
2371
0
          NULL, NULL, 0, NULL);
2372
0
}
2373
2374
DEFUN (add_vnc_prefix_life_cost,
2375
       add_vnc_prefix_life_cost_cmd,
2376
       "add vnc prefix <A.B.C.D/M|X:X::X:X/M> vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> lifetime (1-4294967295) cost (0-255)",
2377
       "Add registration\n"
2378
       "VNC Information\n"
2379
       "Add/modify prefix related information\n"
2380
       "IPv4 prefix\n"
2381
       "IPv6 prefix\n"
2382
       "VN address of NVE\n"
2383
       "VN IPv4 interface address\n"
2384
       "VN IPv6 interface address\n"
2385
       "UN address of NVE\n"
2386
       "UN IPv4 interface address\n"
2387
       "UN IPv6 interface address\n"
2388
       "Registration lifetime [default: infinite]\n"
2389
       "Lifetime value in seconds\n"
2390
       "Administrative cost   [default: 255]\n"
2391
       "Administrative cost\n")
2392
0
{
2393
  /*                       pfx      vn       un       cost     life */
2394
0
  return register_add(vty, argv[3], argv[5], argv[7], argv[11], argv[9],
2395
          /* mac vni */
2396
0
          NULL, NULL, 0, NULL);
2397
0
}
2398
2399
DEFUN (add_vnc_prefix_cost,
2400
       add_vnc_prefix_cost_cmd,
2401
       "add vnc prefix <A.B.C.D/M|X:X::X:X/M> vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> cost (0-255)",
2402
       "Add registration\n"
2403
       "VNC Information\n"
2404
       "Add/modify prefix related information\n"
2405
       "IPv4 prefix\n"
2406
       "IPv6 prefix\n"
2407
       "VN address of NVE\n"
2408
       "VN IPv4 interface address\n"
2409
       "VN IPv6 interface address\n"
2410
       "UN address of NVE\n"
2411
       "UN IPv4 interface address\n"
2412
       "UN IPv6 interface address\n"
2413
       "Administrative cost   [default: 255]\n"
2414
       "Administrative cost\n")
2415
0
{
2416
  /*                       pfx      vn       un       cost     life */
2417
0
  return register_add(vty, argv[3], argv[5], argv[7], argv[9], NULL,
2418
          /* mac vni */
2419
0
          NULL, NULL, 0, NULL);
2420
0
}
2421
2422
DEFUN (add_vnc_prefix_life,
2423
       add_vnc_prefix_life_cmd,
2424
       "add vnc prefix <A.B.C.D/M|X:X::X:X/M> vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> lifetime (1-4294967295)",
2425
       "Add registration\n"
2426
       "VNC Information\n"
2427
       "Add/modify prefix related information\n"
2428
       "IPv4 prefix\n"
2429
       "IPv6 prefix\n"
2430
       "VN address of NVE\n"
2431
       "VN IPv4 interface address\n"
2432
       "VN IPv6 interface address\n"
2433
       "UN address of NVE\n"
2434
       "UN IPv4 interface address\n"
2435
       "UN IPv6 interface address\n"
2436
       "Registration lifetime [default: infinite]\n"
2437
       "Lifetime value in seconds\n")
2438
0
{
2439
  /*                       pfx      vn       un       cost     life */
2440
0
  return register_add(vty, argv[3], argv[5], argv[7], NULL, argv[9],
2441
          /* mac vni */
2442
0
          NULL, NULL, 0, NULL);
2443
0
}
2444
2445
DEFUN (add_vnc_prefix,
2446
       add_vnc_prefix_cmd,
2447
       "add vnc prefix <A.B.C.D/M|X:X::X:X/M> vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X>",
2448
       "Add registration\n"
2449
       "VNC Information\n"
2450
       "Add/modify prefix related information\n"
2451
       "IPv4 prefix\n"
2452
       "IPv6 prefix\n"
2453
       "VN address of NVE\n"
2454
       "VN IPv4 interface address\n"
2455
       "VN IPv6 interface address\n"
2456
       "UN address of NVE\n"
2457
       "UN IPv4 interface address\n"
2458
       "UN IPv6 interface address\n")
2459
0
{
2460
  /*                       pfx      vn       un       cost     life */
2461
0
  return register_add(vty, argv[3], argv[5], argv[7], NULL, NULL,
2462
          /* mac vni */
2463
0
          NULL, NULL, 0, NULL);
2464
0
}
2465
2466
/************************************************************************
2467
 *      Mac address registrations
2468
 ************************************************************************/
2469
DEFUN (add_vnc_mac_vni_prefix_cost_life,
2470
       add_vnc_mac_vni_prefix_cost_life_cmd,
2471
       "add vnc mac X:X:X:X:X:X virtual-network-identifier (1-4294967295) vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> prefix <A.B.C.D/M|X:X::X:X/M> cost (0-255) lifetime (1-4294967295)",
2472
       "Add registration\n"
2473
       "VNC Information\n"
2474
       "Add/modify mac address information\n"
2475
       "MAC address\n"
2476
       "Virtual Network Identifier follows\n"
2477
       "Virtual Network Identifier\n"
2478
       "VN address of NVE\n"
2479
       "VN IPv4 interface address\n"
2480
       "VN IPv6 interface address\n"
2481
       "UN address of NVE\n"
2482
       "UN IPv4 interface address\n"
2483
       "UN IPv6 interface address\n"
2484
       "Add/modify prefix related information\n"
2485
       "IPv4 prefix\n"
2486
       "IPv6 prefix\n"
2487
       "Administrative cost   [default: 255]\n"
2488
       "Administrative cost\n"
2489
       "Registration lifetime [default: infinite]\n"
2490
       "Lifetime value in seconds\n")
2491
0
{
2492
  /*                       pfx      vn       un       cost     life */
2493
0
  return register_add(vty, argv[11], argv[7], argv[9], argv[13], argv[15],
2494
          /* mac vni */
2495
0
          argv[3], argv[5], 0, NULL);
2496
0
}
2497
2498
2499
DEFUN (add_vnc_mac_vni_prefix_life,
2500
       add_vnc_mac_vni_prefix_life_cmd,
2501
       "add vnc mac X:X:X:X:X:X virtual-network-identifier (1-4294967295) vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> prefix <A.B.C.D/M|X:X::X:X/M> lifetime (1-4294967295)",
2502
       "Add registration\n"
2503
       "VNC Information\n"
2504
       "Add/modify mac address information\n"
2505
       "MAC address\n"
2506
       "Virtual Network Identifier follows\n"
2507
       "Virtual Network Identifier\n"
2508
       "VN address of NVE\n"
2509
       "VN IPv4 interface address\n"
2510
       "VN IPv6 interface address\n"
2511
       "UN address of NVE\n"
2512
       "UN IPv4 interface address\n"
2513
       "UN IPv6 interface address\n"
2514
       "Add/modify prefix related information\n"
2515
       "IPv4 prefix\n"
2516
       "IPv6 prefix\n"
2517
       "Registration lifetime [default: infinite]\n"
2518
       "Lifetime value in seconds\n")
2519
0
{
2520
  /*                       pfx      vn       un       cost     life */
2521
0
  return register_add(vty, argv[11], argv[7], argv[9], NULL, argv[13],
2522
          /* mac vni */
2523
0
          argv[3], argv[5], 0, NULL);
2524
0
}
2525
2526
DEFUN (add_vnc_mac_vni_prefix_cost,
2527
       add_vnc_mac_vni_prefix_cost_cmd,
2528
       "add vnc mac X:X:X:X:X:X virtual-network-identifier (1-4294967295) vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> prefix <A.B.C.D/M|X:X::X:X/M> cost (0-255)",
2529
       "Add registration\n"
2530
       "VNC Information\n"
2531
       "Add/modify mac address information\n"
2532
       "MAC address\n"
2533
       "Virtual Network Identifier follows\n"
2534
       "Virtual Network Identifier\n"
2535
       "VN address of NVE\n"
2536
       "VN IPv4 interface address\n"
2537
       "VN IPv6 interface address\n"
2538
       "UN address of NVE\n"
2539
       "UN IPv4 interface address\n"
2540
       "UN IPv6 interface address\n"
2541
       "Add/modify prefix related information\n"
2542
       "IPv4 prefix\n"
2543
       "IPv6 prefix\n"
2544
       "Administrative cost   [default: 255]\n" "Administrative cost\n")
2545
0
{
2546
  /*                       pfx      vn       un       cost     life */
2547
0
  return register_add(vty, argv[11], argv[7], argv[9], argv[13], NULL,
2548
          /* mac vni */
2549
0
          argv[3], argv[5], 0, NULL);
2550
0
}
2551
2552
DEFUN (add_vnc_mac_vni_prefix,
2553
       add_vnc_mac_vni_prefix_cmd,
2554
       "add vnc mac X:X:X:X:X:X virtual-network-identifier (1-4294967295) vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> prefix <A.B.C.D/M|X:X::X:X/M>",
2555
       "Add registration\n"
2556
       "VNC Information\n"
2557
       "Add/modify mac address information\n"
2558
       "MAC address\n"
2559
       "Virtual Network Identifier follows\n"
2560
       "Virtual Network Identifier\n"
2561
       "VN address of NVE\n"
2562
       "VN IPv4 interface address\n"
2563
       "VN IPv6 interface address\n"
2564
       "UN address of NVE\n"
2565
       "UN IPv4 interface address\n"
2566
       "UN IPv6 interface address\n"
2567
       "Add/modify prefix related information\n"
2568
       "IPv4 prefix\n" "IPv6 prefix\n")
2569
0
{
2570
  /*                       pfx      vn       un       cost     life */
2571
0
  return register_add(vty, argv[11], argv[7], argv[9], NULL, NULL,
2572
          /* mac vni */
2573
0
          argv[3], argv[5], 0, NULL);
2574
0
}
2575
2576
DEFUN (add_vnc_mac_vni_cost_life,
2577
       add_vnc_mac_vni_cost_life_cmd,
2578
       "add vnc mac X:X:X:X:X:X virtual-network-identifier (1-4294967295) vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> cost (0-255) lifetime (1-4294967295)",
2579
       "Add registration\n"
2580
       "VNC Information\n"
2581
       "Add/modify mac address information\n"
2582
       "MAC address\n"
2583
       "Virtual Network Identifier follows\n"
2584
       "Virtual Network Identifier\n"
2585
       "VN address of NVE\n"
2586
       "VN IPv4 interface address\n"
2587
       "VN IPv6 interface address\n"
2588
       "UN address of NVE\n"
2589
       "UN IPv4 interface address\n"
2590
       "UN IPv6 interface address\n"
2591
       "Administrative cost   [default: 255]\n"
2592
       "Administrative cost\n"
2593
       "Registration lifetime [default: infinite]\n"
2594
       "Lifetime value in seconds\n")
2595
0
{
2596
  /*                       pfx      vn       un       cost     life */
2597
0
  return register_add(vty, NULL, argv[7], argv[9], argv[11], argv[13],
2598
          /* mac vni */
2599
0
          argv[3], argv[5], 0, NULL);
2600
0
}
2601
2602
2603
DEFUN (add_vnc_mac_vni_cost,
2604
       add_vnc_mac_vni_cost_cmd,
2605
       "add vnc mac X:X:X:X:X:X virtual-network-identifier (1-4294967295) vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> cost (0-255)",
2606
       "Add registration\n"
2607
       "VNC Information\n"
2608
       "Add/modify mac address information\n"
2609
       "MAC address\n"
2610
       "Virtual Network Identifier follows\n"
2611
       "Virtual Network Identifier\n"
2612
       "VN address of NVE\n"
2613
       "VN IPv4 interface address\n"
2614
       "VN IPv6 interface address\n"
2615
       "UN address of NVE\n"
2616
       "UN IPv4 interface address\n"
2617
       "UN IPv6 interface address\n"
2618
       "Administrative cost   [default: 255]\n" "Administrative cost\n")
2619
0
{
2620
  /*                       pfx      vn       un    cost     life */
2621
0
  return register_add(vty, NULL, argv[7], argv[9], argv[11], NULL,
2622
          /* mac vni */
2623
0
          argv[3], argv[5], 0, NULL);
2624
0
}
2625
2626
2627
DEFUN (add_vnc_mac_vni_life,
2628
       add_vnc_mac_vni_life_cmd,
2629
       "add vnc mac X:X:X:X:X:X virtual-network-identifier (1-4294967295) vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> lifetime (1-4294967295)",
2630
       "Add registration\n"
2631
       "VNC Information\n"
2632
       "Add/modify mac address information\n"
2633
       "MAC address\n"
2634
       "Virtual Network Identifier follows\n"
2635
       "Virtual Network Identifier\n"
2636
       "VN address of NVE\n"
2637
       "VN IPv4 interface address\n"
2638
       "VN IPv6 interface address\n"
2639
       "UN address of NVE\n"
2640
       "UN IPv4 interface address\n"
2641
       "UN IPv6 interface address\n"
2642
       "Registration lifetime [default: infinite]\n"
2643
       "Lifetime value in seconds\n")
2644
0
{
2645
  /*                       pfx      vn       un    cost  life */
2646
0
  return register_add(vty, NULL, argv[7], argv[9], NULL, argv[11],
2647
          /* mac vni */
2648
0
          argv[3], argv[5], 0, NULL);
2649
0
}
2650
2651
2652
DEFUN (add_vnc_mac_vni,
2653
       add_vnc_mac_vni_cmd,
2654
       "add vnc mac X:X:X:X:X:X virtual-network-identifier (1-4294967295) vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X>",
2655
       "Add registration\n"
2656
       "VNC Information\n"
2657
       "Add/modify mac address information\n"
2658
       "MAC address\n"
2659
       "Virtual Network Identifier follows\n"
2660
       "Virtual Network Identifier\n"
2661
       "VN address of NVE\n"
2662
       "VN IPv4 interface address\n"
2663
       "VN IPv6 interface address\n"
2664
       "UN address of NVE\n"
2665
       "UN IPv4 interface address\n" "UN IPv6 interface address\n")
2666
0
{
2667
  /*                       pfx      vn       un    cost  life */
2668
0
  return register_add(vty, NULL, argv[7], argv[9], NULL, NULL,
2669
          /* mac vni */
2670
0
          argv[3], argv[5], 0, NULL);
2671
0
}
2672
2673
/************************************************************************
2674
 *      Delete prefix
2675
 ************************************************************************/
2676
2677
struct rfapi_local_reg_delete_arg {
2678
  /*
2679
   * match parameters
2680
   */
2681
  struct bgp *bgp;
2682
  struct rfapi_ip_addr un_address; /* AF==0: wildcard */
2683
  struct rfapi_ip_addr vn_address; /* AF==0: wildcard */
2684
  struct prefix prefix;    /* AF==0: wildcard */
2685
  struct prefix_rd rd;     /* plen!=64: wildcard */
2686
  struct rfapi_nve_group_cfg *rfg; /* NULL: wildcard */
2687
2688
  struct rfapi_l2address_option_match l2o;
2689
2690
  /*
2691
   * result parameters
2692
   */
2693
  struct vty *vty;
2694
  uint32_t reg_count;
2695
  uint32_t pfx_count;
2696
  uint32_t query_count;
2697
2698
  uint32_t failed_pfx_count;
2699
2700
  uint32_t nve_count;
2701
  struct skiplist *nves;
2702
2703
  uint32_t remote_active_nve_count;
2704
  uint32_t remote_active_pfx_count;
2705
  uint32_t remote_holddown_nve_count;
2706
  uint32_t remote_holddown_pfx_count;
2707
};
2708
2709
struct nve_addr {
2710
  struct rfapi_ip_addr vn;
2711
  struct rfapi_ip_addr un;
2712
  struct rfapi_descriptor *rfd;
2713
  struct rfapi_local_reg_delete_arg *cda;
2714
};
2715
2716
static void nve_addr_free(void *hap)
2717
0
{
2718
0
  ((struct nve_addr *)hap)->cda->nve_count += 1;
2719
0
  XFREE(MTYPE_RFAPI_NVE_ADDR, hap);
2720
0
}
2721
2722
static int nve_addr_cmp(const void *k1, const void *k2)
2723
0
{
2724
0
  const struct nve_addr *a = (struct nve_addr *)k1;
2725
0
  const struct nve_addr *b = (struct nve_addr *)k2;
2726
0
  int ret = 0;
2727
2728
0
  if (!a || !b) {
2729
0
    return (a - b);
2730
0
  }
2731
0
  if (a->un.addr_family != b->un.addr_family) {
2732
0
    return (a->un.addr_family - b->un.addr_family);
2733
0
  }
2734
0
  if (a->vn.addr_family != b->vn.addr_family) {
2735
0
    return (a->vn.addr_family - b->vn.addr_family);
2736
0
  }
2737
0
  if (a->un.addr_family == AF_INET) {
2738
0
    ret = IPV4_ADDR_CMP(&a->un.addr.v4, &b->un.addr.v4);
2739
0
    if (ret != 0) {
2740
0
      return ret;
2741
0
    }
2742
0
  } else if (a->un.addr_family == AF_INET6) {
2743
0
    ret = IPV6_ADDR_CMP(&a->un.addr.v6, &b->un.addr.v6);
2744
0
    if (ret != 0) {
2745
0
      return ret;
2746
0
    }
2747
0
  } else {
2748
0
    assert(0);
2749
0
  }
2750
0
  if (a->vn.addr_family == AF_INET) {
2751
0
    ret = IPV4_ADDR_CMP(&a->vn.addr.v4, &b->vn.addr.v4);
2752
0
    if (ret != 0)
2753
0
      return ret;
2754
0
  } else if (a->vn.addr_family == AF_INET6) {
2755
0
    ret = IPV6_ADDR_CMP(&a->vn.addr.v6, &b->vn.addr.v6);
2756
0
    if (ret == 0) {
2757
0
      return ret;
2758
0
    }
2759
0
  } else {
2760
0
    assert(0);
2761
0
  }
2762
0
  return 0;
2763
0
}
2764
2765
static int parse_deleter_args(struct vty *vty, struct bgp *bgp,
2766
            const char *arg_prefix, const char *arg_vn,
2767
            const char *arg_un, const char *arg_l2addr,
2768
            const char *arg_vni, const char *arg_rd,
2769
            struct rfapi_nve_group_cfg *arg_rfg,
2770
            struct rfapi_local_reg_delete_arg *rcdarg)
2771
0
{
2772
0
  int rc = CMD_WARNING;
2773
2774
0
  memset(rcdarg, 0, sizeof(struct rfapi_local_reg_delete_arg));
2775
2776
0
  rcdarg->vty = vty;
2777
0
  if (bgp == NULL)
2778
0
    bgp = bgp_get_default();
2779
0
  rcdarg->bgp = bgp;
2780
0
  rcdarg->rfg = arg_rfg; /* may be NULL */
2781
2782
0
  if (arg_vn && strcmp(arg_vn, "*")) {
2783
0
    if ((rc = rfapiCliGetRfapiIpAddr(vty, arg_vn,
2784
0
             &rcdarg->vn_address)))
2785
0
      return rc;
2786
0
  }
2787
0
  if (arg_un && strcmp(arg_un, "*")) {
2788
0
    if ((rc = rfapiCliGetRfapiIpAddr(vty, arg_un,
2789
0
             &rcdarg->un_address)))
2790
0
      return rc;
2791
0
  }
2792
0
  if (arg_prefix && strcmp(arg_prefix, "*")) {
2793
2794
0
    if (!str2prefix(arg_prefix, &rcdarg->prefix)) {
2795
0
      vty_out(vty, "Malformed prefix \"%s\"\n", arg_prefix);
2796
0
      return rc;
2797
0
    }
2798
0
  }
2799
2800
0
  if (arg_l2addr) {
2801
0
    if (!arg_vni) {
2802
0
      vty_out(vty, "Missing VNI\n");
2803
0
      return rc;
2804
0
    }
2805
0
    if (strcmp(arg_l2addr, "*")) {
2806
0
      if ((rc = rfapiStr2EthAddr(arg_l2addr,
2807
0
               &rcdarg->l2o.o.macaddr))) {
2808
0
        vty_out(vty, "Malformed L2 Address \"%s\"\n",
2809
0
          arg_l2addr);
2810
0
        return rc;
2811
0
      }
2812
0
      rcdarg->l2o.flags |= RFAPI_L2O_MACADDR;
2813
0
    }
2814
0
    if (strcmp(arg_vni, "*")) {
2815
0
      rcdarg->l2o.o.logical_net_id =
2816
0
        strtoul(arg_vni, NULL, 10);
2817
0
      rcdarg->l2o.flags |= RFAPI_L2O_LNI;
2818
0
    }
2819
0
  }
2820
0
  if (arg_rd) {
2821
0
    if (!str2prefix_rd(arg_rd, &rcdarg->rd)) {
2822
0
      vty_out(vty, "Malformed RD \"%s\"\n", arg_rd);
2823
0
      return rc;
2824
0
    }
2825
0
  }
2826
2827
0
  return CMD_SUCCESS;
2828
0
}
2829
2830
static int
2831
parse_deleter_tokens(struct vty *vty, struct bgp *bgp,
2832
         struct cmd_token *carg_prefix, struct cmd_token *carg_vn,
2833
         struct cmd_token *carg_un, struct cmd_token *carg_l2addr,
2834
         struct cmd_token *carg_vni, struct cmd_token *carg_rd,
2835
         struct rfapi_nve_group_cfg *arg_rfg,
2836
         struct rfapi_local_reg_delete_arg *rcdarg)
2837
0
{
2838
0
  const char *arg_prefix = carg_prefix ? carg_prefix->arg : NULL;
2839
0
  const char *arg_vn = carg_vn ? carg_vn->arg : NULL;
2840
0
  const char *arg_un = carg_un ? carg_un->arg : NULL;
2841
0
  const char *arg_l2addr = carg_l2addr ? carg_l2addr->arg : NULL;
2842
0
  const char *arg_vni = carg_vni ? carg_vni->arg : NULL;
2843
0
  const char *arg_rd = carg_rd ? carg_rd->arg : NULL;
2844
0
  return parse_deleter_args(vty, bgp, arg_prefix, arg_vn, arg_un,
2845
0
          arg_l2addr, arg_vni, arg_rd, arg_rfg, rcdarg);
2846
0
}
2847
2848
static void record_nve_in_cda_list(struct rfapi_local_reg_delete_arg *cda,
2849
           struct rfapi_ip_addr *un_address,
2850
           struct rfapi_ip_addr *vn_address,
2851
           struct rfapi_descriptor *rfd)
2852
0
{
2853
0
  struct nve_addr ha;
2854
0
  struct nve_addr *hap;
2855
2856
0
  memset(&ha, 0, sizeof(ha));
2857
0
  ha.un = *un_address;
2858
0
  ha.vn = *vn_address;
2859
0
  ha.rfd = rfd;
2860
2861
0
  if (!cda->nves)
2862
0
    cda->nves = skiplist_new(0, nve_addr_cmp, nve_addr_free);
2863
2864
0
  if (skiplist_search(cda->nves, &ha, (void *)&hap)) {
2865
0
    hap = XCALLOC(MTYPE_RFAPI_NVE_ADDR, sizeof(struct nve_addr));
2866
0
    assert(hap);
2867
0
    ha.cda = cda;
2868
0
    *hap = ha;
2869
0
    skiplist_insert(cda->nves, hap, hap);
2870
0
  }
2871
0
}
2872
2873
static void clear_vnc_responses(struct rfapi_local_reg_delete_arg *cda)
2874
0
{
2875
0
  struct rfapi *h;
2876
0
  struct rfapi_descriptor *rfd;
2877
0
  int query_count = 0;
2878
0
  struct listnode *node;
2879
0
  struct bgp *bgp_default = bgp_get_default();
2880
2881
0
  if (cda->vn_address.addr_family && cda->un_address.addr_family) {
2882
    /*
2883
     * Single nve case
2884
     */
2885
0
    if (rfapi_find_rfd(bgp_default, &cda->vn_address,
2886
0
           &cda->un_address, &rfd))
2887
0
      return;
2888
2889
0
    rfapiRibClear(rfd);
2890
0
    rfapi_query_done_all(rfd, &query_count);
2891
0
    cda->query_count += query_count;
2892
2893
    /*
2894
     * Track unique nves seen
2895
     */
2896
0
    record_nve_in_cda_list(cda, &rfd->un_addr, &rfd->vn_addr, rfd);
2897
0
    return;
2898
0
  }
2899
2900
  /*
2901
   * wildcard case
2902
   */
2903
2904
0
  if (!bgp_default)
2905
0
    return; /* ENXIO */
2906
2907
0
  h = bgp_default->rfapi;
2908
2909
0
  if (!h)
2910
0
    return; /* ENXIO */
2911
2912
0
  for (ALL_LIST_ELEMENTS_RO(&h->descriptors, node, rfd)) {
2913
    /*
2914
     * match un, vn addresses of NVEs
2915
     */
2916
0
    if (cda->un_address.addr_family
2917
0
        && rfapi_ip_addr_cmp(&cda->un_address, &rfd->un_addr)) {
2918
0
      continue;
2919
0
    }
2920
0
    if (cda->vn_address.addr_family
2921
0
        && rfapi_ip_addr_cmp(&cda->vn_address, &rfd->vn_addr)) {
2922
0
      continue;
2923
0
    }
2924
2925
0
    rfapiRibClear(rfd);
2926
2927
0
    rfapi_query_done_all(rfd, &query_count);
2928
0
    cda->query_count += query_count;
2929
2930
    /*
2931
     * Track unique nves seen
2932
     */
2933
0
    record_nve_in_cda_list(cda, &rfd->un_addr, &rfd->vn_addr, rfd);
2934
0
  }
2935
0
}
2936
2937
/*
2938
 * TBD need to count deleted prefixes and nves?
2939
 *
2940
 * ENXIO  BGP or VNC not configured
2941
 */
2942
static int rfapiDeleteLocalPrefixesByRFD(struct rfapi_local_reg_delete_arg *cda,
2943
           struct rfapi_descriptor *rfd)
2944
0
{
2945
0
  struct rfapi_ip_addr *pUn; /* NULL = wildcard */
2946
0
  struct rfapi_ip_addr *pVn; /* NULL = wildcard */
2947
0
  struct prefix *pPrefix;    /* NULL = wildcard */
2948
0
  struct prefix_rd *pPrd;    /* NULL = wildcard */
2949
2950
0
  struct rfapi_ip_prefix rprefix;
2951
0
  struct rfapi_next_hop_entry *head = NULL;
2952
0
  struct rfapi_next_hop_entry *tail = NULL;
2953
2954
#if DEBUG_L2_EXTRA
2955
  vnc_zlog_debug_verbose("%s: entry", __func__);
2956
#endif
2957
2958
0
  pUn = (cda->un_address.addr_family ? &cda->un_address : NULL);
2959
0
  pVn = (cda->vn_address.addr_family ? &cda->vn_address : NULL);
2960
0
  pPrefix = (cda->prefix.family ? &cda->prefix : NULL);
2961
0
  pPrd = (cda->rd.prefixlen == 64 ? &cda->rd : NULL);
2962
2963
0
  if (pPrefix) {
2964
0
    rfapiQprefix2Rprefix(pPrefix, &rprefix);
2965
0
  }
2966
2967
0
  do /* to preserve old code structure */
2968
0
  {
2969
0
    struct rfapi *h = cda->bgp->rfapi;
2970
0
    ;
2971
0
    struct rfapi_adb *adb;
2972
0
    int rc;
2973
0
    int deleted_from_this_nve;
2974
0
    struct nve_addr ha;
2975
0
    struct nve_addr *hap;
2976
2977
#if DEBUG_L2_EXTRA
2978
    vnc_zlog_debug_verbose("%s: rfd=%p", __func__, rfd);
2979
#endif
2980
2981
    /*
2982
     * match un, vn addresses of NVEs
2983
     */
2984
0
    if (pUn && (rfapi_ip_addr_cmp(pUn, &rfd->un_addr)))
2985
0
      break;
2986
0
    if (pVn && (rfapi_ip_addr_cmp(pVn, &rfd->vn_addr)))
2987
0
      break;
2988
2989
#if DEBUG_L2_EXTRA
2990
    vnc_zlog_debug_verbose("%s: un, vn match", __func__);
2991
#endif
2992
2993
    /*
2994
     * match prefix
2995
     */
2996
2997
0
    deleted_from_this_nve = 0;
2998
2999
0
    {
3000
0
      struct skiplist *sl;
3001
0
      struct rfapi_ip_prefix rp;
3002
0
      void *cursor;
3003
0
      struct list *adb_delete_list;
3004
3005
      /*
3006
       * The advertisements are stored in a skiplist.
3007
       * Withdrawing
3008
       * the registration deletes the advertisement from the
3009
       * skiplist, which we can't do while iterating over that
3010
       * same skiplist using the current skiplist API.
3011
       *
3012
       * Strategy: iterate over the skiplist and build another
3013
       * list containing only the matching ADBs. Then delete
3014
       * _everything_ in that second list (which can be done
3015
       * using either skiplists or quagga linklists).
3016
       */
3017
0
      adb_delete_list = list_new();
3018
3019
      /*
3020
       * Advertised IP prefixes (not 0/32 or 0/128)
3021
       */
3022
0
      sl = rfd->advertised.ipN_by_prefix;
3023
3024
0
      for (cursor = NULL,
3025
0
          rc = skiplist_next(sl, NULL, (void **)&adb,
3026
0
                 &cursor);
3027
0
           !rc; rc = skiplist_next(sl, NULL, (void **)&adb,
3028
0
                 &cursor)) {
3029
3030
0
        if (pPrefix) {
3031
0
          if (!prefix_same(pPrefix,
3032
0
               &adb->u.s.prefix_ip)) {
3033
#if DEBUG_L2_EXTRA
3034
            vnc_zlog_debug_verbose(
3035
              "%s: adb=%p, prefix doesn't match, skipping",
3036
              __func__, adb);
3037
#endif
3038
0
            continue;
3039
0
          }
3040
0
        }
3041
0
        if (pPrd) {
3042
0
          if (memcmp(pPrd->val, adb->u.s.prd.val,
3043
0
               8)
3044
0
              != 0) {
3045
#if DEBUG_L2_EXTRA
3046
            vnc_zlog_debug_verbose(
3047
              "%s: adb=%p, RD doesn't match, skipping",
3048
              __func__, adb);
3049
#endif
3050
0
            continue;
3051
0
          }
3052
0
        }
3053
0
        if (CHECK_FLAG(cda->l2o.flags,
3054
0
                 RFAPI_L2O_MACADDR)) {
3055
0
          if (memcmp(cda->l2o.o.macaddr.octet,
3056
0
               adb->u.s.prefix_eth.u
3057
0
                 .prefix_eth.octet,
3058
0
               ETH_ALEN)) {
3059
#if DEBUG_L2_EXTRA
3060
            vnc_zlog_debug_verbose(
3061
              "%s: adb=%p, macaddr doesn't match, skipping",
3062
              __func__, adb);
3063
#endif
3064
0
            continue;
3065
0
          }
3066
0
        }
3067
3068
0
        if (CHECK_FLAG(cda->l2o.flags, RFAPI_L2O_LNI)) {
3069
0
          if (cda->l2o.o.logical_net_id
3070
0
              != adb->l2o.logical_net_id) {
3071
#if DEBUG_L2_EXTRA
3072
            vnc_zlog_debug_verbose(
3073
              "%s: adb=%p, LNI doesn't match, skipping",
3074
              __func__, adb);
3075
#endif
3076
0
            continue;
3077
0
          }
3078
0
        }
3079
3080
#if DEBUG_L2_EXTRA
3081
        vnc_zlog_debug_verbose(
3082
          "%s: ipN adding adb %p to delete list",
3083
          __func__, adb);
3084
#endif
3085
3086
0
        listnode_add(adb_delete_list, adb);
3087
0
      }
3088
3089
0
      struct listnode *node;
3090
3091
0
      for (ALL_LIST_ELEMENTS_RO(adb_delete_list, node, adb)) {
3092
0
        int this_advertisement_prefix_count;
3093
0
        struct rfapi_vn_option optary[3];
3094
0
        struct rfapi_vn_option *opt = NULL;
3095
0
        int cur_opt = 0;
3096
3097
0
        this_advertisement_prefix_count = 1;
3098
3099
0
        rfapiQprefix2Rprefix(&adb->u.s.prefix_ip, &rp);
3100
3101
0
        memset(optary, 0, sizeof(optary));
3102
3103
        /* if mac addr present in advert,  make l2o vn
3104
         * option */
3105
0
        if (adb->u.s.prefix_eth.family == AF_ETHERNET) {
3106
0
          if (opt != NULL)
3107
0
            opt->next = &optary[cur_opt];
3108
0
          opt = &optary[cur_opt++];
3109
0
          opt->type = RFAPI_VN_OPTION_TYPE_L2ADDR;
3110
0
          opt->v.l2addr.macaddr =
3111
0
            adb->u.s.prefix_eth.u
3112
0
              .prefix_eth;
3113
0
          ++this_advertisement_prefix_count;
3114
0
        }
3115
        /*
3116
         * use saved RD value instead of trying to
3117
         * invert
3118
         * complex RD computation in rfapi_register()
3119
         */
3120
0
        if (opt != NULL)
3121
0
          opt->next = &optary[cur_opt];
3122
0
        opt = &optary[cur_opt++];
3123
0
        opt->type = RFAPI_VN_OPTION_TYPE_INTERNAL_RD;
3124
0
        opt->v.internal_rd = adb->u.s.prd;
3125
3126
#if DEBUG_L2_EXTRA
3127
        vnc_zlog_debug_verbose(
3128
          "%s: ipN killing reg from adb %p ",
3129
          __func__, adb);
3130
#endif
3131
3132
0
        rc = rfapi_register(rfd, &rp, 0, NULL,
3133
0
                (cur_opt ? optary : NULL),
3134
0
                RFAPI_REGISTER_KILL);
3135
0
        if (!rc) {
3136
0
          cda->pfx_count +=
3137
0
            this_advertisement_prefix_count;
3138
0
          cda->reg_count += 1;
3139
0
          deleted_from_this_nve = 1;
3140
0
        }
3141
0
        if (h->rfp_methods.local_cb) {
3142
0
          rfapiAddDeleteLocalRfpPrefix(
3143
0
            &rfd->un_addr, &rfd->vn_addr,
3144
0
            &rp, 0, 0, NULL, &head, &tail);
3145
0
        }
3146
0
      }
3147
0
      list_delete_all_node(adb_delete_list);
3148
3149
0
      if (!(pPrefix && !RFAPI_0_PREFIX(pPrefix))) {
3150
        /*
3151
         * Caller didn't specify a prefix, or specified
3152
         * (0/32 or 0/128)
3153
         */
3154
3155
        /*
3156
         * Advertised 0/32 and 0/128 (indexed by
3157
         * ethernet address)
3158
         */
3159
0
        sl = rfd->advertised.ip0_by_ether;
3160
3161
0
        for (cursor = NULL,
3162
0
            rc = skiplist_next(sl, NULL, (void **)&adb,
3163
0
                   &cursor);
3164
0
             !rc;
3165
0
             rc = skiplist_next(sl, NULL, (void **)&adb,
3166
0
              &cursor)) {
3167
3168
0
          if (CHECK_FLAG(cda->l2o.flags,
3169
0
                   RFAPI_L2O_MACADDR)) {
3170
0
            if (memcmp(cda->l2o.o.macaddr
3171
0
                   .octet,
3172
0
                 adb->u.s.prefix_eth.u
3173
0
                   .prefix_eth
3174
0
                   .octet,
3175
0
                 ETH_ALEN)) {
3176
3177
0
              continue;
3178
0
            }
3179
0
          }
3180
0
          if (CHECK_FLAG(cda->l2o.flags,
3181
0
                   RFAPI_L2O_LNI)) {
3182
0
            if (cda->l2o.o.logical_net_id
3183
0
                != adb->l2o.logical_net_id) {
3184
0
              continue;
3185
0
            }
3186
0
          }
3187
#if DEBUG_L2_EXTRA
3188
          vnc_zlog_debug_verbose(
3189
            "%s: ip0 adding adb %p to delete list",
3190
            __func__, adb);
3191
#endif
3192
0
          listnode_add(adb_delete_list, adb);
3193
0
        }
3194
3195
3196
0
        for (ALL_LIST_ELEMENTS_RO(adb_delete_list, node,
3197
0
                adb)) {
3198
3199
0
          struct rfapi_vn_option vn;
3200
3201
0
          rfapiQprefix2Rprefix(
3202
0
            &adb->u.s.prefix_ip, &rp);
3203
3204
0
          memset(&vn, 0, sizeof(vn));
3205
0
          vn.type = RFAPI_VN_OPTION_TYPE_L2ADDR;
3206
0
          vn.v.l2addr = adb->l2o;
3207
3208
#if DEBUG_L2_EXTRA
3209
          vnc_zlog_debug_verbose(
3210
            "%s: ip0 killing reg from adb %p ",
3211
            __func__, adb);
3212
#endif
3213
3214
0
          rc = rfapi_register(
3215
0
            rfd, &rp, 0, NULL, &vn,
3216
0
            RFAPI_REGISTER_KILL);
3217
0
          if (!rc) {
3218
0
            cda->pfx_count += 1;
3219
0
            cda->reg_count += 1;
3220
0
            deleted_from_this_nve = 1;
3221
0
          }
3222
0
          if (h->rfp_methods.local_cb) {
3223
0
            struct rfapi_vn_option
3224
0
              *vn_opt_new;
3225
3226
0
            vn_opt_new =
3227
0
              rfapi_vn_options_dup(
3228
0
                &vn);
3229
0
            rfapiAddDeleteLocalRfpPrefix(
3230
0
              &rfd->un_addr,
3231
0
              &rfd->vn_addr, &rp, 0,
3232
0
              0, vn_opt_new, &head,
3233
0
              &tail);
3234
0
          }
3235
0
        }
3236
0
        list_delete_all_node(adb_delete_list);
3237
0
      }
3238
0
      list_delete(&adb_delete_list);
3239
0
    }
3240
3241
3242
0
    if (head) { /* should not be set if (NULL ==
3243
             rfapi_cfg->local_cb) */
3244
0
      h->flags |= RFAPI_INCALLBACK;
3245
0
      (*h->rfp_methods.local_cb)(head, rfd->cookie);
3246
0
      h->flags &= ~RFAPI_INCALLBACK;
3247
0
      head = tail = NULL;
3248
0
    }
3249
3250
0
    if (deleted_from_this_nve) {
3251
      /*
3252
       * track unique NVEs seen
3253
       */
3254
0
      memset(&ha, 0, sizeof(ha));
3255
0
      ha.un = rfd->un_addr;
3256
0
      ha.vn = rfd->vn_addr;
3257
3258
0
      if (!cda->nves)
3259
0
        cda->nves = skiplist_new(0, nve_addr_cmp,
3260
0
               nve_addr_free);
3261
0
      if (skiplist_search(cda->nves, &ha, (void **)&hap)) {
3262
0
        hap = XCALLOC(MTYPE_RFAPI_NVE_ADDR,
3263
0
                sizeof(struct nve_addr));
3264
0
        assert(hap);
3265
0
        ha.cda = cda;
3266
0
        *hap = ha;
3267
0
        skiplist_insert(cda->nves, hap, hap);
3268
0
      }
3269
0
    }
3270
0
  } while (0); /*  to preserve old code structure */
3271
3272
0
  return 0;
3273
0
}
3274
3275
static int rfapiDeleteLocalPrefixes(struct rfapi_local_reg_delete_arg *cda)
3276
0
{
3277
0
  int rc = 0;
3278
3279
0
  if (cda->rfg) {
3280
0
    if (cda->rfg->rfd) /* if not open, nothing to delete */
3281
0
      rc = rfapiDeleteLocalPrefixesByRFD(cda, cda->rfg->rfd);
3282
0
  } else {
3283
0
    struct bgp *bgp = cda->bgp;
3284
0
    struct rfapi *h;
3285
0
    struct rfapi_cfg *rfapi_cfg;
3286
3287
0
    struct listnode *node;
3288
0
    struct rfapi_descriptor *rfd;
3289
0
    if (!bgp)
3290
0
      return ENXIO;
3291
0
    h = bgp->rfapi;
3292
0
    rfapi_cfg = bgp->rfapi_cfg;
3293
0
    if (!h || !rfapi_cfg)
3294
0
      return ENXIO;
3295
0
    vnc_zlog_debug_verbose("%s: starting descriptor loop",
3296
0
               __func__);
3297
0
    for (ALL_LIST_ELEMENTS_RO(&h->descriptors, node, rfd)) {
3298
0
      rc = rfapiDeleteLocalPrefixesByRFD(cda, rfd);
3299
0
    }
3300
0
  }
3301
0
  return rc;
3302
0
}
3303
3304
/*
3305
 * clear_vnc_prefix
3306
 *
3307
 * Deletes local and remote prefixes that match
3308
 */
3309
static void clear_vnc_prefix(struct rfapi_local_reg_delete_arg *cda)
3310
0
{
3311
0
  struct prefix pfx_un;
3312
0
  struct prefix pfx_vn;
3313
3314
0
  struct prefix *pUN = NULL;
3315
0
  struct prefix *pVN = NULL;
3316
0
  struct prefix *pPrefix = NULL;
3317
3318
0
  struct rfapi_import_table *it = NULL;
3319
3320
  /*
3321
   * Delete matching remote prefixes in holddown
3322
   */
3323
0
  if (cda->vn_address.addr_family) {
3324
0
    if (!rfapiRaddr2Qprefix(&cda->vn_address, &pfx_vn))
3325
0
      pVN = &pfx_vn;
3326
0
  }
3327
0
  if (cda->un_address.addr_family) {
3328
0
    if (!rfapiRaddr2Qprefix(&cda->un_address, &pfx_un))
3329
0
      pUN = &pfx_un;
3330
0
  }
3331
0
  if (cda->prefix.family) {
3332
0
    pPrefix = &cda->prefix;
3333
0
  }
3334
0
  if (cda->rfg) {
3335
0
    it = cda->rfg->rfapi_import_table;
3336
0
  }
3337
0
  rfapiDeleteRemotePrefixes(
3338
0
    pUN, pVN, pPrefix, it, 0, 1, &cda->remote_active_pfx_count,
3339
0
    &cda->remote_active_nve_count, &cda->remote_holddown_pfx_count,
3340
0
    &cda->remote_holddown_nve_count);
3341
3342
  /*
3343
   * Now do local prefixes
3344
   */
3345
0
  rfapiDeleteLocalPrefixes(cda);
3346
0
}
3347
3348
static void print_cleared_stats(struct rfapi_local_reg_delete_arg *cda)
3349
0
{
3350
0
  struct vty *vty = cda->vty; /* for benefit of VTYNL */
3351
3352
  /* Our special element-deleting function counts nves */
3353
0
  if (cda->nves) {
3354
0
    skiplist_free(cda->nves);
3355
0
    cda->nves = NULL;
3356
0
  }
3357
0
  if (cda->failed_pfx_count)
3358
0
    vty_out(vty, "Failed to delete %d prefixes\n",
3359
0
      cda->failed_pfx_count);
3360
3361
  /* left as "prefixes" even in single case for ease of machine parsing */
3362
0
  vty_out(vty,
3363
0
    "[Local] Cleared %u registrations, %u prefixes, %u responses from %d NVEs\n",
3364
0
    cda->reg_count, cda->pfx_count, cda->query_count,
3365
0
    cda->nve_count);
3366
3367
  /*
3368
   * We don't currently allow deletion of active remote prefixes from
3369
   * the command line
3370
   */
3371
3372
0
  vty_out(vty, "[Holddown] Cleared %u prefixes from %u NVEs\n",
3373
0
    cda->remote_holddown_pfx_count, cda->remote_holddown_nve_count);
3374
0
}
3375
3376
/*
3377
 * Caller has already deleted registrations and queries for this/these
3378
 * NVEs. Now we just have to close their descriptors.
3379
 */
3380
static void clear_vnc_nve_closer(struct rfapi_local_reg_delete_arg *cda)
3381
0
{
3382
0
  struct skiplist *sl = cda->nves; /* contains affected NVEs */
3383
0
  struct nve_addr *pKey;
3384
0
  struct nve_addr *pValue;
3385
0
  void *cursor = NULL;
3386
0
  int rc;
3387
3388
0
  if (!sl)
3389
0
    return;
3390
3391
0
  for (rc = skiplist_next(sl, (void **)&pKey, (void **)&pValue, &cursor);
3392
0
       !rc; rc = skiplist_next(sl, (void **)&pKey, (void **)&pValue,
3393
0
             &cursor)) {
3394
3395
0
    if (pValue->rfd) {
3396
0
      pValue->rfd->flags |=
3397
0
        RFAPI_HD_FLAG_CLOSING_ADMINISTRATIVELY;
3398
0
      rfapi_close(pValue->rfd);
3399
0
    }
3400
0
  }
3401
0
}
3402
3403
DEFUN (clear_vnc_nve_all,
3404
       clear_vnc_nve_all_cmd,
3405
       "clear vnc nve *",
3406
       "clear\n"
3407
       "VNC Information\n"
3408
       "Clear per NVE information\n"
3409
       "For all NVEs\n")
3410
0
{
3411
3412
0
  struct rfapi_local_reg_delete_arg cda;
3413
0
  int rc;
3414
3415
0
  if ((rc = parse_deleter_args(vty, NULL, NULL, NULL, NULL, NULL, NULL,
3416
0
             NULL, NULL, &cda)))
3417
0
    return rc;
3418
3419
0
  cda.vty = vty;
3420
3421
0
  clear_vnc_responses(&cda);
3422
0
  clear_vnc_prefix(&cda);
3423
0
  clear_vnc_nve_closer(&cda);
3424
3425
0
  print_cleared_stats(&cda);
3426
3427
0
  return 0;
3428
0
}
3429
3430
DEFUN (clear_vnc_nve_vn_un,
3431
       clear_vnc_nve_vn_un_cmd,
3432
       "clear vnc nve vn <*|A.B.C.D|X:X::X:X> un <*|A.B.C.D|X:X::X:X>",
3433
       "clear\n"
3434
       "VNC Information\n"
3435
       "Clear prefix registration information\n"
3436
       "VN address of NVE\n"
3437
       "For all NVEs\n"
3438
       "VN IPv4 interface address\n"
3439
       "VN IPv6 interface address\n"
3440
       "UN address of NVE\n"
3441
       "For all UN addresses\n"
3442
       "UN IPv4 interface address\n"
3443
       "UN IPv6 interface address\n")
3444
0
{
3445
0
  struct rfapi_local_reg_delete_arg cda;
3446
0
  int rc;
3447
3448
0
  if ((rc = parse_deleter_tokens(vty, NULL, NULL, argv[4], argv[6], NULL,
3449
0
               NULL, NULL, NULL, &cda)))
3450
0
    return rc;
3451
3452
0
  cda.vty = vty;
3453
3454
0
  clear_vnc_responses(&cda);
3455
0
  clear_vnc_prefix(&cda);
3456
0
  clear_vnc_nve_closer(&cda);
3457
3458
0
  print_cleared_stats(&cda);
3459
3460
0
  return 0;
3461
0
}
3462
3463
DEFUN (clear_vnc_nve_un_vn,
3464
       clear_vnc_nve_un_vn_cmd,
3465
       "clear vnc nve un <*|A.B.C.D|X:X::X:X> vn <*|A.B.C.D|X:X::X:X>",
3466
       "clear\n"
3467
       "VNC Information\n"
3468
       "Clear prefix registration information\n"
3469
       "UN address of NVE\n"
3470
       "For all un NVEs\n"
3471
       "UN IPv4 interface address\n"
3472
       "UN IPv6 interface address\n"
3473
       "VN address of NVE\n"
3474
       "For all vn NVEs\n"
3475
       "VN IPv4 interface address\n"
3476
       "VN IPv6 interface address\n")
3477
0
{
3478
0
  struct rfapi_local_reg_delete_arg cda;
3479
0
  int rc;
3480
3481
0
  if ((rc = parse_deleter_tokens(vty, NULL, NULL, argv[6], argv[4], NULL,
3482
0
               NULL, NULL, NULL, &cda)))
3483
0
    return rc;
3484
3485
0
  cda.vty = vty;
3486
3487
0
  clear_vnc_responses(&cda);
3488
0
  clear_vnc_prefix(&cda);
3489
0
  clear_vnc_nve_closer(&cda);
3490
3491
0
  print_cleared_stats(&cda);
3492
3493
0
  return 0;
3494
0
}
3495
3496
DEFUN (clear_vnc_nve_vn,
3497
       clear_vnc_nve_vn_cmd,
3498
       "clear vnc nve vn <*|A.B.C.D|X:X::X:X>",
3499
       "clear\n"
3500
       "VNC Information\n"
3501
       "Clear prefix registration information\n"
3502
       "VN address of NVE\n"
3503
       "All addresses\n"
3504
       "VN IPv4 interface address\n"
3505
       "VN IPv6 interface address\n")
3506
0
{
3507
0
  struct rfapi_local_reg_delete_arg cda;
3508
0
  int rc;
3509
3510
0
  if ((rc = parse_deleter_tokens(vty, NULL, NULL, argv[4], NULL, NULL,
3511
0
               NULL, NULL, NULL, &cda)))
3512
0
    return rc;
3513
3514
0
  cda.vty = vty;
3515
3516
0
  clear_vnc_responses(&cda);
3517
0
  clear_vnc_prefix(&cda);
3518
0
  clear_vnc_nve_closer(&cda);
3519
3520
0
  print_cleared_stats(&cda);
3521
0
  return 0;
3522
0
}
3523
3524
DEFUN (clear_vnc_nve_un,
3525
       clear_vnc_nve_un_cmd,
3526
       "clear vnc nve un <*|A.B.C.D|X:X::X:X>",
3527
       "clear\n"
3528
       "VNC Information\n"
3529
       "Clear prefix registration information\n"
3530
       "UN address of NVE\n"
3531
       "All un nves\n"
3532
       "UN IPv4 interface address\n"
3533
       "UN IPv6 interface address\n")
3534
0
{
3535
0
  struct rfapi_local_reg_delete_arg cda;
3536
0
  int rc;
3537
3538
0
  if ((rc = parse_deleter_tokens(vty, NULL, NULL, NULL, argv[4], NULL,
3539
0
               NULL, NULL, NULL, &cda)))
3540
0
    return rc;
3541
3542
0
  cda.vty = vty;
3543
3544
0
  clear_vnc_responses(&cda);
3545
0
  clear_vnc_prefix(&cda);
3546
0
  clear_vnc_nve_closer(&cda);
3547
3548
0
  print_cleared_stats(&cda);
3549
0
  return 0;
3550
0
}
3551
3552
/*-------------------------------------------------
3553
 *    Clear VNC Prefix
3554
 *-------------------------------------------------*/
3555
3556
/*
3557
 * This function is defined in this file (rather than in rfp_registration.c)
3558
 * because here we have access to all the task handles.
3559
 */
3560
DEFUN (clear_vnc_prefix_vn_un,
3561
       clear_vnc_prefix_vn_un_cmd,
3562
       "clear vnc prefix <*|A.B.C.D/M|X:X::X:X/M> vn <*|A.B.C.D|X:X::X:X> un <*|A.B.C.D|X:X::X:X>",
3563
       "clear\n"
3564
       "VNC Information\n"
3565
       "Clear prefix registration information\n"
3566
       "All prefixes\n"
3567
       "IPv4 prefix\n"
3568
       "IPv6 prefix\n"
3569
       "VN address of NVE\n"
3570
       "All VN addresses\n"
3571
       "VN IPv4 interface address\n"
3572
       "VN IPv6 interface address\n"
3573
       "UN address of NVE\n"
3574
       "All UN addresses\n"
3575
       "UN IPv4 interface address\n"
3576
       "UN IPv6 interface address\n")
3577
0
{
3578
0
  struct rfapi_local_reg_delete_arg cda;
3579
0
  int rc;
3580
3581
0
  if ((rc = parse_deleter_tokens(vty, NULL, argv[3], argv[5], argv[7],
3582
0
               NULL, NULL, NULL, NULL, &cda)))
3583
0
    return rc;
3584
0
  cda.vty = vty;
3585
0
  clear_vnc_prefix(&cda);
3586
0
  print_cleared_stats(&cda);
3587
0
  return 0;
3588
0
}
3589
3590
DEFUN (clear_vnc_prefix_un_vn,
3591
       clear_vnc_prefix_un_vn_cmd,
3592
       "clear vnc prefix <*|A.B.C.D/M|X:X::X:X/M> un <*|A.B.C.D|X:X::X:X> vn <*|A.B.C.D|X:X::X:X>",
3593
       "clear\n"
3594
       "VNC Information\n"
3595
       "Clear prefix registration information\n"
3596
       "All prefixes\n"
3597
       "IPv4 prefix\n"
3598
       "IPv6 prefix\n"
3599
       "UN address of NVE\n"
3600
       "All UN addresses\n"
3601
       "UN IPv4 interface address\n"
3602
       "UN IPv6 interface address\n"
3603
       "VN address of NVE\n"
3604
       "All VN addresses\n"
3605
       "VN IPv4 interface address\n"
3606
       "VN IPv6 interface address\n")
3607
0
{
3608
0
  struct rfapi_local_reg_delete_arg cda;
3609
0
  int rc;
3610
3611
0
  if ((rc = parse_deleter_tokens(vty, NULL, argv[3], argv[7], argv[5],
3612
0
               NULL, NULL, NULL, NULL, &cda)))
3613
0
    return rc;
3614
0
  cda.vty = vty;
3615
0
  clear_vnc_prefix(&cda);
3616
0
  print_cleared_stats(&cda);
3617
0
  return 0;
3618
0
}
3619
3620
DEFUN (clear_vnc_prefix_un,
3621
       clear_vnc_prefix_un_cmd,
3622
       "clear vnc prefix <*|A.B.C.D/M|X:X::X:X/M> un <*|A.B.C.D|X:X::X:X>",
3623
       "clear\n"
3624
       "VNC Information\n"
3625
       "Clear prefix registration information\n"
3626
       "All prefixes\n"
3627
       "IPv4 prefix\n"
3628
       "IPv6 prefix\n"
3629
       "UN address of NVE\n"
3630
       "All UN addresses\n"
3631
       "UN IPv4 interface address\n"
3632
       "UN IPv6 interface address\n")
3633
0
{
3634
0
  struct rfapi_local_reg_delete_arg cda;
3635
0
  int rc;
3636
3637
0
  if ((rc = parse_deleter_tokens(vty, NULL, argv[3], NULL, argv[5], NULL,
3638
0
               NULL, NULL, NULL, &cda)))
3639
0
    return rc;
3640
0
  cda.vty = vty;
3641
0
  clear_vnc_prefix(&cda);
3642
0
  print_cleared_stats(&cda);
3643
0
  return 0;
3644
0
}
3645
3646
DEFUN (clear_vnc_prefix_vn,
3647
       clear_vnc_prefix_vn_cmd,
3648
       "clear vnc prefix <*|A.B.C.D/M|X:X::X:X/M> vn <*|A.B.C.D|X:X::X:X>",
3649
       "clear\n"
3650
       "VNC Information\n"
3651
       "Clear prefix registration information\n"
3652
       "All prefixes\n"
3653
       "IPv4 prefix\n"
3654
       "IPv6 prefix\n"
3655
       "UN address of NVE\n"
3656
       "All VN addresses\n"
3657
       "VN IPv4 interface address\n"
3658
       "VN IPv6 interface address\n")
3659
0
{
3660
0
  struct rfapi_local_reg_delete_arg cda;
3661
0
  int rc;
3662
3663
0
  if ((rc = parse_deleter_tokens(vty, NULL, argv[3], argv[5], NULL, NULL,
3664
0
               NULL, NULL, NULL, &cda)))
3665
0
    return rc;
3666
0
  cda.vty = vty;
3667
0
  clear_vnc_prefix(&cda);
3668
0
  print_cleared_stats(&cda);
3669
0
  return 0;
3670
0
}
3671
3672
DEFUN (clear_vnc_prefix_all,
3673
       clear_vnc_prefix_all_cmd,
3674
       "clear vnc prefix <*|A.B.C.D/M|X:X::X:X/M> *",
3675
       "clear\n"
3676
       "VNC Information\n"
3677
       "Clear prefix registration information\n"
3678
       "All prefixes\n"
3679
       "IPv4 prefix\n"
3680
       "IPv6 prefix\n"
3681
       "From any NVE\n")
3682
0
{
3683
0
  struct rfapi_local_reg_delete_arg cda;
3684
0
  int rc;
3685
3686
0
  if ((rc = parse_deleter_tokens(vty, NULL, argv[3], NULL, NULL, NULL,
3687
0
               NULL, NULL, NULL, &cda)))
3688
0
    return rc;
3689
0
  cda.vty = vty;
3690
0
  clear_vnc_prefix(&cda);
3691
0
  print_cleared_stats(&cda);
3692
0
  return 0;
3693
0
}
3694
3695
/*-------------------------------------------------
3696
 *    Clear VNC MAC
3697
 *-------------------------------------------------*/
3698
3699
/*
3700
 * This function is defined in this file (rather than in rfp_registration.c)
3701
 * because here we have access to all the task handles.
3702
 */
3703
DEFUN (clear_vnc_mac_vn_un,
3704
       clear_vnc_mac_vn_un_cmd,
3705
       "clear vnc mac <*|X:X:X:X:X:X> virtual-network-identifier <*|(1-4294967295)> vn <*|A.B.C.D|X:X::X:X> un <*|A.B.C.D|X:X::X:X>",
3706
       "clear\n"
3707
       "VNC Information\n"
3708
       "Clear mac registration information\n"
3709
       "All macs\n"
3710
       "MAC address\n"
3711
       "VNI keyword\n"
3712
       "Any virtual network identifier\n"
3713
       "Virtual network identifier\n"
3714
       "VN address of NVE\n"
3715
       "All VN addresses\n"
3716
       "VN IPv4 interface address\n"
3717
       "VN IPv6 interface address\n"
3718
       "UN address of NVE\n"
3719
       "All UN addresses\n"
3720
       "UN IPv4 interface address\n"
3721
       "UN IPv6 interface address\n")
3722
0
{
3723
0
  struct rfapi_local_reg_delete_arg cda;
3724
0
  int rc;
3725
3726
  /* pfx vn un L2 VNI */
3727
0
  if ((rc = parse_deleter_tokens(vty, NULL, NULL, argv[7], argv[9],
3728
0
               argv[3], argv[5], NULL, NULL, &cda)))
3729
0
    return rc;
3730
0
  cda.vty = vty;
3731
0
  clear_vnc_prefix(&cda);
3732
0
  print_cleared_stats(&cda);
3733
0
  return 0;
3734
0
}
3735
3736
DEFUN (clear_vnc_mac_un_vn,
3737
       clear_vnc_mac_un_vn_cmd,
3738
       "clear vnc mac <*|X:X:X:X:X:X> virtual-network-identifier <*|(1-4294967295)> un <*|A.B.C.D|X:X::X:X> vn <*|A.B.C.D|X:X::X:X>",
3739
       "clear\n"
3740
       "VNC Information\n"
3741
       "Clear mac registration information\n"
3742
       "All macs\n"
3743
       "MAC address\n"
3744
       "VNI keyword\n"
3745
       "Any virtual network identifier\n"
3746
       "Virtual network identifier\n"
3747
       "UN address of NVE\n"
3748
       "All UN addresses\n"
3749
       "UN IPv4 interface address\n"
3750
       "UN IPv6 interface address\n"
3751
       "VN address of NVE\n"
3752
       "All VN addresses\n"
3753
       "VN IPv4 interface address\n"
3754
       "VN IPv6 interface address\n")
3755
0
{
3756
0
  struct rfapi_local_reg_delete_arg cda;
3757
0
  int rc;
3758
3759
  /* pfx vn un L2 VNI */
3760
0
  if ((rc = parse_deleter_tokens(vty, NULL, NULL, argv[9], argv[7],
3761
0
               argv[3], argv[5], NULL, NULL, &cda)))
3762
0
    return rc;
3763
0
  cda.vty = vty;
3764
0
  clear_vnc_prefix(&cda);
3765
0
  print_cleared_stats(&cda);
3766
0
  return 0;
3767
0
}
3768
3769
DEFUN (clear_vnc_mac_un,
3770
       clear_vnc_mac_un_cmd,
3771
       "clear vnc mac <*|X:X:X:X:X:X> virtual-network-identifier <*|(1-4294967295)> un <*|A.B.C.D|X:X::X:X>",
3772
       "clear\n"
3773
       "VNC Information\n"
3774
       "Clear mac registration information\n"
3775
       "All macs\n"
3776
       "MAC address\n"
3777
       "VNI keyword\n"
3778
       "Any virtual network identifier\n"
3779
       "Virtual network identifier\n"
3780
       "UN address of NVE\n"
3781
       "All UN addresses\n"
3782
       "UN IPv4 interface address\n"
3783
       "UN IPv6 interface address\n")
3784
0
{
3785
0
  struct rfapi_local_reg_delete_arg cda;
3786
0
  int rc;
3787
3788
  /* pfx vn un L2 VNI */
3789
0
  if ((rc = parse_deleter_tokens(vty, NULL, NULL, NULL, argv[7], argv[3],
3790
0
               argv[5], NULL, NULL, &cda)))
3791
0
    return rc;
3792
0
  cda.vty = vty;
3793
0
  clear_vnc_prefix(&cda);
3794
0
  print_cleared_stats(&cda);
3795
0
  return 0;
3796
0
}
3797
3798
DEFUN (clear_vnc_mac_vn,
3799
       clear_vnc_mac_vn_cmd,
3800
       "clear vnc mac <*|X:X:X:X:X:X> virtual-network-identifier <*|(1-4294967295)> vn <*|A.B.C.D|X:X::X:X>",
3801
       "clear\n"
3802
       "VNC Information\n"
3803
       "Clear mac registration information\n"
3804
       "All macs\n"
3805
       "MAC address\n"
3806
       "VNI keyword\n"
3807
       "Any virtual network identifier\n"
3808
       "Virtual network identifier\n"
3809
       "UN address of NVE\n"
3810
       "All VN addresses\n"
3811
       "VN IPv4 interface address\n"
3812
       "VN IPv6 interface address\n")
3813
0
{
3814
0
  struct rfapi_local_reg_delete_arg cda;
3815
0
  int rc;
3816
3817
  /* pfx vn un L2 VNI */
3818
0
  if ((rc = parse_deleter_tokens(vty, NULL, NULL, argv[7], NULL, argv[3],
3819
0
               argv[5], NULL, NULL, &cda)))
3820
0
    return rc;
3821
0
  cda.vty = vty;
3822
0
  clear_vnc_prefix(&cda);
3823
0
  print_cleared_stats(&cda);
3824
0
  return 0;
3825
0
}
3826
3827
DEFUN (clear_vnc_mac_all,
3828
       clear_vnc_mac_all_cmd,
3829
       "clear vnc mac <*|X:X:X:X:X:X> virtual-network-identifier <*|(1-4294967295)> *",
3830
       "clear\n"
3831
       "VNC Information\n"
3832
       "Clear mac registration information\n"
3833
       "All macs\n"
3834
       "MAC address\n"
3835
       "VNI keyword\n"
3836
       "Any virtual network identifier\n"
3837
       "Virtual network identifier\n"
3838
       "From any NVE\n")
3839
0
{
3840
0
  struct rfapi_local_reg_delete_arg cda;
3841
0
  int rc;
3842
3843
  /* pfx vn un L2 VNI */
3844
0
  if ((rc = parse_deleter_tokens(vty, NULL, NULL, NULL, NULL, argv[3],
3845
0
               argv[5], NULL, NULL, &cda)))
3846
0
    return rc;
3847
0
  cda.vty = vty;
3848
0
  clear_vnc_prefix(&cda);
3849
0
  print_cleared_stats(&cda);
3850
0
  return 0;
3851
0
}
3852
3853
/*-------------------------------------------------
3854
 *    Clear VNC MAC PREFIX
3855
 *-------------------------------------------------*/
3856
3857
DEFUN (clear_vnc_mac_vn_un_prefix,
3858
       clear_vnc_mac_vn_un_prefix_cmd,
3859
       "clear vnc mac <*|X:X:X:X:X:X> virtual-network-identifier <*|(1-4294967295)> vn <*|A.B.C.D|X:X::X:X> un <*|A.B.C.D|X:X::X:X> prefix <*|A.B.C.D/M|X:X::X:X/M>",
3860
       "clear\n"
3861
       "VNC Information\n"
3862
       "Clear mac registration information\n"
3863
       "All macs\n"
3864
       "MAC address\n"
3865
       "VNI keyword\n"
3866
       "Any virtual network identifier\n"
3867
       "Virtual network identifier\n"
3868
       "VN address of NVE\n"
3869
       "All VN addresses\n"
3870
       "VN IPv4 interface address\n"
3871
       "VN IPv6 interface address\n"
3872
       "UN address of NVE\n"
3873
       "All UN addresses\n"
3874
       "UN IPv4 interface address\n"
3875
       "UN IPv6 interface address\n"
3876
       "Clear prefix registration information\n"
3877
       "All prefixes\n"
3878
       "IPv4 prefix\n"
3879
       "IPv6 prefix\n")
3880
0
{
3881
0
  struct rfapi_local_reg_delete_arg cda;
3882
0
  int rc;
3883
3884
  /* pfx vn un L2 VNI */
3885
0
  if ((rc = parse_deleter_tokens(vty, NULL, argv[11], argv[7], argv[9],
3886
0
               argv[3], argv[5], NULL, NULL, &cda)))
3887
0
    return rc;
3888
0
  cda.vty = vty;
3889
0
  clear_vnc_prefix(&cda);
3890
0
  print_cleared_stats(&cda);
3891
0
  return 0;
3892
0
}
3893
3894
DEFUN (clear_vnc_mac_un_vn_prefix,
3895
       clear_vnc_mac_un_vn_prefix_cmd,
3896
       "clear vnc mac <*|X:X:X:X:X:X> virtual-network-identifier <*|(1-4294967295)> un <*|A.B.C.D|X:X::X:X> vn <*|A.B.C.D|X:X::X:X> prefix <*|A.B.C.D/M|X:X::X:X/M> prefix <*|A.B.C.D/M|X:X::X:X/M>",
3897
       "clear\n"
3898
       "VNC Information\n"
3899
       "Clear mac registration information\n"
3900
       "All macs\n"
3901
       "MAC address\n"
3902
       "VNI keyword\n"
3903
       "Any virtual network identifier\n"
3904
       "Virtual network identifier\n"
3905
       "UN address of NVE\n"
3906
       "All UN addresses\n"
3907
       "UN IPv4 interface address\n"
3908
       "UN IPv6 interface address\n"
3909
       "VN address of NVE\n"
3910
       "All VN addresses\n"
3911
       "VN IPv4 interface address\n"
3912
       "VN IPv6 interface address\n"
3913
       "Clear prefix registration information\n"
3914
       "All prefixes\n"
3915
       "IPv4 prefix\n"
3916
       "IPv6 prefix\n"
3917
       "Clear prefix registration information\n"
3918
       "All prefixes\n"
3919
       "IPv4 prefix\n"
3920
       "IPv6 prefix\n")
3921
0
{
3922
0
  struct rfapi_local_reg_delete_arg cda;
3923
0
  int rc;
3924
3925
  /* pfx vn un L2 VNI */
3926
0
  if ((rc = parse_deleter_tokens(vty, NULL, argv[11], argv[9], argv[7],
3927
0
               argv[3], argv[5], NULL, NULL, &cda)))
3928
0
    return rc;
3929
0
  cda.vty = vty;
3930
0
  clear_vnc_prefix(&cda);
3931
0
  print_cleared_stats(&cda);
3932
0
  return 0;
3933
0
}
3934
3935
DEFUN (clear_vnc_mac_un_prefix,
3936
       clear_vnc_mac_un_prefix_cmd,
3937
       "clear vnc mac <*|X:X:X:X:X:X> virtual-network-identifier <*|(1-4294967295)> un <*|A.B.C.D|X:X::X:X> prefix <*|A.B.C.D/M|X:X::X:X/M>",
3938
       "clear\n"
3939
       "VNC Information\n"
3940
       "Clear mac registration information\n"
3941
       "All macs\n"
3942
       "MAC address\n"
3943
       "VNI keyword\n"
3944
       "Any virtual network identifier\n"
3945
       "Virtual network identifier\n"
3946
       "UN address of NVE\n"
3947
       "All UN addresses\n"
3948
       "UN IPv4 interface address\n"
3949
       "UN IPv6 interface address\n"
3950
       "Clear prefix registration information\n"
3951
       "All prefixes\n"
3952
       "IPv4 Prefix\n"
3953
       "IPv6 Prefix\n")
3954
0
{
3955
0
  struct rfapi_local_reg_delete_arg cda;
3956
0
  int rc;
3957
3958
  /* pfx vn un L2 VNI */
3959
0
  if ((rc = parse_deleter_tokens(vty, NULL, argv[9], NULL, argv[7],
3960
0
               argv[3], argv[5], NULL, NULL, &cda)))
3961
0
    return rc;
3962
0
  cda.vty = vty;
3963
0
  clear_vnc_prefix(&cda);
3964
0
  print_cleared_stats(&cda);
3965
0
  return 0;
3966
0
}
3967
3968
DEFUN (clear_vnc_mac_vn_prefix,
3969
       clear_vnc_mac_vn_prefix_cmd,
3970
       "clear vnc mac <*|X:X:X:X:X:X> virtual-network-identifier <*|(1-4294967295)> vn <*|A.B.C.D|X:X::X:X> prefix <*|A.B.C.D/M|X:X::X:X/M>",
3971
       "clear\n"
3972
       "VNC Information\n"
3973
       "Clear mac registration information\n"
3974
       "All macs\n"
3975
       "MAC address\n"
3976
       "VNI keyword\n"
3977
       "Any virtual network identifier\n"
3978
       "Virtual network identifier\n"
3979
       "UN address of NVE\n"
3980
       "All VN addresses\n"
3981
       "VN IPv4 interface address\n"
3982
       "VN IPv6 interface address\n"
3983
       "Clear prefix registration information\n"
3984
       "All prefixes\n"
3985
       "IPv4 Prefix\n"
3986
       "IPv6 Prefix\n")
3987
0
{
3988
0
  struct rfapi_local_reg_delete_arg cda;
3989
0
  int rc;
3990
3991
  /* pfx vn un L2 VNI */
3992
0
  if ((rc = parse_deleter_tokens(vty, NULL, argv[9], argv[7], NULL,
3993
0
               argv[3], argv[5], NULL, NULL, &cda)))
3994
0
    return rc;
3995
0
  cda.vty = vty;
3996
0
  clear_vnc_prefix(&cda);
3997
0
  print_cleared_stats(&cda);
3998
0
  return 0;
3999
0
}
4000
4001
DEFUN (clear_vnc_mac_all_prefix,
4002
       clear_vnc_mac_all_prefix_cmd,
4003
       "clear vnc mac <*|X:X:X:X:X:X> virtual-network-identifier <*|(1-4294967295)> prefix <*|A.B.C.D/M|X:X::X:X/M>",
4004
       "clear\n"
4005
       "VNC Information\n"
4006
       "Clear mac registration information\n"
4007
       "All macs\n"
4008
       "MAC address\n"
4009
       "VNI keyword\n"
4010
       "Any virtual network identifier\n"
4011
       "Virtual network identifier\n"
4012
       "UN address of NVE\n"
4013
       "All VN addresses\n"
4014
       "VN IPv4 interface address\n"
4015
       "VN IPv6 interface address\n")
4016
0
{
4017
0
  struct rfapi_local_reg_delete_arg cda;
4018
0
  int rc;
4019
4020
  /* pfx vn un L2 VNI */
4021
0
  if ((rc = parse_deleter_tokens(vty, NULL, argv[7], NULL, NULL, argv[3],
4022
0
               argv[5], NULL, NULL, &cda)))
4023
0
    return rc;
4024
0
  cda.vty = vty;
4025
0
  clear_vnc_prefix(&cda);
4026
0
  print_cleared_stats(&cda);
4027
0
  return 0;
4028
0
}
4029
4030
/************************************************************************
4031
 *      Show commands
4032
 ************************************************************************/
4033
4034
4035
/* copied from rfp_vty.c */
4036
static int check_and_display_is_vnc_running(struct vty *vty)
4037
0
{
4038
0
  if (bgp_rfapi_is_vnc_configured(NULL) == 0)
4039
0
    return 1; /* is running */
4040
4041
0
  if (vty) {
4042
0
    vty_out(vty, "VNC is not configured.\n");
4043
0
  }
4044
0
  return 0; /* not running */
4045
0
}
4046
4047
static int rfapi_vty_show_nve_summary(struct vty *vty,
4048
              show_nve_summary_t show_type)
4049
0
{
4050
0
  struct bgp *bgp_default = bgp_get_default();
4051
0
  struct rfapi *h;
4052
0
  int is_vnc_running = (bgp_rfapi_is_vnc_configured(bgp_default) == 0);
4053
4054
0
  int active_local_routes;
4055
0
  int active_remote_routes;
4056
0
  int holddown_remote_routes;
4057
0
  int imported_remote_routes;
4058
4059
0
  if (!bgp_default)
4060
0
    goto notcfg;
4061
4062
0
  h = bgp_default->rfapi;
4063
4064
0
  if (!h)
4065
0
    goto notcfg;
4066
4067
  /* don't show local info if not running RFP */
4068
0
  if (is_vnc_running || show_type == SHOW_NVE_SUMMARY_REGISTERED) {
4069
4070
0
    switch (show_type) {
4071
4072
0
    case SHOW_NVE_SUMMARY_ACTIVE_NVES:
4073
0
      vty_out(vty, "%-24s ", "NVEs:");
4074
0
      vty_out(vty, "%-8s %-8u ",
4075
0
        "Active:", h->descriptors.count);
4076
0
      vty_out(vty, "%-8s %-8u ",
4077
0
        "Maximum:", h->stat.max_descriptors);
4078
0
      vty_out(vty, "%-8s %-8u",
4079
0
        "Unknown:", h->stat.count_unknown_nves);
4080
0
      break;
4081
4082
0
    case SHOW_NVE_SUMMARY_REGISTERED:
4083
      /*
4084
       * NB: With the introduction of L2 route support, we no
4085
       * longer have a one-to-one correspondence between
4086
       * locally-originated route advertisements and routes in
4087
       * the import tables that have local origin. This
4088
       * discrepancy arises because a single advertisement
4089
       * may contain both an IP prefix and a MAC address.
4090
       * Such an advertisement results in two import table
4091
       * entries: one indexed by IP prefix, the other indexed
4092
       * by MAC address.
4093
       *
4094
       * TBD: update computation and display of registration
4095
       * statistics to reflect the underlying semantics.
4096
       */
4097
0
      if (is_vnc_running) {
4098
0
        vty_out(vty, "%-24s ", "Registrations:");
4099
0
        vty_out(vty, "%-8s %-8u ", "Active:",
4100
0
          rfapiApCountAll(bgp_default));
4101
0
        vty_out(vty, "%-8s %-8u ", "Failed:",
4102
0
          h->stat.count_registrations_failed);
4103
0
        vty_out(vty, "%-8s %-8u",
4104
0
          "Total:", h->stat.count_registrations);
4105
0
        vty_out(vty, "\n");
4106
0
      }
4107
0
      vty_out(vty, "%-24s ", "Prefixes registered:");
4108
0
      vty_out(vty, "\n");
4109
4110
0
      rfapiCountAllItRoutes(&active_local_routes,
4111
0
                &active_remote_routes,
4112
0
                &holddown_remote_routes,
4113
0
                &imported_remote_routes);
4114
4115
      /* local */
4116
0
      if (is_vnc_running) {
4117
0
        vty_out(vty, "    %-20s ", "Locally:");
4118
0
        vty_out(vty, "%-8s %-8u ",
4119
0
          "Active:", active_local_routes);
4120
0
        vty_out(vty, "\n");
4121
0
      }
4122
4123
4124
0
      vty_out(vty, "    %-20s ", "Remotely:");
4125
0
      vty_out(vty, "%-8s %-8u",
4126
0
        "Active:", active_remote_routes);
4127
0
      vty_out(vty, "\n");
4128
0
      vty_out(vty, "    %-20s ", "In Holddown:");
4129
0
      vty_out(vty, "%-8s %-8u",
4130
0
        "Active:", holddown_remote_routes);
4131
0
      vty_out(vty, "\n");
4132
0
      vty_out(vty, "    %-20s ", "Imported:");
4133
0
      vty_out(vty, "%-8s %-8u",
4134
0
        "Active:", imported_remote_routes);
4135
0
      break;
4136
4137
0
    case SHOW_NVE_SUMMARY_QUERIES:
4138
0
      vty_out(vty, "%-24s ", "Queries:");
4139
0
      vty_out(vty, "%-8s %-8u ",
4140
0
        "Active:", rfapi_monitor_count(NULL));
4141
0
      vty_out(vty, "%-8s %-8u ",
4142
0
        "Failed:", h->stat.count_queries_failed);
4143
0
      vty_out(vty, "%-8s %-8u",
4144
0
        "Total:", h->stat.count_queries);
4145
0
      break;
4146
4147
0
    case SHOW_NVE_SUMMARY_RESPONSES:
4148
0
      rfapiRibShowResponsesSummary(vty);
4149
4150
0
    case SHOW_NVE_SUMMARY_UNKNOWN_NVES:
4151
0
    case SHOW_NVE_SUMMARY_MAX:
4152
0
      break;
4153
0
    }
4154
0
    vty_out(vty, "\n");
4155
0
  }
4156
0
  return 0;
4157
4158
0
notcfg:
4159
0
  vty_out(vty, "VNC is not configured.\n");
4160
0
  return CMD_WARNING;
4161
0
}
4162
4163
static int rfapi_show_nves(struct vty *vty, struct prefix *vn_prefix,
4164
         struct prefix *un_prefix)
4165
0
{
4166
  // struct hash                      *rfds;
4167
  // struct rfp_rfapi_descriptor_param param;
4168
4169
0
  struct bgp *bgp_default = bgp_get_default();
4170
0
  struct rfapi *h;
4171
0
  struct listnode *node;
4172
0
  struct rfapi_descriptor *rfd;
4173
4174
0
  int total = 0;
4175
0
  int printed = 0;
4176
0
  int rc;
4177
4178
0
  if (!bgp_default)
4179
0
    goto notcfg;
4180
4181
0
  h = bgp_default->rfapi;
4182
4183
0
  if (!h)
4184
0
    goto notcfg;
4185
4186
0
  rc = rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_ACTIVE_NVES);
4187
0
  if (rc)
4188
0
    return rc;
4189
4190
0
  for (ALL_LIST_ELEMENTS_RO(&h->descriptors, node, rfd)) {
4191
0
    struct prefix pfx;
4192
0
    char vn_addr_buf[INET6_ADDRSTRLEN] = {
4193
0
      0,
4194
0
    };
4195
0
    char un_addr_buf[INET6_ADDRSTRLEN] = {
4196
0
      0,
4197
0
    };
4198
0
    char age[10];
4199
4200
0
    ++total;
4201
4202
0
    if (vn_prefix) {
4203
0
      assert(!rfapiRaddr2Qprefix(&rfd->vn_addr, &pfx));
4204
0
      if (!prefix_match(vn_prefix, &pfx))
4205
0
        continue;
4206
0
    }
4207
4208
0
    if (un_prefix) {
4209
0
      assert(!rfapiRaddr2Qprefix(&rfd->un_addr, &pfx));
4210
0
      if (!prefix_match(un_prefix, &pfx))
4211
0
        continue;
4212
0
    }
4213
4214
0
    rfapiRfapiIpAddr2Str(&rfd->vn_addr, vn_addr_buf,
4215
0
             INET6_ADDRSTRLEN);
4216
0
    rfapiRfapiIpAddr2Str(&rfd->un_addr, un_addr_buf,
4217
0
             INET6_ADDRSTRLEN);
4218
4219
0
    if (!printed) {
4220
      /* print out a header */
4221
0
      vty_out(vty,
4222
0
        "                                Active      Next Hops\n");
4223
0
      vty_out(vty, "%-15s %-15s %-5s %-5s %-6s %-6s %s\n",
4224
0
        "VN Address", "UN Address", "Regis", "Resps",
4225
0
        "Reach", "Remove", "Age");
4226
0
    }
4227
4228
0
    ++printed;
4229
4230
0
    vty_out(vty, "%-15s %-15s %-5u %-5u %-6u %-6u %s\n",
4231
0
      vn_addr_buf, un_addr_buf, rfapiApCount(rfd),
4232
0
      rfapi_monitor_count(rfd), rfd->stat_count_nh_reachable,
4233
0
      rfd->stat_count_nh_removal,
4234
0
      rfapiFormatAge(rfd->open_time, age, 10));
4235
0
  }
4236
4237
0
  if (printed > 0 || vn_prefix || un_prefix)
4238
0
    vty_out(vty, "Displayed %d out of %d active NVEs\n", printed,
4239
0
      total);
4240
4241
0
  return 0;
4242
4243
0
notcfg:
4244
0
  vty_out(vty, "VNC is not configured.\n");
4245
0
  return CMD_WARNING;
4246
0
}
4247
4248
4249
DEFUN (vnc_show_summary,
4250
       vnc_show_summary_cmd,
4251
       "show vnc summary",
4252
       SHOW_STR
4253
       VNC_SHOW_STR
4254
       "Display VNC status summary\n")
4255
0
{
4256
0
  if (!check_and_display_is_vnc_running(vty))
4257
0
    return CMD_SUCCESS;
4258
0
  bgp_rfapi_show_summary(bgp_get_default(), vty);
4259
0
  vty_out(vty, "\n");
4260
0
  rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_ACTIVE_NVES);
4261
0
  rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_QUERIES);
4262
0
  rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_RESPONSES);
4263
0
  rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_REGISTERED);
4264
0
  return CMD_SUCCESS;
4265
0
}
4266
4267
DEFUN (vnc_show_nves,
4268
       vnc_show_nves_cmd,
4269
       "show vnc nves",
4270
       SHOW_STR
4271
       VNC_SHOW_STR
4272
       "List known NVEs\n")
4273
0
{
4274
0
  rfapi_show_nves(vty, NULL, NULL);
4275
0
  return CMD_SUCCESS;
4276
0
}
4277
4278
DEFUN (vnc_show_nves_ptct,
4279
       vnc_show_nves_ptct_cmd,
4280
       "show vnc nves <vn|un> <A.B.C.D|X:X::X:X>",
4281
       SHOW_STR
4282
       VNC_SHOW_STR
4283
       "List known NVEs\n"
4284
       "VN address of NVE\n"
4285
       "UN address of NVE\n"
4286
       "IPv4 interface address\n"
4287
       "IPv6 interface address\n")
4288
0
{
4289
0
  struct prefix pfx;
4290
4291
0
  if (!check_and_display_is_vnc_running(vty))
4292
0
    return CMD_SUCCESS;
4293
4294
0
  if (!str2prefix(argv[4]->arg, &pfx)) {
4295
0
    vty_out(vty, "Malformed address \"%s\"\n", argv[4]->arg);
4296
0
    return CMD_WARNING;
4297
0
  }
4298
0
  if (pfx.family != AF_INET && pfx.family != AF_INET6) {
4299
0
    vty_out(vty, "Invalid address \"%s\"\n", argv[4]->arg);
4300
0
    return CMD_WARNING;
4301
0
  }
4302
4303
0
  if (argv[3]->arg[0] == 'u') {
4304
0
    rfapi_show_nves(vty, NULL, &pfx);
4305
0
  } else {
4306
0
    rfapi_show_nves(vty, &pfx, NULL);
4307
0
  }
4308
4309
0
  return CMD_SUCCESS;
4310
0
}
4311
4312
/* adapted from rfp_registration_cache_log() */
4313
static void rfapi_show_registrations(struct vty *vty,
4314
             struct prefix *restrict_to, int show_local,
4315
             int show_remote, int show_holddown,
4316
             int show_imported)
4317
0
{
4318
0
  int printed = 0;
4319
4320
0
  if (!vty)
4321
0
    return;
4322
4323
0
  rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_REGISTERED);
4324
4325
0
  if (show_local) {
4326
    /* non-expiring, local */
4327
0
    printed += rfapiShowRemoteRegistrations(vty, restrict_to, 0, 1,
4328
0
              0, 0);
4329
0
  }
4330
0
  if (show_remote) {
4331
    /* non-expiring, non-local */
4332
0
    printed += rfapiShowRemoteRegistrations(vty, restrict_to, 0, 0,
4333
0
              1, 0);
4334
0
  }
4335
0
  if (show_holddown) {
4336
    /* expiring, including local */
4337
0
    printed += rfapiShowRemoteRegistrations(vty, restrict_to, 1, 1,
4338
0
              1, 0);
4339
0
  }
4340
0
  if (show_imported) {
4341
    /* non-expiring, non-local */
4342
0
    printed += rfapiShowRemoteRegistrations(vty, restrict_to, 0, 0,
4343
0
              1, 1);
4344
0
  }
4345
0
  if (!printed) {
4346
0
    vty_out(vty, "\n");
4347
0
  }
4348
0
}
4349
4350
DEFUN (vnc_show_registrations_pfx,
4351
       vnc_show_registrations_pfx_cmd,
4352
       "show vnc registrations [<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M|X:X:X:X:X:X>]",
4353
       SHOW_STR
4354
       VNC_SHOW_STR
4355
       "List active prefix registrations\n"
4356
       "Limit output to a particualr IPV4 address\n"
4357
       "Limit output to a particular IPv4 prefix\n"
4358
       "Limit output to a particualr IPV6 address\n"
4359
       "Limit output to a particular IPv6 prefix\n"
4360
       "Limit output to a particular MAC address\n")
4361
0
{
4362
0
  struct prefix p;
4363
0
  struct prefix *p_addr = NULL;
4364
4365
0
  if (argc > 3) {
4366
0
    if (!str2prefix(argv[3]->arg, &p)) {
4367
0
      vty_out(vty, "Invalid prefix: %s\n", argv[3]->arg);
4368
0
      return CMD_SUCCESS;
4369
0
    } else {
4370
0
      p_addr = &p;
4371
0
    }
4372
0
  }
4373
4374
0
  rfapi_show_registrations(vty, p_addr, 1, 1, 1, 1);
4375
0
  return CMD_SUCCESS;
4376
0
}
4377
4378
DEFUN (vnc_show_registrations_some_pfx,
4379
         vnc_show_registrations_some_pfx_cmd,
4380
         "show vnc registrations <all|holddown|imported|local|remote> [<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M|X:X:X:X:X:X>]",
4381
         SHOW_STR
4382
         VNC_SHOW_STR
4383
         "List active prefix registrations\n"
4384
         "show all registrations\n"
4385
         "show only registrations in holddown\n"
4386
         "show only imported prefixes\n"
4387
         "show only local registrations\n"
4388
         "show only remote registrations\n"
4389
         "Limit output to a particualr IPV4 address\n"
4390
         "Limit output to a particular IPv4 prefix\n"
4391
         "Limit output to a particualr IPV6 address\n"
4392
         "Limit output to a particular IPv6 prefix\n"
4393
         "Limit output to a particular MAC address\n")
4394
0
{
4395
0
  struct prefix p;
4396
0
  struct prefix *p_addr = NULL;
4397
4398
0
  int show_local = 0;
4399
0
  int show_remote = 0;
4400
0
  int show_holddown = 0;
4401
0
  int show_imported = 0;
4402
4403
0
  if (argc > 4) {
4404
0
    if (!str2prefix(argv[4]->arg, &p)) {
4405
0
      vty_out(vty, "Invalid prefix: %s\n", argv[4]->arg);
4406
0
      return CMD_SUCCESS;
4407
0
    } else {
4408
0
      p_addr = &p;
4409
0
    }
4410
0
  }
4411
0
  switch (argv[3]->arg[0]) {
4412
0
  case 'a':
4413
0
    show_local = 1;
4414
0
    show_remote = 1;
4415
0
    show_holddown = 1;
4416
0
    show_imported = 1;
4417
0
    break;
4418
4419
0
  case 'h':
4420
0
    show_holddown = 1;
4421
0
    break;
4422
4423
0
  case 'i':
4424
0
    show_imported = 1;
4425
0
    break;
4426
4427
0
  case 'l':
4428
0
    show_local = 1;
4429
0
    break;
4430
4431
0
  case 'r':
4432
0
    show_remote = 1;
4433
0
    break;
4434
0
  }
4435
4436
0
  rfapi_show_registrations(vty, p_addr, show_local, show_remote,
4437
0
         show_holddown, show_imported);
4438
0
  return CMD_SUCCESS;
4439
0
}
4440
4441
DEFUN (vnc_show_responses_pfx,
4442
       vnc_show_responses_pfx_cmd,
4443
       "show vnc responses [<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M|X:X:X:X:X:X>]",
4444
       SHOW_STR
4445
       VNC_SHOW_STR
4446
       "List recent query responses\n"
4447
       "Limit output to a particualr IPV4 address\n"
4448
       "Limit output to a particular IPv4 prefix\n"
4449
       "Limit output to a particualr IPV6 address\n"
4450
       "Limit output to a particular IPv6 prefix\n"
4451
       "Limit output to a particular MAC address\n" )
4452
0
{
4453
0
  struct prefix p;
4454
0
  struct prefix *p_addr = NULL;
4455
4456
0
  if (argc > 3) {
4457
0
    if (!str2prefix(argv[3]->arg, &p)) {
4458
0
      vty_out(vty, "Invalid prefix: %s\n", argv[3]->arg);
4459
0
      return CMD_SUCCESS;
4460
0
    } else {
4461
0
      p_addr = &p;
4462
0
    }
4463
0
  }
4464
0
  rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_QUERIES);
4465
4466
0
  rfapiRibShowResponsesSummary(vty);
4467
4468
0
  rfapiRibShowResponses(vty, p_addr, 0);
4469
0
  rfapiRibShowResponses(vty, p_addr, 1);
4470
4471
0
  return CMD_SUCCESS;
4472
0
}
4473
4474
DEFUN (vnc_show_responses_some_pfx,
4475
       vnc_show_responses_some_pfx_cmd,
4476
       "show vnc responses <active|removed> [<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M|X:X:X:X:X:X>]",
4477
       SHOW_STR
4478
       VNC_SHOW_STR
4479
       "List recent query responses\n"
4480
       "show only active query responses\n"
4481
       "show only removed query responses\n"
4482
       "Limit output to a particualr IPV4 address\n"
4483
       "Limit output to a particular IPv4 prefix\n"
4484
       "Limit output to a particualr IPV6 address\n"
4485
       "Limit output to a particular IPv6 prefix\n"
4486
       "Limit output to a particular MAC address\n")
4487
0
{
4488
0
  struct prefix p;
4489
0
  struct prefix *p_addr = NULL;
4490
4491
0
  int show_active = 0;
4492
0
  int show_removed = 0;
4493
4494
0
  if (!check_and_display_is_vnc_running(vty))
4495
0
    return CMD_SUCCESS;
4496
4497
0
  if (argc > 4) {
4498
0
    if (!str2prefix(argv[4]->arg, &p)) {
4499
0
      vty_out(vty, "Invalid prefix: %s\n", argv[4]->arg);
4500
0
      return CMD_SUCCESS;
4501
0
    } else {
4502
0
      p_addr = &p;
4503
0
    }
4504
0
  }
4505
4506
0
  switch (argv[3]->arg[0]) {
4507
0
  case 'a':
4508
0
    show_active = 1;
4509
0
    break;
4510
4511
0
  case 'r':
4512
0
    show_removed = 1;
4513
0
    break;
4514
0
  }
4515
4516
0
  rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_QUERIES);
4517
4518
0
  rfapiRibShowResponsesSummary(vty);
4519
4520
0
  if (show_active)
4521
0
    rfapiRibShowResponses(vty, p_addr, 0);
4522
0
  if (show_removed)
4523
0
    rfapiRibShowResponses(vty, p_addr, 1);
4524
4525
0
  return CMD_SUCCESS;
4526
0
}
4527
4528
DEFUN (show_vnc_queries_pfx,
4529
       show_vnc_queries_pfx_cmd,
4530
       "show vnc queries [<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M|X:X:X:X:X:X>]",
4531
       SHOW_STR
4532
       VNC_SHOW_STR
4533
       "List active queries\n"
4534
       "Limit output to a particualr IPV4 address\n"
4535
       "Limit output to a particular IPv4 prefix\n"
4536
       "Limit output to a particualr IPV6 address\n"
4537
       "Limit output to a particular IPv6 prefix\n"
4538
       "Limit output to a particualr MAC address\n")
4539
0
{
4540
0
  struct prefix pfx;
4541
0
  struct prefix *p = NULL;
4542
4543
0
  if (argc > 3) {
4544
0
    if (!str2prefix(argv[3]->arg, &pfx)) {
4545
0
      vty_out(vty, "Invalid prefix: %s\n", argv[3]->arg);
4546
0
      return CMD_WARNING;
4547
0
    }
4548
0
    p = &pfx;
4549
0
  }
4550
4551
0
  rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_QUERIES);
4552
4553
0
  return rfapiShowVncQueries(vty, p);
4554
0
}
4555
4556
DEFUN (vnc_clear_counters,
4557
       vnc_clear_counters_cmd,
4558
       "clear vnc counters",
4559
       CLEAR_STR
4560
       VNC_SHOW_STR
4561
       "Reset VNC counters\n")
4562
0
{
4563
0
  struct bgp *bgp_default = bgp_get_default();
4564
0
  struct rfapi *h;
4565
0
  struct listnode *node;
4566
0
  struct rfapi_descriptor *rfd;
4567
4568
0
  if (!bgp_default)
4569
0
    goto notcfg;
4570
4571
0
  h = bgp_default->rfapi;
4572
4573
0
  if (!h)
4574
0
    goto notcfg;
4575
4576
  /* per-rfd */
4577
0
  for (ALL_LIST_ELEMENTS_RO(&h->descriptors, node, rfd)) {
4578
0
    rfd->stat_count_nh_reachable = 0;
4579
0
    rfd->stat_count_nh_removal = 0;
4580
0
  }
4581
4582
  /* global */
4583
0
  memset(&h->stat, 0, sizeof(h->stat));
4584
4585
  /*
4586
   * 151122 per bug 103, set count_registrations = number active.
4587
   * Do same for queries
4588
   */
4589
0
  h->stat.count_registrations = rfapiApCountAll(bgp_default);
4590
0
  h->stat.count_queries = rfapi_monitor_count(NULL);
4591
4592
0
  rfapiRibShowResponsesSummaryClear();
4593
4594
0
  return CMD_SUCCESS;
4595
4596
0
notcfg:
4597
0
  vty_out(vty, "VNC is not configured.\n");
4598
0
  return CMD_WARNING;
4599
0
}
4600
4601
/************************************************************************
4602
 *    Add prefix with vrf
4603
 *
4604
 * add [vrf <vrf-name>] prefix <prefix>
4605
 *     [rd <value>] [label <value>] [local-preference <0-4294967295>]
4606
 ************************************************************************/
4607
void vnc_add_vrf_opener(struct bgp *bgp, struct rfapi_nve_group_cfg *rfg)
4608
0
{
4609
0
  if (rfg->rfd == NULL) { /* need new rfapi_handle */
4610
    /* based on rfapi_open */
4611
0
    struct rfapi_descriptor *rfd;
4612
4613
0
    rfd = XCALLOC(MTYPE_RFAPI_DESC,
4614
0
            sizeof(struct rfapi_descriptor));
4615
0
    rfd->bgp = bgp;
4616
0
    rfg->rfd = rfd;
4617
    /* leave most fields empty as will get from (dynamic) config
4618
     * when needed */
4619
0
    rfd->default_tunneltype_option.type = BGP_ENCAP_TYPE_MPLS;
4620
0
    rfd->cookie = rfg;
4621
0
    if (rfg->vn_prefix.family
4622
0
        && !CHECK_FLAG(rfg->flags, RFAPI_RFG_VPN_NH_SELF)) {
4623
0
      rfapiQprefix2Raddr(&rfg->vn_prefix, &rfd->vn_addr);
4624
0
    } else {
4625
0
      memset(&rfd->vn_addr, 0, sizeof(struct rfapi_ip_addr));
4626
0
      rfd->vn_addr.addr_family = AF_INET;
4627
0
      rfd->vn_addr.addr.v4 = bgp->router_id;
4628
0
    }
4629
0
    rfd->un_addr = rfd->vn_addr; /* sigh, need something in UN for
4630
            lookups */
4631
0
    vnc_zlog_debug_verbose("%s: Opening RFD for VRF %s", __func__,
4632
0
               rfg->name);
4633
0
    rfapi_init_and_open(bgp, rfd, rfg);
4634
0
  }
4635
0
}
4636
4637
/* NOTE: this functions parallels vnc_direct_add_rn_group_rd */
4638
static int vnc_add_vrf_prefix(struct vty *vty, const char *arg_vrf,
4639
            const char *arg_prefix,
4640
            const char *arg_rd,    /* optional */
4641
            const char *arg_label, /* optional */
4642
            const char *arg_pref)  /* optional */
4643
0
{
4644
0
  struct bgp *bgp;
4645
0
  struct rfapi_nve_group_cfg *rfg;
4646
0
  struct prefix pfx;
4647
0
  struct rfapi_ip_prefix rpfx;
4648
0
  uint32_t pref = 0;
4649
0
  struct rfapi_vn_option optary[3];
4650
0
  struct rfapi_vn_option *opt = NULL;
4651
0
  int cur_opt = 0;
4652
4653
0
  bgp = bgp_get_default(); /* assume main instance for now */
4654
0
  if (!bgp) {
4655
0
    vty_out(vty, "No BGP process is configured\n");
4656
0
    return CMD_WARNING_CONFIG_FAILED;
4657
0
  }
4658
0
  if (!bgp->rfapi || !bgp->rfapi_cfg) {
4659
0
    vty_out(vty, "VRF support not configured\n");
4660
0
    return CMD_WARNING_CONFIG_FAILED;
4661
0
  }
4662
4663
0
  rfg = bgp_rfapi_cfg_match_byname(bgp, arg_vrf, RFAPI_GROUP_CFG_VRF);
4664
  /* arg checks */
4665
0
  if (!rfg) {
4666
0
    vty_out(vty, "VRF \"%s\" appears not to be configured.\n",
4667
0
      arg_vrf);
4668
0
    return CMD_WARNING_CONFIG_FAILED;
4669
0
  }
4670
0
  if (!rfg->rt_export_list || !rfg->rfapi_import_table) {
4671
0
    vty_out(vty,
4672
0
      "VRF \"%s\" is missing RT import/export RT configuration.\n",
4673
0
      arg_vrf);
4674
0
    return CMD_WARNING_CONFIG_FAILED;
4675
0
  }
4676
0
  if (!rfg->rd.prefixlen && !arg_rd) {
4677
0
    vty_out(vty,
4678
0
      "VRF \"%s\" isn't configured with an RD, so RD must be provided.\n",
4679
0
      arg_vrf);
4680
0
    return CMD_WARNING_CONFIG_FAILED;
4681
0
  }
4682
0
  if (rfg->label > MPLS_LABEL_MAX && !arg_label) {
4683
0
    vty_out(vty,
4684
0
      "VRF \"%s\" isn't configured with a default labels, so a label must be provided.\n",
4685
0
      arg_vrf);
4686
0
    return CMD_WARNING_CONFIG_FAILED;
4687
0
  }
4688
0
  if (!str2prefix(arg_prefix, &pfx)) {
4689
0
    vty_out(vty, "Malformed prefix \"%s\"\n", arg_prefix);
4690
0
    return CMD_WARNING_CONFIG_FAILED;
4691
0
  }
4692
0
  rfapiQprefix2Rprefix(&pfx, &rpfx);
4693
0
  memset(optary, 0, sizeof(optary));
4694
0
  if (arg_rd) {
4695
0
    opt = &optary[cur_opt++];
4696
0
    opt->type = RFAPI_VN_OPTION_TYPE_INTERNAL_RD;
4697
    /* TODO: save RD format */
4698
0
    if (!str2prefix_rd(arg_rd, &opt->v.internal_rd)) {
4699
0
      vty_out(vty, "Malformed RD \"%s\"\n", arg_rd);
4700
0
      return CMD_WARNING_CONFIG_FAILED;
4701
0
    }
4702
0
  }
4703
0
  if (rfg->label <= MPLS_LABEL_MAX || arg_label) {
4704
0
    struct rfapi_l2address_option *l2o;
4705
0
    if (opt != NULL)
4706
0
      opt->next = &optary[cur_opt];
4707
0
    opt = &optary[cur_opt++];
4708
0
    opt->type = RFAPI_VN_OPTION_TYPE_L2ADDR;
4709
0
    l2o = &opt->v.l2addr;
4710
0
    if (arg_label) {
4711
0
      int32_t label;
4712
0
      label = strtoul(arg_label, NULL, 10);
4713
0
      l2o->label = label;
4714
0
    } else
4715
0
      l2o->label = rfg->label;
4716
0
  }
4717
0
  if (arg_pref) {
4718
0
    char *endptr = NULL;
4719
0
    pref = strtoul(arg_pref, &endptr, 10);
4720
0
    if (*endptr != '\0') {
4721
0
      vty_out(vty,
4722
0
        "%% Invalid local-preference value \"%s\"\n",
4723
0
        arg_pref);
4724
0
      return CMD_WARNING_CONFIG_FAILED;
4725
0
    }
4726
0
  }
4727
0
  rpfx.cost = 255 - (pref & 255);
4728
0
  vnc_add_vrf_opener(bgp, rfg);
4729
4730
0
  if (!rfapi_register(rfg->rfd, &rpfx, RFAPI_INFINITE_LIFETIME, NULL,
4731
0
          (cur_opt ? optary : NULL), RFAPI_REGISTER_ADD)) {
4732
0
    struct rfapi_next_hop_entry *head = NULL;
4733
0
    struct rfapi_next_hop_entry *tail = NULL;
4734
0
    struct rfapi_vn_option *vn_opt_new;
4735
4736
0
    vnc_zlog_debug_verbose("%s: rfapi_register succeeded",
4737
0
               __func__);
4738
4739
0
    if (bgp->rfapi->rfp_methods.local_cb) {
4740
0
      struct rfapi_descriptor *r =
4741
0
        (struct rfapi_descriptor *)rfg->rfd;
4742
0
      vn_opt_new = rfapi_vn_options_dup(opt);
4743
4744
0
      rfapiAddDeleteLocalRfpPrefix(&r->un_addr, &r->vn_addr,
4745
0
                 &rpfx, 1,
4746
0
                 RFAPI_INFINITE_LIFETIME,
4747
0
                 vn_opt_new, &head, &tail);
4748
0
      if (head) {
4749
0
        bgp->rfapi->flags |= RFAPI_INCALLBACK;
4750
0
        (*bgp->rfapi->rfp_methods.local_cb)(head,
4751
0
                    r->cookie);
4752
0
        bgp->rfapi->flags &= ~RFAPI_INCALLBACK;
4753
0
      }
4754
0
      head = tail = NULL;
4755
0
    }
4756
0
    vnc_zlog_debug_verbose(
4757
0
      "%s completed, count=%d/%d", __func__,
4758
0
      rfg->rfapi_import_table->local_count[AFI_IP],
4759
0
      rfg->rfapi_import_table->local_count[AFI_IP6]);
4760
0
    return CMD_SUCCESS;
4761
0
  }
4762
4763
0
  vnc_zlog_debug_verbose("%s: rfapi_register failed", __func__);
4764
0
  vty_out(vty, "Add failed.\n");
4765
0
  return CMD_WARNING_CONFIG_FAILED;
4766
0
}
4767
4768
DEFUN (add_vrf_prefix_rd_label_pref,
4769
       add_vrf_prefix_rd_label_pref_cmd,
4770
      "add vrf NAME prefix <A.B.C.D/M|X:X::X:X/M> [{rd ASN:NN_OR_IP-ADDRESS|label (0-1048575)|preference (0-4294967295)}]",
4771
       "Add\n"
4772
       "To a VRF\n"
4773
       "VRF name\n"
4774
       "Add/modify prefix related information\n"
4775
       "IPv4 prefix\n"
4776
       "IPv6 prefix\n"
4777
       "Override configured VRF Route Distinguisher\n"
4778
       "<as-number>:<number> or <ip-address>:<number>\n"
4779
       "Override configured VRF label\n"
4780
       "Label Value <0-1048575>\n"
4781
       "Set advertised local preference\n"
4782
       "local preference (higher=more preferred)\n")
4783
0
{
4784
0
  char *arg_vrf = argv[2]->arg;
4785
0
  char *arg_prefix = argv[4]->arg;
4786
0
  char *arg_rd = NULL;    /* optional */
4787
0
  char *arg_label = NULL; /* optional */
4788
0
  char *arg_pref = NULL;  /* optional */
4789
0
  int pargc = 5;
4790
0
  argc--; /* don't parse argument */
4791
0
  while (pargc < argc) {
4792
0
    switch (argv[pargc++]->arg[0]) {
4793
0
    case 'r':
4794
0
      arg_rd = argv[pargc]->arg;
4795
0
      break;
4796
0
    case 'l':
4797
0
      arg_label = argv[pargc]->arg;
4798
0
      break;
4799
0
    case 'p':
4800
0
      arg_pref = argv[pargc]->arg;
4801
0
      break;
4802
0
    default:
4803
0
      break;
4804
0
    }
4805
0
    pargc++;
4806
0
  }
4807
4808
0
  return vnc_add_vrf_prefix(vty, arg_vrf, arg_prefix, arg_rd, arg_label,
4809
0
          arg_pref);
4810
0
}
4811
4812
/************************************************************************
4813
 *    del prefix with vrf
4814
 *
4815
 * clear [vrf <vrf-name>] prefix <prefix> [rd <value>]
4816
 ************************************************************************/
4817
static int rfapi_cfg_group_it_count(struct rfapi_nve_group_cfg *rfg)
4818
0
{
4819
0
  int count = 0;
4820
4821
0
  if (rfg->rfapi_import_table == NULL)
4822
0
    return 0;
4823
4824
0
  afi_t afi = AFI_MAX;
4825
0
  while (afi-- > 0) {
4826
0
    count += rfg->rfapi_import_table->local_count[afi];
4827
0
  }
4828
0
  return count;
4829
0
}
4830
4831
void clear_vnc_vrf_closer(struct rfapi_nve_group_cfg *rfg)
4832
0
{
4833
0
  struct rfapi_descriptor *rfd = rfg->rfd;
4834
0
  afi_t afi;
4835
4836
0
  if (rfd == NULL)
4837
0
    return;
4838
  /* check if IT is empty */
4839
0
  for (afi = 0;
4840
0
       afi < AFI_MAX && rfg->rfapi_import_table->local_count[afi] == 0;
4841
0
       afi++)
4842
0
    ;
4843
4844
0
  if (afi == AFI_MAX) {
4845
0
    vnc_zlog_debug_verbose("%s: closing RFD for VRF %s", __func__,
4846
0
               rfg->name);
4847
0
    rfg->rfd = NULL;
4848
0
    rfapi_close(rfd);
4849
0
  } else {
4850
0
    vnc_zlog_debug_verbose(
4851
0
      "%s: VRF %s afi=%d count=%d", __func__, rfg->name, afi,
4852
0
      rfg->rfapi_import_table->local_count[afi]);
4853
0
  }
4854
0
}
4855
4856
static int vnc_clear_vrf(struct vty *vty, struct bgp *bgp, const char *arg_vrf,
4857
       const char *arg_prefix, /* NULL = all */
4858
       const char *arg_rd)     /* optional */
4859
0
{
4860
0
  struct rfapi_nve_group_cfg *rfg;
4861
0
  struct rfapi_local_reg_delete_arg cda;
4862
0
  int rc;
4863
0
  int start_count;
4864
4865
0
  if (bgp == NULL)
4866
0
    bgp = bgp_get_default(); /* assume main instance for now */
4867
0
  if (!bgp) {
4868
0
    vty_out(vty, "No BGP process is configured\n");
4869
0
    return CMD_WARNING;
4870
0
  }
4871
0
  if (!bgp->rfapi || !bgp->rfapi_cfg) {
4872
0
    vty_out(vty, "VRF support not configured\n");
4873
0
    return CMD_WARNING;
4874
0
  }
4875
0
  rfg = bgp_rfapi_cfg_match_byname(bgp, arg_vrf, RFAPI_GROUP_CFG_VRF);
4876
  /* arg checks */
4877
0
  if (!rfg) {
4878
0
    vty_out(vty, "VRF \"%s\" appears not to be configured.\n",
4879
0
      arg_vrf);
4880
0
    return CMD_WARNING;
4881
0
  }
4882
0
  rc = parse_deleter_args(vty, bgp, arg_prefix, NULL, NULL, NULL, NULL,
4883
0
        arg_rd, rfg, &cda);
4884
0
  if (rc != CMD_SUCCESS) /* parse error */
4885
0
    return rc;
4886
4887
0
  start_count = rfapi_cfg_group_it_count(rfg);
4888
0
  clear_vnc_prefix(&cda);
4889
0
  vty_out(vty, "Cleared %u out of %d prefixes.\n", cda.pfx_count,
4890
0
    start_count);
4891
0
  print_cleared_stats(&cda); /* frees lists in cda */
4892
0
  return CMD_SUCCESS;
4893
0
}
4894
4895
DEFUN (clear_vrf_prefix_rd,
4896
       clear_vrf_prefix_rd_cmd,
4897
       "clear vrf NAME [prefix <A.B.C.D/M|X:X::X:X/M>] [rd ASN:NN_OR_IP-ADDRESS]",
4898
       "Clear stored data\n"
4899
       "From a VRF\n"
4900
       "VRF name\n"
4901
       "Prefix related information\n"
4902
       "IPv4 prefix\n"
4903
       "IPv6 prefix\n"
4904
       "Specific VRF Route Distinguisher\n"
4905
       "<as-number>:<number> or <ip-address>:<number>\n")
4906
0
{
4907
0
  char *arg_vrf = argv[2]->arg;
4908
0
  char *arg_prefix = NULL; /* optional */
4909
0
  char *arg_rd = NULL;     /* optional */
4910
0
  int pargc = 3;
4911
0
  argc--; /* don't check parameter */
4912
0
  while (pargc < argc) {
4913
0
    switch (argv[pargc++]->arg[0]) {
4914
0
    case 'r':
4915
0
      arg_rd = argv[pargc]->arg;
4916
0
      break;
4917
0
    case 'p':
4918
0
      arg_prefix = argv[pargc]->arg;
4919
0
      break;
4920
0
    default:
4921
0
      break;
4922
0
    }
4923
0
    pargc++;
4924
0
  }
4925
0
  return vnc_clear_vrf(vty, NULL, arg_vrf, arg_prefix, arg_rd);
4926
0
}
4927
4928
DEFUN (clear_vrf_all,
4929
       clear_vrf_all_cmd,
4930
       "clear vrf NAME all",
4931
       "Clear stored data\n"
4932
       "From a VRF\n"
4933
       "VRF name\n"
4934
       "All prefixes\n")
4935
0
{
4936
0
  char *arg_vrf = argv[2]->arg;
4937
0
  return vnc_clear_vrf(vty, NULL, arg_vrf, NULL, NULL);
4938
0
}
4939
4940
void rfapi_vty_init(void)
4941
0
{
4942
0
  install_element(ENABLE_NODE, &add_vnc_prefix_cost_life_lnh_cmd);
4943
0
  install_element(ENABLE_NODE, &add_vnc_prefix_life_cost_lnh_cmd);
4944
0
  install_element(ENABLE_NODE, &add_vnc_prefix_cost_lnh_cmd);
4945
0
  install_element(ENABLE_NODE, &add_vnc_prefix_life_lnh_cmd);
4946
0
  install_element(ENABLE_NODE, &add_vnc_prefix_lnh_cmd);
4947
4948
0
  install_element(ENABLE_NODE, &add_vnc_prefix_cost_life_cmd);
4949
0
  install_element(ENABLE_NODE, &add_vnc_prefix_life_cost_cmd);
4950
0
  install_element(ENABLE_NODE, &add_vnc_prefix_cost_cmd);
4951
0
  install_element(ENABLE_NODE, &add_vnc_prefix_life_cmd);
4952
0
  install_element(ENABLE_NODE, &add_vnc_prefix_cmd);
4953
4954
0
  install_element(ENABLE_NODE, &add_vnc_mac_vni_prefix_cost_life_cmd);
4955
0
  install_element(ENABLE_NODE, &add_vnc_mac_vni_prefix_life_cmd);
4956
0
  install_element(ENABLE_NODE, &add_vnc_mac_vni_prefix_cost_cmd);
4957
0
  install_element(ENABLE_NODE, &add_vnc_mac_vni_prefix_cmd);
4958
0
  install_element(ENABLE_NODE, &add_vnc_mac_vni_cost_life_cmd);
4959
0
  install_element(ENABLE_NODE, &add_vnc_mac_vni_cost_cmd);
4960
0
  install_element(ENABLE_NODE, &add_vnc_mac_vni_life_cmd);
4961
0
  install_element(ENABLE_NODE, &add_vnc_mac_vni_cmd);
4962
4963
0
  install_element(ENABLE_NODE, &add_vrf_prefix_rd_label_pref_cmd);
4964
4965
0
  install_element(ENABLE_NODE, &clear_vnc_nve_all_cmd);
4966
0
  install_element(ENABLE_NODE, &clear_vnc_nve_vn_un_cmd);
4967
0
  install_element(ENABLE_NODE, &clear_vnc_nve_un_vn_cmd);
4968
0
  install_element(ENABLE_NODE, &clear_vnc_nve_vn_cmd);
4969
0
  install_element(ENABLE_NODE, &clear_vnc_nve_un_cmd);
4970
4971
0
  install_element(ENABLE_NODE, &clear_vnc_prefix_vn_un_cmd);
4972
0
  install_element(ENABLE_NODE, &clear_vnc_prefix_un_vn_cmd);
4973
0
  install_element(ENABLE_NODE, &clear_vnc_prefix_un_cmd);
4974
0
  install_element(ENABLE_NODE, &clear_vnc_prefix_vn_cmd);
4975
0
  install_element(ENABLE_NODE, &clear_vnc_prefix_all_cmd);
4976
4977
0
  install_element(ENABLE_NODE, &clear_vnc_mac_vn_un_cmd);
4978
0
  install_element(ENABLE_NODE, &clear_vnc_mac_un_vn_cmd);
4979
0
  install_element(ENABLE_NODE, &clear_vnc_mac_un_cmd);
4980
0
  install_element(ENABLE_NODE, &clear_vnc_mac_vn_cmd);
4981
0
  install_element(ENABLE_NODE, &clear_vnc_mac_all_cmd);
4982
4983
0
  install_element(ENABLE_NODE, &clear_vnc_mac_vn_un_prefix_cmd);
4984
0
  install_element(ENABLE_NODE, &clear_vnc_mac_un_vn_prefix_cmd);
4985
0
  install_element(ENABLE_NODE, &clear_vnc_mac_un_prefix_cmd);
4986
0
  install_element(ENABLE_NODE, &clear_vnc_mac_vn_prefix_cmd);
4987
0
  install_element(ENABLE_NODE, &clear_vnc_mac_all_prefix_cmd);
4988
4989
0
  install_element(ENABLE_NODE, &clear_vrf_prefix_rd_cmd);
4990
0
  install_element(ENABLE_NODE, &clear_vrf_all_cmd);
4991
4992
0
  install_element(ENABLE_NODE, &vnc_clear_counters_cmd);
4993
4994
0
  install_element(VIEW_NODE, &vnc_show_summary_cmd);
4995
0
  install_element(VIEW_NODE, &vnc_show_nves_cmd);
4996
0
  install_element(VIEW_NODE, &vnc_show_nves_ptct_cmd);
4997
4998
0
  install_element(VIEW_NODE, &vnc_show_registrations_pfx_cmd);
4999
0
  install_element(VIEW_NODE, &vnc_show_registrations_some_pfx_cmd);
5000
0
  install_element(VIEW_NODE, &vnc_show_responses_pfx_cmd);
5001
0
  install_element(VIEW_NODE, &vnc_show_responses_some_pfx_cmd);
5002
0
  install_element(VIEW_NODE, &show_vnc_queries_pfx_cmd);
5003
0
}