]>
Commit | Line | Data |
---|---|---|
718e3744 | 1 | /* MPLS-VPN |
896014f4 DL |
2 | * Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org> |
3 | * | |
4 | * This file is part of GNU Zebra. | |
5 | * | |
6 | * GNU Zebra 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 | * GNU Zebra 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 | */ | |
718e3744 | 20 | |
21 | #include <zebra.h> | |
22 | ||
23 | #include "command.h" | |
24 | #include "prefix.h" | |
25 | #include "log.h" | |
26 | #include "memory.h" | |
27 | #include "stream.h" | |
3f9c7369 | 28 | #include "queue.h" |
039f3a34 | 29 | #include "filter.h" |
856ca177 | 30 | #include "lib/json.h" |
9bedbb1e | 31 | |
718e3744 | 32 | #include "bgpd/bgpd.h" |
33 | #include "bgpd/bgp_table.h" | |
34 | #include "bgpd/bgp_route.h" | |
35 | #include "bgpd/bgp_attr.h" | |
9bedbb1e | 36 | #include "bgpd/bgp_label.h" |
718e3744 | 37 | #include "bgpd/bgp_mplsvpn.h" |
48a5452b | 38 | #include "bgpd/bgp_packet.h" |
3f227172 | 39 | #include "bgpd/bgp_vty.h" |
784d3a42 | 40 | #include "bgpd/bgp_vpn.h" |
718e3744 | 41 | |
65efcfce | 42 | #if ENABLE_BGP_VNC |
f8b6f499 | 43 | #include "bgpd/rfapi/rfapi_backend.h" |
65efcfce LB |
44 | #endif |
45 | ||
d62a17ae | 46 | extern int argv_find_and_parse_vpnvx(struct cmd_token **argv, int argc, |
47 | int *index, afi_t *afi) | |
3f227172 | 48 | { |
d62a17ae | 49 | int ret = 0; |
50 | if (argv_find(argv, argc, "vpnv4", index)) { | |
51 | ret = 1; | |
52 | if (afi) | |
53 | *afi = AFI_IP; | |
54 | } else if (argv_find(argv, argc, "vpnv6", index)) { | |
55 | ret = 1; | |
56 | if (afi) | |
57 | *afi = AFI_IP6; | |
58 | } | |
59 | return ret; | |
3f227172 PG |
60 | } |
61 | ||
d62a17ae | 62 | u_int32_t decode_label(mpls_label_t *label_pnt) |
718e3744 | 63 | { |
d62a17ae | 64 | u_int32_t l; |
65 | u_char *pnt = (u_char *)label_pnt; | |
718e3744 | 66 | |
d62a17ae | 67 | l = ((u_int32_t)*pnt++ << 12); |
68 | l |= (u_int32_t)*pnt++ << 4; | |
69 | l |= (u_int32_t)((*pnt & 0xf0) >> 4); | |
70 | return l; | |
718e3744 | 71 | } |
72 | ||
d62a17ae | 73 | void encode_label(mpls_label_t label, mpls_label_t *label_pnt) |
65efcfce | 74 | { |
d62a17ae | 75 | u_char *pnt = (u_char *)label_pnt; |
76 | if (pnt == NULL) | |
77 | return; | |
78 | *pnt++ = (label >> 12) & 0xff; | |
79 | *pnt++ = (label >> 4) & 0xff; | |
80 | *pnt++ = ((label << 4) + 1) & 0xff; /* S=1 */ | |
65efcfce LB |
81 | } |
82 | ||
d62a17ae | 83 | int bgp_nlri_parse_vpn(struct peer *peer, struct attr *attr, |
84 | struct bgp_nlri *packet) | |
718e3744 | 85 | { |
d62a17ae | 86 | u_char *pnt; |
87 | u_char *lim; | |
88 | struct prefix p; | |
89 | int psize = 0; | |
90 | int prefixlen; | |
91 | u_int16_t type; | |
92 | struct rd_as rd_as; | |
93 | struct rd_ip rd_ip; | |
94 | struct prefix_rd prd; | |
95 | mpls_label_t label; | |
96 | afi_t afi; | |
97 | safi_t safi; | |
98 | int addpath_encoded; | |
99 | u_int32_t addpath_id; | |
100 | ||
101 | /* Check peer status. */ | |
102 | if (peer->status != Established) | |
103 | return 0; | |
104 | ||
105 | /* Make prefix_rd */ | |
106 | prd.family = AF_UNSPEC; | |
107 | prd.prefixlen = 64; | |
108 | ||
109 | pnt = packet->nlri; | |
110 | lim = pnt + packet->length; | |
111 | afi = packet->afi; | |
112 | safi = packet->safi; | |
113 | addpath_id = 0; | |
114 | ||
115 | addpath_encoded = | |
116 | (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV) | |
117 | && CHECK_FLAG(peer->af_cap[afi][safi], | |
118 | PEER_CAP_ADDPATH_AF_TX_RCV)); | |
718e3744 | 119 | |
50905aa2 | 120 | #define VPN_PREFIXLEN_MIN_BYTES (3 + 8) /* label + RD */ |
d62a17ae | 121 | for (; pnt < lim; pnt += psize) { |
122 | /* Clear prefix structure. */ | |
123 | memset(&p, 0, sizeof(struct prefix)); | |
124 | ||
125 | if (addpath_encoded) { | |
126 | ||
127 | /* When packet overflow occurs return immediately. */ | |
128 | if (pnt + BGP_ADDPATH_ID_LEN > lim) | |
129 | return -1; | |
130 | ||
131 | addpath_id = ntohl(*((uint32_t *)pnt)); | |
132 | pnt += BGP_ADDPATH_ID_LEN; | |
133 | } | |
134 | ||
135 | /* Fetch prefix length. */ | |
136 | prefixlen = *pnt++; | |
137 | p.family = afi2family(packet->afi); | |
138 | psize = PSIZE(prefixlen); | |
139 | ||
140 | if (prefixlen < VPN_PREFIXLEN_MIN_BYTES * 8) { | |
141 | zlog_err( | |
142 | "%s [Error] Update packet error / VPN (prefix length %d less than VPN min length)", | |
143 | peer->host, prefixlen); | |
144 | return -1; | |
145 | } | |
146 | ||
147 | /* sanity check against packet data */ | |
148 | if ((pnt + psize) > lim) { | |
149 | zlog_err( | |
150 | "%s [Error] Update packet error / VPN (prefix length %d exceeds packet size %u)", | |
151 | peer->host, prefixlen, (uint)(lim - pnt)); | |
152 | return -1; | |
153 | } | |
154 | ||
155 | /* sanity check against storage for the IP address portion */ | |
156 | if ((psize - VPN_PREFIXLEN_MIN_BYTES) > (ssize_t)sizeof(p.u)) { | |
157 | zlog_err( | |
158 | "%s [Error] Update packet error / VPN (psize %d exceeds storage size %zu)", | |
159 | peer->host, | |
160 | prefixlen - VPN_PREFIXLEN_MIN_BYTES * 8, | |
161 | sizeof(p.u)); | |
162 | return -1; | |
163 | } | |
164 | ||
165 | /* Sanity check against max bitlen of the address family */ | |
166 | if ((psize - VPN_PREFIXLEN_MIN_BYTES) > prefix_blen(&p)) { | |
167 | zlog_err( | |
168 | "%s [Error] Update packet error / VPN (psize %d exceeds family (%u) max byte len %u)", | |
169 | peer->host, | |
170 | prefixlen - VPN_PREFIXLEN_MIN_BYTES * 8, | |
171 | p.family, prefix_blen(&p)); | |
172 | return -1; | |
173 | } | |
174 | ||
175 | /* Copy label to prefix. */ | |
176 | memcpy(&label, pnt, BGP_LABEL_BYTES); | |
177 | bgp_set_valid_label(&label); | |
178 | ||
179 | /* Copy routing distinguisher to rd. */ | |
180 | memcpy(&prd.val, pnt + BGP_LABEL_BYTES, 8); | |
181 | ||
182 | /* Decode RD type. */ | |
183 | type = decode_rd_type(pnt + BGP_LABEL_BYTES); | |
184 | ||
185 | switch (type) { | |
186 | case RD_TYPE_AS: | |
187 | decode_rd_as(pnt + 5, &rd_as); | |
188 | break; | |
189 | ||
190 | case RD_TYPE_AS4: | |
191 | decode_rd_as4(pnt + 5, &rd_as); | |
192 | break; | |
193 | ||
194 | case RD_TYPE_IP: | |
195 | decode_rd_ip(pnt + 5, &rd_ip); | |
196 | break; | |
fe770c88 | 197 | |
65efcfce | 198 | #if ENABLE_BGP_VNC |
d62a17ae | 199 | case RD_TYPE_VNC_ETH: |
200 | break; | |
65efcfce LB |
201 | #endif |
202 | ||
d62a17ae | 203 | default: |
204 | zlog_err("Unknown RD type %d", type); | |
205 | break; /* just report */ | |
206 | } | |
207 | ||
208 | p.prefixlen = | |
209 | prefixlen | |
210 | - VPN_PREFIXLEN_MIN_BYTES * 8; /* exclude label & RD */ | |
211 | memcpy(&p.u.prefix, pnt + VPN_PREFIXLEN_MIN_BYTES, | |
212 | psize - VPN_PREFIXLEN_MIN_BYTES); | |
213 | ||
214 | if (attr) { | |
215 | bgp_update(peer, &p, addpath_id, attr, packet->afi, | |
216 | SAFI_MPLS_VPN, ZEBRA_ROUTE_BGP, | |
b57ba6d2 | 217 | BGP_ROUTE_NORMAL, &prd, &label, 1, 0, NULL); |
d62a17ae | 218 | } else { |
219 | bgp_withdraw(peer, &p, addpath_id, attr, packet->afi, | |
220 | SAFI_MPLS_VPN, ZEBRA_ROUTE_BGP, | |
b57ba6d2 | 221 | BGP_ROUTE_NORMAL, &prd, &label, 1, NULL); |
d62a17ae | 222 | } |
223 | } | |
224 | /* Packet length consistency check. */ | |
225 | if (pnt != lim) { | |
226 | zlog_err( | |
227 | "%s [Error] Update packet error / VPN (%zu data remaining after parsing)", | |
228 | peer->host, lim - pnt); | |
229 | return -1; | |
230 | } | |
231 | ||
232 | return 0; | |
50905aa2 | 233 | #undef VPN_PREFIXLEN_MIN_BYTES |
718e3744 | 234 | } |
235 | ||
718e3744 | 236 | /* For testing purpose, static route of MPLS-VPN. */ |
237 | DEFUN (vpnv4_network, | |
238 | vpnv4_network_cmd, | |
d114b977 | 239 | "network A.B.C.D/M rd ASN:NN_OR_IP-ADDRESS:NN <tag|label> (0-1048575)", |
718e3744 | 240 | "Specify a network to announce via BGP\n" |
0c7b1b01 | 241 | "IPv4 prefix\n" |
718e3744 | 242 | "Specify Route Distinguisher\n" |
243 | "VPN Route Distinguisher\n" | |
fb1d2a2d LB |
244 | "VPN NLRI label (tag)\n" |
245 | "VPN NLRI label (tag)\n" | |
246 | "Label value\n") | |
718e3744 | 247 | { |
d62a17ae | 248 | int idx_ipv4_prefixlen = 1; |
249 | int idx_ext_community = 3; | |
250 | int idx_label = 5; | |
251 | return bgp_static_set_safi( | |
252 | AFI_IP, SAFI_MPLS_VPN, vty, argv[idx_ipv4_prefixlen]->arg, | |
253 | argv[idx_ext_community]->arg, argv[idx_label]->arg, NULL, 0, | |
254 | NULL, NULL, NULL, NULL); | |
137446f9 LB |
255 | } |
256 | ||
257 | DEFUN (vpnv4_network_route_map, | |
258 | vpnv4_network_route_map_cmd, | |
d114b977 | 259 | "network A.B.C.D/M rd ASN:NN_OR_IP-ADDRESS:NN <tag|label> (0-1048575) route-map WORD", |
137446f9 | 260 | "Specify a network to announce via BGP\n" |
0c7b1b01 | 261 | "IPv4 prefix\n" |
137446f9 LB |
262 | "Specify Route Distinguisher\n" |
263 | "VPN Route Distinguisher\n" | |
fb1d2a2d LB |
264 | "VPN NLRI label (tag)\n" |
265 | "VPN NLRI label (tag)\n" | |
266 | "Label value\n" | |
137446f9 LB |
267 | "route map\n" |
268 | "route map name\n") | |
269 | { | |
d62a17ae | 270 | int idx_ipv4_prefixlen = 1; |
271 | int idx_ext_community = 3; | |
272 | int idx_label = 5; | |
273 | int idx_word_2 = 7; | |
274 | return bgp_static_set_safi( | |
275 | AFI_IP, SAFI_MPLS_VPN, vty, argv[idx_ipv4_prefixlen]->arg, | |
276 | argv[idx_ext_community]->arg, argv[idx_label]->arg, | |
277 | argv[idx_word_2]->arg, 0, NULL, NULL, NULL, NULL); | |
718e3744 | 278 | } |
279 | ||
280 | /* For testing purpose, static route of MPLS-VPN. */ | |
281 | DEFUN (no_vpnv4_network, | |
282 | no_vpnv4_network_cmd, | |
d114b977 | 283 | "no network A.B.C.D/M rd ASN:NN_OR_IP-ADDRESS:NN <tag|label> (0-1048575)", |
718e3744 | 284 | NO_STR |
285 | "Specify a network to announce via BGP\n" | |
0c7b1b01 | 286 | "IPv4 prefix\n" |
718e3744 | 287 | "Specify Route Distinguisher\n" |
288 | "VPN Route Distinguisher\n" | |
fb1d2a2d LB |
289 | "VPN NLRI label (tag)\n" |
290 | "VPN NLRI label (tag)\n" | |
291 | "Label value\n") | |
718e3744 | 292 | { |
d62a17ae | 293 | int idx_ipv4_prefixlen = 2; |
294 | int idx_ext_community = 4; | |
295 | int idx_label = 6; | |
296 | return bgp_static_unset_safi(AFI_IP, SAFI_MPLS_VPN, vty, | |
297 | argv[idx_ipv4_prefixlen]->arg, | |
298 | argv[idx_ext_community]->arg, | |
299 | argv[idx_label]->arg, 0, NULL, NULL, NULL); | |
718e3744 | 300 | } |
301 | ||
c286be96 LX |
302 | DEFUN (vpnv6_network, |
303 | vpnv6_network_cmd, | |
d114b977 | 304 | "network X:X::X:X/M rd ASN:NN_OR_IP-ADDRESS:NN <tag|label> (0-1048575) [route-map WORD]", |
c286be96 LX |
305 | "Specify a network to announce via BGP\n" |
306 | "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n" | |
307 | "Specify Route Distinguisher\n" | |
308 | "VPN Route Distinguisher\n" | |
fb1d2a2d LB |
309 | "VPN NLRI label (tag)\n" |
310 | "VPN NLRI label (tag)\n" | |
311 | "Label value\n" | |
11daee81 DS |
312 | "route map\n" |
313 | "route map name\n") | |
c286be96 | 314 | { |
d62a17ae | 315 | int idx_ipv6_prefix = 1; |
316 | int idx_ext_community = 3; | |
317 | int idx_label = 5; | |
318 | int idx_word_2 = 7; | |
319 | if (argc == 8) | |
320 | return bgp_static_set_safi( | |
321 | AFI_IP6, SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg, | |
322 | argv[idx_ext_community]->arg, argv[idx_label]->arg, | |
323 | argv[idx_word_2]->arg, 0, NULL, NULL, NULL, NULL); | |
324 | else | |
325 | return bgp_static_set_safi( | |
326 | AFI_IP6, SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg, | |
327 | argv[idx_ext_community]->arg, argv[idx_label]->arg, | |
328 | NULL, 0, NULL, NULL, NULL, NULL); | |
c286be96 LX |
329 | } |
330 | ||
331 | /* For testing purpose, static route of MPLS-VPN. */ | |
332 | DEFUN (no_vpnv6_network, | |
333 | no_vpnv6_network_cmd, | |
d114b977 | 334 | "no network X:X::X:X/M rd ASN:NN_OR_IP-ADDRESS:NN <tag|label> (0-1048575)", |
c286be96 LX |
335 | NO_STR |
336 | "Specify a network to announce via BGP\n" | |
337 | "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n" | |
338 | "Specify Route Distinguisher\n" | |
339 | "VPN Route Distinguisher\n" | |
fb1d2a2d LB |
340 | "VPN NLRI label (tag)\n" |
341 | "VPN NLRI label (tag)\n" | |
342 | "Label value\n") | |
c286be96 | 343 | { |
d62a17ae | 344 | int idx_ipv6_prefix = 2; |
345 | int idx_ext_community = 4; | |
346 | int idx_label = 6; | |
347 | return bgp_static_unset_safi(AFI_IP6, SAFI_MPLS_VPN, vty, | |
348 | argv[idx_ipv6_prefix]->arg, | |
349 | argv[idx_ext_community]->arg, | |
350 | argv[idx_label]->arg, 0, NULL, NULL, NULL); | |
c286be96 LX |
351 | } |
352 | ||
d62a17ae | 353 | int bgp_show_mpls_vpn(struct vty *vty, afi_t afi, struct prefix_rd *prd, |
354 | enum bgp_show_type type, void *output_arg, int tags, | |
355 | u_char use_json) | |
718e3744 | 356 | { |
d62a17ae | 357 | struct bgp *bgp; |
358 | struct bgp_table *table; | |
d62a17ae | 359 | |
360 | bgp = bgp_get_default(); | |
361 | if (bgp == NULL) { | |
362 | if (!use_json) | |
363 | vty_out(vty, "No BGP process is configured\n"); | |
16307668 RW |
364 | else |
365 | vty_out(vty, "{}\n"); | |
d62a17ae | 366 | return CMD_WARNING; |
367 | } | |
1ae44dfc | 368 | table = bgp->rib[afi][SAFI_MPLS_VPN]; |
a4d82a8a PZ |
369 | return bgp_show_table_rd(vty, bgp, SAFI_MPLS_VPN, table, prd, type, |
370 | output_arg, use_json); | |
718e3744 | 371 | } |
372 | ||
4f280b15 LB |
373 | DEFUN (show_bgp_ip_vpn_all_rd, |
374 | show_bgp_ip_vpn_all_rd_cmd, | |
d114b977 | 375 | "show bgp "BGP_AFI_CMD_STR" vpn all [rd ASN:NN_OR_IP-ADDRESS:NN] [json]", |
e3e29b32 LB |
376 | SHOW_STR |
377 | BGP_STR | |
05e588f4 | 378 | BGP_VPNVX_HELP_STR |
e3e29b32 | 379 | "Display VPN NLRI specific information\n" |
af8528fa | 380 | "Display VPN NLRI specific information\n" |
e3e29b32 LB |
381 | "Display information for a route distinguisher\n" |
382 | "VPN Route Distinguisher\n" | |
383 | JSON_STR) | |
384 | { | |
d62a17ae | 385 | int ret; |
386 | struct prefix_rd prd; | |
387 | afi_t afi; | |
388 | int idx = 0; | |
389 | ||
390 | if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) { | |
3d7c4cd7 | 391 | if (argv_find(argv, argc, "rd", &idx)) { |
a4d82a8a | 392 | ret = str2prefix_rd(argv[idx + 1]->arg, &prd); |
d62a17ae | 393 | if (!ret) { |
394 | vty_out(vty, | |
395 | "%% Malformed Route Distinguisher\n"); | |
396 | return CMD_WARNING; | |
397 | } | |
398 | return bgp_show_mpls_vpn(vty, afi, &prd, | |
399 | bgp_show_type_normal, NULL, 0, | |
400 | use_json(argc, argv)); | |
401 | } else { | |
402 | return bgp_show_mpls_vpn(vty, afi, NULL, | |
403 | bgp_show_type_normal, NULL, 0, | |
404 | use_json(argc, argv)); | |
405 | } | |
406 | } | |
407 | return CMD_SUCCESS; | |
718e3744 | 408 | } |
409 | ||
af8528fa LB |
410 | ALIAS(show_bgp_ip_vpn_all_rd, |
411 | show_bgp_ip_vpn_rd_cmd, | |
412 | "show bgp "BGP_AFI_CMD_STR" vpn rd ASN:NN_OR_IP-ADDRESS:NN [json]", | |
413 | SHOW_STR | |
414 | BGP_STR | |
415 | BGP_VPNVX_HELP_STR | |
416 | "Display VPN NLRI specific information\n" | |
417 | "Display information for a route distinguisher\n" | |
418 | "VPN Route Distinguisher\n" | |
419 | JSON_STR) | |
420 | ||
421 | #ifdef KEEP_OLD_VPN_COMMANDS | |
3f227172 PG |
422 | DEFUN (show_ip_bgp_vpn_rd, |
423 | show_ip_bgp_vpn_rd_cmd, | |
af8528fa | 424 | "show ip bgp "BGP_AFI_CMD_STR" vpn rd ASN:NN_OR_IP-ADDRESS:NN", |
718e3744 | 425 | SHOW_STR |
426 | IP_STR | |
427 | BGP_STR | |
4f280b15 | 428 | BGP_AFI_HELP_STR |
3517059b | 429 | "Address Family modifier\n" |
718e3744 | 430 | "Display information for a route distinguisher\n" |
431 | "VPN Route Distinguisher\n") | |
432 | { | |
d62a17ae | 433 | int idx_ext_community = argc - 1; |
434 | int ret; | |
435 | struct prefix_rd prd; | |
436 | afi_t afi; | |
437 | int idx = 0; | |
438 | ||
439 | if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) { | |
440 | ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd); | |
441 | if (!ret) { | |
442 | vty_out(vty, "%% Malformed Route Distinguisher\n"); | |
443 | return CMD_WARNING; | |
444 | } | |
445 | return bgp_show_mpls_vpn(vty, afi, &prd, bgp_show_type_normal, | |
446 | NULL, 0, 0); | |
447 | } | |
448 | return CMD_SUCCESS; | |
449 | } | |
718e3744 | 450 | |
4f280b15 LB |
451 | DEFUN (show_ip_bgp_vpn_all, |
452 | show_ip_bgp_vpn_all_cmd, | |
453 | "show [ip] bgp <vpnv4|vpnv6>", | |
454 | SHOW_STR | |
455 | IP_STR | |
456 | BGP_STR | |
457 | BGP_VPNVX_HELP_STR) | |
458 | { | |
d62a17ae | 459 | afi_t afi; |
460 | int idx = 0; | |
4f280b15 | 461 | |
d62a17ae | 462 | if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) |
463 | return bgp_show_mpls_vpn(vty, afi, NULL, bgp_show_type_normal, | |
464 | NULL, 0, 0); | |
465 | return CMD_SUCCESS; | |
4f280b15 LB |
466 | } |
467 | ||
3f227172 PG |
468 | DEFUN (show_ip_bgp_vpn_all_tags, |
469 | show_ip_bgp_vpn_all_tags_cmd, | |
470 | "show [ip] bgp <vpnv4|vpnv6> all tags", | |
718e3744 | 471 | SHOW_STR |
472 | IP_STR | |
473 | BGP_STR | |
3f227172 PG |
474 | BGP_VPNVX_HELP_STR |
475 | "Display information about all VPNv4/VPNV6 NLRIs\n" | |
718e3744 | 476 | "Display BGP tags for prefixes\n") |
477 | { | |
d62a17ae | 478 | afi_t afi; |
479 | int idx = 0; | |
3f227172 | 480 | |
d62a17ae | 481 | if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) |
482 | return bgp_show_mpls_vpn(vty, afi, NULL, bgp_show_type_normal, | |
483 | NULL, 1, 0); | |
484 | return CMD_SUCCESS; | |
718e3744 | 485 | } |
486 | ||
3f227172 PG |
487 | DEFUN (show_ip_bgp_vpn_rd_tags, |
488 | show_ip_bgp_vpn_rd_tags_cmd, | |
d114b977 | 489 | "show [ip] bgp <vpnv4|vpnv6> rd ASN:NN_OR_IP-ADDRESS:NN tags", |
718e3744 | 490 | SHOW_STR |
491 | IP_STR | |
492 | BGP_STR | |
3f227172 | 493 | BGP_VPNVX_HELP_STR |
718e3744 | 494 | "Display information for a route distinguisher\n" |
495 | "VPN Route Distinguisher\n" | |
496 | "Display BGP tags for prefixes\n") | |
497 | { | |
d62a17ae | 498 | int idx_ext_community = 5; |
499 | int ret; | |
500 | struct prefix_rd prd; | |
501 | afi_t afi; | |
502 | int idx = 0; | |
503 | ||
504 | if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) { | |
505 | ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd); | |
506 | if (!ret) { | |
507 | vty_out(vty, "%% Malformed Route Distinguisher\n"); | |
508 | return CMD_WARNING; | |
509 | } | |
510 | return bgp_show_mpls_vpn(vty, afi, &prd, bgp_show_type_normal, | |
511 | NULL, 1, 0); | |
512 | } | |
513 | return CMD_SUCCESS; | |
718e3744 | 514 | } |
515 | ||
3f227172 PG |
516 | DEFUN (show_ip_bgp_vpn_all_neighbor_routes, |
517 | show_ip_bgp_vpn_all_neighbor_routes_cmd, | |
518 | "show [ip] bgp <vpnv4|vpnv6> all neighbors A.B.C.D routes [json]", | |
718e3744 | 519 | SHOW_STR |
520 | IP_STR | |
521 | BGP_STR | |
3f227172 PG |
522 | BGP_VPNVX_HELP_STR |
523 | "Display information about all VPNv4/VPNv6 NLRIs\n" | |
718e3744 | 524 | "Detailed information on TCP and BGP neighbor connections\n" |
525 | "Neighbor to display information about\n" | |
856ca177 | 526 | "Display routes learned from neighbor\n" |
9973d184 | 527 | JSON_STR) |
718e3744 | 528 | { |
d62a17ae | 529 | int idx_ipv4 = 6; |
530 | union sockunion su; | |
531 | struct peer *peer; | |
532 | int ret; | |
533 | u_char uj = use_json(argc, argv); | |
534 | afi_t afi; | |
535 | int idx = 0; | |
536 | ||
537 | if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) { | |
538 | ret = str2sockunion(argv[idx_ipv4]->arg, &su); | |
539 | if (ret < 0) { | |
540 | if (uj) { | |
541 | json_object *json_no = NULL; | |
542 | json_no = json_object_new_object(); | |
543 | json_object_string_add(json_no, "warning", | |
544 | "Malformed address"); | |
545 | vty_out(vty, "%s\n", | |
546 | json_object_to_json_string(json_no)); | |
547 | json_object_free(json_no); | |
548 | } else | |
549 | vty_out(vty, "Malformed address: %s\n", | |
550 | argv[idx_ipv4]->arg); | |
551 | return CMD_WARNING; | |
552 | } | |
553 | ||
554 | peer = peer_lookup(NULL, &su); | |
555 | if (!peer || !peer->afc[afi][SAFI_MPLS_VPN]) { | |
556 | if (uj) { | |
557 | json_object *json_no = NULL; | |
558 | json_no = json_object_new_object(); | |
559 | json_object_string_add( | |
560 | json_no, "warning", | |
561 | "No such neighbor or address family"); | |
562 | vty_out(vty, "%s\n", | |
563 | json_object_to_json_string(json_no)); | |
564 | json_object_free(json_no); | |
565 | } else | |
566 | vty_out(vty, | |
567 | "%% No such neighbor or address family\n"); | |
568 | return CMD_WARNING; | |
569 | } | |
570 | ||
571 | return bgp_show_mpls_vpn(vty, afi, NULL, bgp_show_type_neighbor, | |
572 | &su, 0, uj); | |
573 | } | |
574 | return CMD_SUCCESS; | |
718e3744 | 575 | } |
576 | ||
3f227172 PG |
577 | DEFUN (show_ip_bgp_vpn_rd_neighbor_routes, |
578 | show_ip_bgp_vpn_rd_neighbor_routes_cmd, | |
d114b977 | 579 | "show [ip] bgp <vpnv4|vpnv6> rd ASN:NN_OR_IP-ADDRESS:NN neighbors A.B.C.D routes [json]", |
718e3744 | 580 | SHOW_STR |
581 | IP_STR | |
582 | BGP_STR | |
3f227172 | 583 | BGP_VPNVX_HELP_STR |
718e3744 | 584 | "Display information for a route distinguisher\n" |
585 | "VPN Route Distinguisher\n" | |
586 | "Detailed information on TCP and BGP neighbor connections\n" | |
587 | "Neighbor to display information about\n" | |
856ca177 | 588 | "Display routes learned from neighbor\n" |
9973d184 | 589 | JSON_STR) |
718e3744 | 590 | { |
d62a17ae | 591 | int idx_ext_community = 5; |
592 | int idx_ipv4 = 7; | |
593 | int ret; | |
594 | union sockunion su; | |
595 | struct peer *peer; | |
596 | struct prefix_rd prd; | |
597 | u_char uj = use_json(argc, argv); | |
598 | afi_t afi; | |
599 | int idx = 0; | |
600 | ||
601 | if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) { | |
602 | ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd); | |
603 | if (!ret) { | |
604 | if (uj) { | |
605 | json_object *json_no = NULL; | |
606 | json_no = json_object_new_object(); | |
607 | json_object_string_add( | |
608 | json_no, "warning", | |
609 | "Malformed Route Distinguisher"); | |
610 | vty_out(vty, "%s\n", | |
611 | json_object_to_json_string(json_no)); | |
612 | json_object_free(json_no); | |
613 | } else | |
614 | vty_out(vty, | |
615 | "%% Malformed Route Distinguisher\n"); | |
616 | return CMD_WARNING; | |
617 | } | |
618 | ||
619 | ret = str2sockunion(argv[idx_ipv4]->arg, &su); | |
620 | if (ret < 0) { | |
621 | if (uj) { | |
622 | json_object *json_no = NULL; | |
623 | json_no = json_object_new_object(); | |
624 | json_object_string_add(json_no, "warning", | |
625 | "Malformed address"); | |
626 | vty_out(vty, "%s\n", | |
627 | json_object_to_json_string(json_no)); | |
628 | json_object_free(json_no); | |
629 | } else | |
630 | vty_out(vty, "Malformed address: %s\n", | |
631 | argv[idx_ext_community]->arg); | |
632 | return CMD_WARNING; | |
633 | } | |
634 | ||
635 | peer = peer_lookup(NULL, &su); | |
636 | if (!peer || !peer->afc[afi][SAFI_MPLS_VPN]) { | |
637 | if (uj) { | |
638 | json_object *json_no = NULL; | |
639 | json_no = json_object_new_object(); | |
640 | json_object_string_add( | |
641 | json_no, "warning", | |
642 | "No such neighbor or address family"); | |
643 | vty_out(vty, "%s\n", | |
644 | json_object_to_json_string(json_no)); | |
645 | json_object_free(json_no); | |
646 | } else | |
647 | vty_out(vty, | |
648 | "%% No such neighbor or address family\n"); | |
649 | return CMD_WARNING; | |
650 | } | |
651 | ||
652 | return bgp_show_mpls_vpn(vty, afi, &prd, bgp_show_type_neighbor, | |
653 | &su, 0, uj); | |
654 | } | |
655 | return CMD_SUCCESS; | |
718e3744 | 656 | } |
657 | ||
3f227172 PG |
658 | DEFUN (show_ip_bgp_vpn_all_neighbor_advertised_routes, |
659 | show_ip_bgp_vpn_all_neighbor_advertised_routes_cmd, | |
660 | "show [ip] bgp <vpnv4|vpnv6> all neighbors A.B.C.D advertised-routes [json]", | |
718e3744 | 661 | SHOW_STR |
662 | IP_STR | |
663 | BGP_STR | |
3f227172 PG |
664 | BGP_VPNVX_HELP_STR |
665 | "Display information about all VPNv4/VPNv6 NLRIs\n" | |
718e3744 | 666 | "Detailed information on TCP and BGP neighbor connections\n" |
667 | "Neighbor to display information about\n" | |
856ca177 | 668 | "Display the routes advertised to a BGP neighbor\n" |
9973d184 | 669 | JSON_STR) |
718e3744 | 670 | { |
d62a17ae | 671 | int idx_ipv4 = 6; |
672 | int ret; | |
673 | struct peer *peer; | |
674 | union sockunion su; | |
675 | u_char uj = use_json(argc, argv); | |
676 | afi_t afi; | |
677 | int idx = 0; | |
678 | ||
679 | if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) { | |
680 | ret = str2sockunion(argv[idx_ipv4]->arg, &su); | |
681 | if (ret < 0) { | |
682 | if (uj) { | |
683 | json_object *json_no = NULL; | |
684 | json_no = json_object_new_object(); | |
685 | json_object_string_add(json_no, "warning", | |
686 | "Malformed address"); | |
687 | vty_out(vty, "%s\n", | |
688 | json_object_to_json_string(json_no)); | |
689 | json_object_free(json_no); | |
690 | } else | |
691 | vty_out(vty, "Malformed address: %s\n", | |
692 | argv[idx_ipv4]->arg); | |
693 | return CMD_WARNING; | |
694 | } | |
695 | peer = peer_lookup(NULL, &su); | |
696 | if (!peer || !peer->afc[afi][SAFI_MPLS_VPN]) { | |
697 | if (uj) { | |
698 | json_object *json_no = NULL; | |
699 | json_no = json_object_new_object(); | |
700 | json_object_string_add( | |
701 | json_no, "warning", | |
702 | "No such neighbor or address family"); | |
703 | vty_out(vty, "%s\n", | |
704 | json_object_to_json_string(json_no)); | |
705 | json_object_free(json_no); | |
706 | } else | |
707 | vty_out(vty, | |
708 | "%% No such neighbor or address family\n"); | |
709 | return CMD_WARNING; | |
710 | } | |
711 | return show_adj_route_vpn(vty, peer, NULL, AFI_IP, | |
712 | SAFI_MPLS_VPN, uj); | |
713 | } | |
714 | return CMD_SUCCESS; | |
718e3744 | 715 | } |
716 | ||
3f227172 PG |
717 | DEFUN (show_ip_bgp_vpn_rd_neighbor_advertised_routes, |
718 | show_ip_bgp_vpn_rd_neighbor_advertised_routes_cmd, | |
d114b977 | 719 | "show [ip] bgp <vpnv4|vpnv6> rd ASN:NN_OR_IP-ADDRESS:NN neighbors A.B.C.D advertised-routes [json]", |
718e3744 | 720 | SHOW_STR |
721 | IP_STR | |
722 | BGP_STR | |
3f227172 | 723 | BGP_VPNVX_HELP_STR |
718e3744 | 724 | "Display information for a route distinguisher\n" |
725 | "VPN Route Distinguisher\n" | |
726 | "Detailed information on TCP and BGP neighbor connections\n" | |
727 | "Neighbor to display information about\n" | |
856ca177 | 728 | "Display the routes advertised to a BGP neighbor\n" |
9973d184 | 729 | JSON_STR) |
718e3744 | 730 | { |
d62a17ae | 731 | int idx_ext_community = 5; |
732 | int idx_ipv4 = 7; | |
733 | int ret; | |
734 | struct peer *peer; | |
735 | struct prefix_rd prd; | |
736 | union sockunion su; | |
737 | u_char uj = use_json(argc, argv); | |
738 | afi_t afi; | |
739 | int idx = 0; | |
740 | ||
741 | if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) { | |
742 | ret = str2sockunion(argv[idx_ipv4]->arg, &su); | |
743 | if (ret < 0) { | |
744 | if (uj) { | |
745 | json_object *json_no = NULL; | |
746 | json_no = json_object_new_object(); | |
747 | json_object_string_add(json_no, "warning", | |
748 | "Malformed address"); | |
749 | vty_out(vty, "%s\n", | |
750 | json_object_to_json_string(json_no)); | |
751 | json_object_free(json_no); | |
752 | } else | |
753 | vty_out(vty, "Malformed address: %s\n", | |
754 | argv[idx_ext_community]->arg); | |
755 | return CMD_WARNING; | |
756 | } | |
757 | peer = peer_lookup(NULL, &su); | |
758 | if (!peer || !peer->afc[afi][SAFI_MPLS_VPN]) { | |
759 | if (uj) { | |
760 | json_object *json_no = NULL; | |
761 | json_no = json_object_new_object(); | |
762 | json_object_string_add( | |
763 | json_no, "warning", | |
764 | "No such neighbor or address family"); | |
765 | vty_out(vty, "%s\n", | |
766 | json_object_to_json_string(json_no)); | |
767 | json_object_free(json_no); | |
768 | } else | |
769 | vty_out(vty, | |
770 | "%% No such neighbor or address family\n"); | |
771 | return CMD_WARNING; | |
772 | } | |
773 | ||
774 | ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd); | |
775 | if (!ret) { | |
776 | if (uj) { | |
777 | json_object *json_no = NULL; | |
778 | json_no = json_object_new_object(); | |
779 | json_object_string_add( | |
780 | json_no, "warning", | |
781 | "Malformed Route Distinguisher"); | |
782 | vty_out(vty, "%s\n", | |
783 | json_object_to_json_string(json_no)); | |
784 | json_object_free(json_no); | |
785 | } else | |
786 | vty_out(vty, | |
787 | "%% Malformed Route Distinguisher\n"); | |
788 | return CMD_WARNING; | |
789 | } | |
790 | ||
791 | return show_adj_route_vpn(vty, peer, &prd, AFI_IP, | |
792 | SAFI_MPLS_VPN, uj); | |
793 | } | |
794 | return CMD_SUCCESS; | |
718e3744 | 795 | } |
d6902373 | 796 | #endif /* KEEP_OLD_VPN_COMMANDS */ |
718e3744 | 797 | |
d62a17ae | 798 | void bgp_mplsvpn_init(void) |
718e3744 | 799 | { |
d62a17ae | 800 | install_element(BGP_VPNV4_NODE, &vpnv4_network_cmd); |
801 | install_element(BGP_VPNV4_NODE, &vpnv4_network_route_map_cmd); | |
802 | install_element(BGP_VPNV4_NODE, &no_vpnv4_network_cmd); | |
718e3744 | 803 | |
d62a17ae | 804 | install_element(BGP_VPNV6_NODE, &vpnv6_network_cmd); |
805 | install_element(BGP_VPNV6_NODE, &no_vpnv6_network_cmd); | |
c286be96 | 806 | |
d62a17ae | 807 | install_element(VIEW_NODE, &show_bgp_ip_vpn_all_rd_cmd); |
af8528fa | 808 | install_element(VIEW_NODE, &show_bgp_ip_vpn_rd_cmd); |
d6902373 | 809 | #ifdef KEEP_OLD_VPN_COMMANDS |
af8528fa | 810 | install_element(VIEW_NODE, &show_ip_bgp_vpn_rd_cmd); |
d62a17ae | 811 | install_element(VIEW_NODE, &show_ip_bgp_vpn_all_cmd); |
812 | install_element(VIEW_NODE, &show_ip_bgp_vpn_all_tags_cmd); | |
813 | install_element(VIEW_NODE, &show_ip_bgp_vpn_rd_tags_cmd); | |
814 | install_element(VIEW_NODE, &show_ip_bgp_vpn_all_neighbor_routes_cmd); | |
815 | install_element(VIEW_NODE, &show_ip_bgp_vpn_rd_neighbor_routes_cmd); | |
816 | install_element(VIEW_NODE, | |
817 | &show_ip_bgp_vpn_all_neighbor_advertised_routes_cmd); | |
818 | install_element(VIEW_NODE, | |
819 | &show_ip_bgp_vpn_rd_neighbor_advertised_routes_cmd); | |
d6902373 | 820 | #endif /* KEEP_OLD_VPN_COMMANDS */ |
718e3744 | 821 | } |