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