]>
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, | |
217 | BGP_ROUTE_NORMAL, &prd, &label, 0, NULL); | |
218 | } else { | |
219 | bgp_withdraw(peer, &p, addpath_id, attr, packet->afi, | |
220 | SAFI_MPLS_VPN, ZEBRA_ROUTE_BGP, | |
221 | BGP_ROUTE_NORMAL, &prd, &label, NULL); | |
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 LB |
368 | table = bgp->rib[afi][SAFI_MPLS_VPN]; |
369 | return bgp_show_table_rd(vty, bgp, SAFI_MPLS_VPN, | |
370 | table, prd, type, 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 | 376 | SHOW_STR |
716b2d8a | 377 | IP_STR |
e3e29b32 | 378 | BGP_STR |
05e588f4 | 379 | BGP_VPNVX_HELP_STR |
e3e29b32 LB |
380 | "Display VPN NLRI specific information\n" |
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 LB |
391 | if (argv_find(argv, argc, "rd", &idx)) { |
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 | ||
3f227172 PG |
410 | DEFUN (show_ip_bgp_vpn_rd, |
411 | show_ip_bgp_vpn_rd_cmd, | |
d114b977 | 412 | "show [ip] bgp "BGP_AFI_CMD_STR" vpn rd ASN:NN_OR_IP-ADDRESS:NN", |
718e3744 | 413 | SHOW_STR |
414 | IP_STR | |
415 | BGP_STR | |
4f280b15 | 416 | BGP_AFI_HELP_STR |
3517059b | 417 | "Address Family modifier\n" |
718e3744 | 418 | "Display information for a route distinguisher\n" |
419 | "VPN Route Distinguisher\n") | |
420 | { | |
d62a17ae | 421 | int idx_ext_community = argc - 1; |
422 | int ret; | |
423 | struct prefix_rd prd; | |
424 | afi_t afi; | |
425 | int idx = 0; | |
426 | ||
427 | if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) { | |
428 | ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd); | |
429 | if (!ret) { | |
430 | vty_out(vty, "%% Malformed Route Distinguisher\n"); | |
431 | return CMD_WARNING; | |
432 | } | |
433 | return bgp_show_mpls_vpn(vty, afi, &prd, bgp_show_type_normal, | |
434 | NULL, 0, 0); | |
435 | } | |
436 | return CMD_SUCCESS; | |
437 | } | |
718e3744 | 438 | |
4f280b15 LB |
439 | #ifdef KEEP_OLD_VPN_COMMANDS |
440 | DEFUN (show_ip_bgp_vpn_all, | |
441 | show_ip_bgp_vpn_all_cmd, | |
442 | "show [ip] bgp <vpnv4|vpnv6>", | |
443 | SHOW_STR | |
444 | IP_STR | |
445 | BGP_STR | |
446 | BGP_VPNVX_HELP_STR) | |
447 | { | |
d62a17ae | 448 | afi_t afi; |
449 | int idx = 0; | |
4f280b15 | 450 | |
d62a17ae | 451 | if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) |
452 | return bgp_show_mpls_vpn(vty, afi, NULL, bgp_show_type_normal, | |
453 | NULL, 0, 0); | |
454 | return CMD_SUCCESS; | |
4f280b15 LB |
455 | } |
456 | ||
3f227172 PG |
457 | DEFUN (show_ip_bgp_vpn_all_tags, |
458 | show_ip_bgp_vpn_all_tags_cmd, | |
459 | "show [ip] bgp <vpnv4|vpnv6> all tags", | |
718e3744 | 460 | SHOW_STR |
461 | IP_STR | |
462 | BGP_STR | |
3f227172 PG |
463 | BGP_VPNVX_HELP_STR |
464 | "Display information about all VPNv4/VPNV6 NLRIs\n" | |
718e3744 | 465 | "Display BGP tags for prefixes\n") |
466 | { | |
d62a17ae | 467 | afi_t afi; |
468 | int idx = 0; | |
3f227172 | 469 | |
d62a17ae | 470 | if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) |
471 | return bgp_show_mpls_vpn(vty, afi, NULL, bgp_show_type_normal, | |
472 | NULL, 1, 0); | |
473 | return CMD_SUCCESS; | |
718e3744 | 474 | } |
475 | ||
3f227172 PG |
476 | DEFUN (show_ip_bgp_vpn_rd_tags, |
477 | show_ip_bgp_vpn_rd_tags_cmd, | |
d114b977 | 478 | "show [ip] bgp <vpnv4|vpnv6> rd ASN:NN_OR_IP-ADDRESS:NN tags", |
718e3744 | 479 | SHOW_STR |
480 | IP_STR | |
481 | BGP_STR | |
3f227172 | 482 | BGP_VPNVX_HELP_STR |
718e3744 | 483 | "Display information for a route distinguisher\n" |
484 | "VPN Route Distinguisher\n" | |
485 | "Display BGP tags for prefixes\n") | |
486 | { | |
d62a17ae | 487 | int idx_ext_community = 5; |
488 | int ret; | |
489 | struct prefix_rd prd; | |
490 | afi_t afi; | |
491 | int idx = 0; | |
492 | ||
493 | if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) { | |
494 | ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd); | |
495 | if (!ret) { | |
496 | vty_out(vty, "%% Malformed Route Distinguisher\n"); | |
497 | return CMD_WARNING; | |
498 | } | |
499 | return bgp_show_mpls_vpn(vty, afi, &prd, bgp_show_type_normal, | |
500 | NULL, 1, 0); | |
501 | } | |
502 | return CMD_SUCCESS; | |
718e3744 | 503 | } |
504 | ||
3f227172 PG |
505 | DEFUN (show_ip_bgp_vpn_all_neighbor_routes, |
506 | show_ip_bgp_vpn_all_neighbor_routes_cmd, | |
507 | "show [ip] bgp <vpnv4|vpnv6> all neighbors A.B.C.D routes [json]", | |
718e3744 | 508 | SHOW_STR |
509 | IP_STR | |
510 | BGP_STR | |
3f227172 PG |
511 | BGP_VPNVX_HELP_STR |
512 | "Display information about all VPNv4/VPNv6 NLRIs\n" | |
718e3744 | 513 | "Detailed information on TCP and BGP neighbor connections\n" |
514 | "Neighbor to display information about\n" | |
856ca177 | 515 | "Display routes learned from neighbor\n" |
9973d184 | 516 | JSON_STR) |
718e3744 | 517 | { |
d62a17ae | 518 | int idx_ipv4 = 6; |
519 | union sockunion su; | |
520 | struct peer *peer; | |
521 | int ret; | |
522 | u_char uj = use_json(argc, argv); | |
523 | afi_t afi; | |
524 | int idx = 0; | |
525 | ||
526 | if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) { | |
527 | ret = str2sockunion(argv[idx_ipv4]->arg, &su); | |
528 | if (ret < 0) { | |
529 | if (uj) { | |
530 | json_object *json_no = NULL; | |
531 | json_no = json_object_new_object(); | |
532 | json_object_string_add(json_no, "warning", | |
533 | "Malformed address"); | |
534 | vty_out(vty, "%s\n", | |
535 | json_object_to_json_string(json_no)); | |
536 | json_object_free(json_no); | |
537 | } else | |
538 | vty_out(vty, "Malformed address: %s\n", | |
539 | argv[idx_ipv4]->arg); | |
540 | return CMD_WARNING; | |
541 | } | |
542 | ||
543 | peer = peer_lookup(NULL, &su); | |
544 | if (!peer || !peer->afc[afi][SAFI_MPLS_VPN]) { | |
545 | if (uj) { | |
546 | json_object *json_no = NULL; | |
547 | json_no = json_object_new_object(); | |
548 | json_object_string_add( | |
549 | json_no, "warning", | |
550 | "No such neighbor or address family"); | |
551 | vty_out(vty, "%s\n", | |
552 | json_object_to_json_string(json_no)); | |
553 | json_object_free(json_no); | |
554 | } else | |
555 | vty_out(vty, | |
556 | "%% No such neighbor or address family\n"); | |
557 | return CMD_WARNING; | |
558 | } | |
559 | ||
560 | return bgp_show_mpls_vpn(vty, afi, NULL, bgp_show_type_neighbor, | |
561 | &su, 0, uj); | |
562 | } | |
563 | return CMD_SUCCESS; | |
718e3744 | 564 | } |
565 | ||
3f227172 PG |
566 | DEFUN (show_ip_bgp_vpn_rd_neighbor_routes, |
567 | show_ip_bgp_vpn_rd_neighbor_routes_cmd, | |
d114b977 | 568 | "show [ip] bgp <vpnv4|vpnv6> rd ASN:NN_OR_IP-ADDRESS:NN neighbors A.B.C.D routes [json]", |
718e3744 | 569 | SHOW_STR |
570 | IP_STR | |
571 | BGP_STR | |
3f227172 | 572 | BGP_VPNVX_HELP_STR |
718e3744 | 573 | "Display information for a route distinguisher\n" |
574 | "VPN Route Distinguisher\n" | |
575 | "Detailed information on TCP and BGP neighbor connections\n" | |
576 | "Neighbor to display information about\n" | |
856ca177 | 577 | "Display routes learned from neighbor\n" |
9973d184 | 578 | JSON_STR) |
718e3744 | 579 | { |
d62a17ae | 580 | int idx_ext_community = 5; |
581 | int idx_ipv4 = 7; | |
582 | int ret; | |
583 | union sockunion su; | |
584 | struct peer *peer; | |
585 | struct prefix_rd prd; | |
586 | u_char uj = use_json(argc, argv); | |
587 | afi_t afi; | |
588 | int idx = 0; | |
589 | ||
590 | if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) { | |
591 | ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd); | |
592 | if (!ret) { | |
593 | if (uj) { | |
594 | json_object *json_no = NULL; | |
595 | json_no = json_object_new_object(); | |
596 | json_object_string_add( | |
597 | json_no, "warning", | |
598 | "Malformed Route Distinguisher"); | |
599 | vty_out(vty, "%s\n", | |
600 | json_object_to_json_string(json_no)); | |
601 | json_object_free(json_no); | |
602 | } else | |
603 | vty_out(vty, | |
604 | "%% Malformed Route Distinguisher\n"); | |
605 | return CMD_WARNING; | |
606 | } | |
607 | ||
608 | ret = str2sockunion(argv[idx_ipv4]->arg, &su); | |
609 | if (ret < 0) { | |
610 | if (uj) { | |
611 | json_object *json_no = NULL; | |
612 | json_no = json_object_new_object(); | |
613 | json_object_string_add(json_no, "warning", | |
614 | "Malformed address"); | |
615 | vty_out(vty, "%s\n", | |
616 | json_object_to_json_string(json_no)); | |
617 | json_object_free(json_no); | |
618 | } else | |
619 | vty_out(vty, "Malformed address: %s\n", | |
620 | argv[idx_ext_community]->arg); | |
621 | return CMD_WARNING; | |
622 | } | |
623 | ||
624 | peer = peer_lookup(NULL, &su); | |
625 | if (!peer || !peer->afc[afi][SAFI_MPLS_VPN]) { | |
626 | if (uj) { | |
627 | json_object *json_no = NULL; | |
628 | json_no = json_object_new_object(); | |
629 | json_object_string_add( | |
630 | json_no, "warning", | |
631 | "No such neighbor or address family"); | |
632 | vty_out(vty, "%s\n", | |
633 | json_object_to_json_string(json_no)); | |
634 | json_object_free(json_no); | |
635 | } else | |
636 | vty_out(vty, | |
637 | "%% No such neighbor or address family\n"); | |
638 | return CMD_WARNING; | |
639 | } | |
640 | ||
641 | return bgp_show_mpls_vpn(vty, afi, &prd, bgp_show_type_neighbor, | |
642 | &su, 0, uj); | |
643 | } | |
644 | return CMD_SUCCESS; | |
718e3744 | 645 | } |
646 | ||
3f227172 PG |
647 | DEFUN (show_ip_bgp_vpn_all_neighbor_advertised_routes, |
648 | show_ip_bgp_vpn_all_neighbor_advertised_routes_cmd, | |
649 | "show [ip] bgp <vpnv4|vpnv6> all neighbors A.B.C.D advertised-routes [json]", | |
718e3744 | 650 | SHOW_STR |
651 | IP_STR | |
652 | BGP_STR | |
3f227172 PG |
653 | BGP_VPNVX_HELP_STR |
654 | "Display information about all VPNv4/VPNv6 NLRIs\n" | |
718e3744 | 655 | "Detailed information on TCP and BGP neighbor connections\n" |
656 | "Neighbor to display information about\n" | |
856ca177 | 657 | "Display the routes advertised to a BGP neighbor\n" |
9973d184 | 658 | JSON_STR) |
718e3744 | 659 | { |
d62a17ae | 660 | int idx_ipv4 = 6; |
661 | int ret; | |
662 | struct peer *peer; | |
663 | union sockunion su; | |
664 | u_char uj = use_json(argc, argv); | |
665 | afi_t afi; | |
666 | int idx = 0; | |
667 | ||
668 | if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) { | |
669 | ret = str2sockunion(argv[idx_ipv4]->arg, &su); | |
670 | if (ret < 0) { | |
671 | if (uj) { | |
672 | json_object *json_no = NULL; | |
673 | json_no = json_object_new_object(); | |
674 | json_object_string_add(json_no, "warning", | |
675 | "Malformed address"); | |
676 | vty_out(vty, "%s\n", | |
677 | json_object_to_json_string(json_no)); | |
678 | json_object_free(json_no); | |
679 | } else | |
680 | vty_out(vty, "Malformed address: %s\n", | |
681 | argv[idx_ipv4]->arg); | |
682 | return CMD_WARNING; | |
683 | } | |
684 | peer = peer_lookup(NULL, &su); | |
685 | if (!peer || !peer->afc[afi][SAFI_MPLS_VPN]) { | |
686 | if (uj) { | |
687 | json_object *json_no = NULL; | |
688 | json_no = json_object_new_object(); | |
689 | json_object_string_add( | |
690 | json_no, "warning", | |
691 | "No such neighbor or address family"); | |
692 | vty_out(vty, "%s\n", | |
693 | json_object_to_json_string(json_no)); | |
694 | json_object_free(json_no); | |
695 | } else | |
696 | vty_out(vty, | |
697 | "%% No such neighbor or address family\n"); | |
698 | return CMD_WARNING; | |
699 | } | |
700 | return show_adj_route_vpn(vty, peer, NULL, AFI_IP, | |
701 | SAFI_MPLS_VPN, uj); | |
702 | } | |
703 | return CMD_SUCCESS; | |
718e3744 | 704 | } |
705 | ||
3f227172 PG |
706 | DEFUN (show_ip_bgp_vpn_rd_neighbor_advertised_routes, |
707 | show_ip_bgp_vpn_rd_neighbor_advertised_routes_cmd, | |
d114b977 | 708 | "show [ip] bgp <vpnv4|vpnv6> rd ASN:NN_OR_IP-ADDRESS:NN neighbors A.B.C.D advertised-routes [json]", |
718e3744 | 709 | SHOW_STR |
710 | IP_STR | |
711 | BGP_STR | |
3f227172 | 712 | BGP_VPNVX_HELP_STR |
718e3744 | 713 | "Display information for a route distinguisher\n" |
714 | "VPN Route Distinguisher\n" | |
715 | "Detailed information on TCP and BGP neighbor connections\n" | |
716 | "Neighbor to display information about\n" | |
856ca177 | 717 | "Display the routes advertised to a BGP neighbor\n" |
9973d184 | 718 | JSON_STR) |
718e3744 | 719 | { |
d62a17ae | 720 | int idx_ext_community = 5; |
721 | int idx_ipv4 = 7; | |
722 | int ret; | |
723 | struct peer *peer; | |
724 | struct prefix_rd prd; | |
725 | union sockunion su; | |
726 | u_char uj = use_json(argc, argv); | |
727 | afi_t afi; | |
728 | int idx = 0; | |
729 | ||
730 | if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) { | |
731 | ret = str2sockunion(argv[idx_ipv4]->arg, &su); | |
732 | if (ret < 0) { | |
733 | if (uj) { | |
734 | json_object *json_no = NULL; | |
735 | json_no = json_object_new_object(); | |
736 | json_object_string_add(json_no, "warning", | |
737 | "Malformed address"); | |
738 | vty_out(vty, "%s\n", | |
739 | json_object_to_json_string(json_no)); | |
740 | json_object_free(json_no); | |
741 | } else | |
742 | vty_out(vty, "Malformed address: %s\n", | |
743 | argv[idx_ext_community]->arg); | |
744 | return CMD_WARNING; | |
745 | } | |
746 | peer = peer_lookup(NULL, &su); | |
747 | if (!peer || !peer->afc[afi][SAFI_MPLS_VPN]) { | |
748 | if (uj) { | |
749 | json_object *json_no = NULL; | |
750 | json_no = json_object_new_object(); | |
751 | json_object_string_add( | |
752 | json_no, "warning", | |
753 | "No such neighbor or address family"); | |
754 | vty_out(vty, "%s\n", | |
755 | json_object_to_json_string(json_no)); | |
756 | json_object_free(json_no); | |
757 | } else | |
758 | vty_out(vty, | |
759 | "%% No such neighbor or address family\n"); | |
760 | return CMD_WARNING; | |
761 | } | |
762 | ||
763 | ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd); | |
764 | if (!ret) { | |
765 | if (uj) { | |
766 | json_object *json_no = NULL; | |
767 | json_no = json_object_new_object(); | |
768 | json_object_string_add( | |
769 | json_no, "warning", | |
770 | "Malformed Route Distinguisher"); | |
771 | vty_out(vty, "%s\n", | |
772 | json_object_to_json_string(json_no)); | |
773 | json_object_free(json_no); | |
774 | } else | |
775 | vty_out(vty, | |
776 | "%% Malformed Route Distinguisher\n"); | |
777 | return CMD_WARNING; | |
778 | } | |
779 | ||
780 | return show_adj_route_vpn(vty, peer, &prd, AFI_IP, | |
781 | SAFI_MPLS_VPN, uj); | |
782 | } | |
783 | return CMD_SUCCESS; | |
718e3744 | 784 | } |
d6902373 | 785 | #endif /* KEEP_OLD_VPN_COMMANDS */ |
718e3744 | 786 | |
d62a17ae | 787 | void bgp_mplsvpn_init(void) |
718e3744 | 788 | { |
d62a17ae | 789 | install_element(BGP_VPNV4_NODE, &vpnv4_network_cmd); |
790 | install_element(BGP_VPNV4_NODE, &vpnv4_network_route_map_cmd); | |
791 | install_element(BGP_VPNV4_NODE, &no_vpnv4_network_cmd); | |
718e3744 | 792 | |
d62a17ae | 793 | install_element(BGP_VPNV6_NODE, &vpnv6_network_cmd); |
794 | install_element(BGP_VPNV6_NODE, &no_vpnv6_network_cmd); | |
c286be96 | 795 | |
d62a17ae | 796 | install_element(VIEW_NODE, &show_bgp_ip_vpn_all_rd_cmd); |
797 | install_element(VIEW_NODE, &show_ip_bgp_vpn_rd_cmd); | |
d6902373 | 798 | #ifdef KEEP_OLD_VPN_COMMANDS |
d62a17ae | 799 | install_element(VIEW_NODE, &show_ip_bgp_vpn_all_cmd); |
800 | install_element(VIEW_NODE, &show_ip_bgp_vpn_all_tags_cmd); | |
801 | install_element(VIEW_NODE, &show_ip_bgp_vpn_rd_tags_cmd); | |
802 | install_element(VIEW_NODE, &show_ip_bgp_vpn_all_neighbor_routes_cmd); | |
803 | install_element(VIEW_NODE, &show_ip_bgp_vpn_rd_neighbor_routes_cmd); | |
804 | install_element(VIEW_NODE, | |
805 | &show_ip_bgp_vpn_all_neighbor_advertised_routes_cmd); | |
806 | install_element(VIEW_NODE, | |
807 | &show_ip_bgp_vpn_rd_neighbor_advertised_routes_cmd); | |
d6902373 | 808 | #endif /* KEEP_OLD_VPN_COMMANDS */ |
718e3744 | 809 | } |