Coverage Report

Created: 2026-05-04 06:53

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/frr/bgpd/bgp_vpn.c
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/* VPN Related functions
3
 * Copyright (C) 2017 6WIND
4
 *
5
 * This file is part of FRRouting
6
 */
7
8
#include <zebra.h>
9
#include "command.h"
10
#include "prefix.h"
11
#include "lib/json.h"
12
#include "lib/printfrr.h"
13
14
#include "bgpd/bgpd.h"
15
#include "bgpd/bgp_route.h"
16
#include "bgpd/bgp_table.h"
17
#include "bgpd/bgp_attr.h"
18
#include "bgpd/bgp_mplsvpn.h"
19
#include "bgpd/bgp_vpn.h"
20
#include "bgpd/bgp_updgrp.h"
21
22
int show_adj_route_vpn(struct vty *vty, struct peer *peer,
23
           struct prefix_rd *prd, afi_t afi, safi_t safi,
24
           bool use_json)
25
0
{
26
0
  struct bgp *bgp;
27
0
  struct bgp_table *table;
28
0
  struct bgp_dest *dest;
29
0
  struct bgp_dest *rm;
30
0
  int rd_header;
31
0
  int header = 1;
32
0
  json_object *json = NULL;
33
0
  json_object *json_scode = NULL;
34
0
  json_object *json_ocode = NULL;
35
0
  json_object *json_adv = NULL;
36
0
  json_object *json_routes = NULL;
37
0
  char rd_str[BUFSIZ];
38
0
  unsigned long output_count = 0;
39
40
0
  bgp = bgp_get_default();
41
0
  if (bgp == NULL) {
42
0
    if (!use_json)
43
0
      vty_out(vty, "No BGP process is configured\n");
44
0
    else
45
0
      vty_out(vty, "{}\n");
46
0
    return CMD_WARNING;
47
0
  }
48
49
0
  if (use_json) {
50
0
    json_scode = json_object_new_object();
51
0
    json_ocode = json_object_new_object();
52
0
    json = json_object_new_object();
53
0
    json_adv = json_object_new_object();
54
55
0
    json_object_string_add(json_scode, "suppressed", "s");
56
0
    json_object_string_add(json_scode, "damped", "d");
57
0
    json_object_string_add(json_scode, "history", "h");
58
0
    json_object_string_add(json_scode, "valid", "*");
59
0
    json_object_string_add(json_scode, "best", ">");
60
0
    json_object_string_add(json_scode, "internal", "i");
61
62
0
    json_object_string_add(json_ocode, "igp", "i");
63
0
    json_object_string_add(json_ocode, "egp", "e");
64
0
    json_object_string_add(json_ocode, "incomplete", "?");
65
0
  }
66
67
0
  for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
68
0
       dest = bgp_route_next(dest)) {
69
0
    const struct prefix *dest_p = bgp_dest_get_prefix(dest);
70
71
0
    if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
72
0
      continue;
73
74
0
    table = bgp_dest_get_bgp_table_info(dest);
75
0
    if (table == NULL)
76
0
      continue;
77
78
    /*
79
     * Initialize variables for each RD
80
     * All prefixes under an RD is aggregated within "json_routes"
81
     */
82
0
    rd_header = 1;
83
0
    memset(rd_str, 0, sizeof(rd_str));
84
0
    json_routes = NULL;
85
86
0
    for (rm = bgp_table_top(table); rm; rm = bgp_route_next(rm)) {
87
0
      struct bgp_adj_out *adj = NULL;
88
0
      struct attr *attr = NULL;
89
0
      struct peer_af *paf = NULL;
90
91
0
      RB_FOREACH (adj, bgp_adj_out_rb, &rm->adj_out)
92
0
        SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
93
0
          if (paf->peer != peer || !adj->attr)
94
0
            continue;
95
96
0
          attr = adj->attr;
97
0
          break;
98
0
      }
99
100
0
      if (bgp_dest_get_bgp_path_info(rm) == NULL)
101
0
        continue;
102
103
0
      if (!attr)
104
0
        continue;
105
106
0
      if (header) {
107
0
        if (use_json) {
108
0
          json_object_int_add(
109
0
            json, "bgpTableVersion", 0);
110
0
          json_object_string_addf(
111
0
            json, "bgpLocalRouterId",
112
0
            "%pI4", &bgp->router_id);
113
0
          json_object_int_add(
114
0
            json,
115
0
            "defaultLocPrf",
116
0
            bgp->default_local_pref);
117
0
          json_object_int_add(
118
0
            json, "localAS",
119
0
            bgp->as);
120
0
          json_object_object_add(json,
121
0
                     "bgpStatusCodes",
122
0
                     json_scode);
123
0
          json_object_object_add(json,
124
0
                     "bgpOriginCodes",
125
0
                     json_ocode);
126
0
        } else {
127
0
          vty_out(vty,
128
0
            "BGP table version is 0, local router ID is %pI4\n",
129
0
            &bgp->router_id);
130
0
          vty_out(vty, "Default local pref %u, ",
131
0
            bgp->default_local_pref);
132
0
          vty_out(vty, "local AS %u\n", bgp->as);
133
0
          vty_out(vty,
134
0
            "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
135
0
          vty_out(vty,
136
0
            "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n");
137
0
          vty_out(vty, V4_HEADER);
138
0
        }
139
0
        header = 0;
140
0
      }
141
142
0
      if (rd_header) {
143
0
        uint16_t type;
144
0
        struct rd_as rd_as = {0};
145
0
        struct rd_ip rd_ip = {0};
146
0
#ifdef ENABLE_BGP_VNC
147
0
        struct rd_vnc_eth rd_vnc_eth = {0};
148
0
#endif
149
0
        const uint8_t *pnt;
150
151
0
        pnt = dest_p->u.val;
152
153
        /* Decode RD type. */
154
0
        type = decode_rd_type(pnt);
155
        /* Decode RD value. */
156
0
        if (type == RD_TYPE_AS)
157
0
          decode_rd_as(pnt + 2, &rd_as);
158
0
        else if (type == RD_TYPE_AS4)
159
0
          decode_rd_as4(pnt + 2, &rd_as);
160
0
        else if (type == RD_TYPE_IP)
161
0
          decode_rd_ip(pnt + 2, &rd_ip);
162
0
#ifdef ENABLE_BGP_VNC
163
0
        else if (type == RD_TYPE_VNC_ETH)
164
0
          decode_rd_vnc_eth(pnt, &rd_vnc_eth);
165
0
#endif
166
0
        if (use_json) {
167
0
          json_routes = json_object_new_object();
168
169
0
          if (type == RD_TYPE_AS
170
0
              || type == RD_TYPE_AS4)
171
0
            snprintf(rd_str, sizeof(rd_str),
172
0
               "%u:%d", rd_as.as,
173
0
               rd_as.val);
174
0
          else if (type == RD_TYPE_IP)
175
0
            snprintfrr(rd_str,
176
0
                 sizeof(rd_str),
177
0
                 "%pI4:%d", &rd_ip.ip,
178
0
                 rd_ip.val);
179
0
          json_object_string_add(
180
0
            json_routes,
181
0
            "rd", rd_str);
182
0
        } else {
183
0
          vty_out(vty, "Route Distinguisher: ");
184
185
0
          if (type == RD_TYPE_AS
186
0
              || type == RD_TYPE_AS4)
187
0
            vty_out(vty, "%u:%d", rd_as.as,
188
0
              rd_as.val);
189
0
          else if (type == RD_TYPE_IP)
190
0
            vty_out(vty, "%pI4:%d",
191
0
              &rd_ip.ip, rd_ip.val);
192
0
#ifdef ENABLE_BGP_VNC
193
0
          else if (type == RD_TYPE_VNC_ETH)
194
0
            vty_out(vty,
195
0
              "%u:%02x:%02x:%02x:%02x:%02x:%02x",
196
0
              rd_vnc_eth.local_nve_id,
197
0
              rd_vnc_eth.macaddr
198
0
                .octet[0],
199
0
              rd_vnc_eth.macaddr
200
0
                .octet[1],
201
0
              rd_vnc_eth.macaddr
202
0
                .octet[2],
203
0
              rd_vnc_eth.macaddr
204
0
                .octet[3],
205
0
              rd_vnc_eth.macaddr
206
0
                .octet[4],
207
0
              rd_vnc_eth.macaddr
208
0
                .octet[5]);
209
0
#endif
210
211
0
          vty_out(vty, "\n");
212
0
        }
213
0
        rd_header = 0;
214
0
      }
215
0
      route_vty_out_tmp(vty, rm, bgp_dest_get_prefix(rm),
216
0
            attr, safi, use_json, json_routes,
217
0
            false);
218
0
      output_count++;
219
0
    }
220
221
0
    if (use_json && json_routes)
222
0
      json_object_object_add(json_adv, rd_str, json_routes);
223
0
  }
224
225
0
  if (use_json) {
226
0
    json_object_object_add(json, "advertisedRoutes", json_adv);
227
0
    json_object_int_add(json,
228
0
      "totalPrefixCounter", output_count);
229
0
    vty_json(vty, json);
230
0
  } else
231
0
    vty_out(vty, "\nTotal number of prefixes %ld\n", output_count);
232
233
0
  return CMD_SUCCESS;
234
0
}