Line data Source code
1 : /* MPLS-VPN
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 : */
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"
28 : #include "queue.h"
29 : #include "filter.h"
30 : #include "mpls.h"
31 : #include "json.h"
32 : #include "zclient.h"
33 :
34 : #include "bgpd/bgpd.h"
35 : #include "bgpd/bgp_debug.h"
36 : #include "bgpd/bgp_errors.h"
37 : #include "bgpd/bgp_table.h"
38 : #include "bgpd/bgp_route.h"
39 : #include "bgpd/bgp_attr.h"
40 : #include "bgpd/bgp_label.h"
41 : #include "bgpd/bgp_mplsvpn.h"
42 : #include "bgpd/bgp_packet.h"
43 : #include "bgpd/bgp_vty.h"
44 : #include "bgpd/bgp_vpn.h"
45 : #include "bgpd/bgp_community.h"
46 : #include "bgpd/bgp_ecommunity.h"
47 : #include "bgpd/bgp_zebra.h"
48 : #include "bgpd/bgp_nexthop.h"
49 : #include "bgpd/bgp_nht.h"
50 : #include "bgpd/bgp_evpn.h"
51 : #include "bgpd/bgp_memory.h"
52 :
53 : #ifdef ENABLE_BGP_VNC
54 : #include "bgpd/rfapi/rfapi_backend.h"
55 : #endif
56 :
57 : /*
58 : * Definitions and external declarations.
59 : */
60 : extern struct zclient *zclient;
61 :
62 0 : extern int argv_find_and_parse_vpnvx(struct cmd_token **argv, int argc,
63 : int *index, afi_t *afi)
64 : {
65 0 : int ret = 0;
66 0 : if (argv_find(argv, argc, "vpnv4", index)) {
67 0 : ret = 1;
68 0 : if (afi)
69 0 : *afi = AFI_IP;
70 0 : } else if (argv_find(argv, argc, "vpnv6", index)) {
71 0 : ret = 1;
72 0 : if (afi)
73 0 : *afi = AFI_IP6;
74 : }
75 0 : return ret;
76 : }
77 :
78 0 : uint32_t decode_label(mpls_label_t *label_pnt)
79 : {
80 0 : uint32_t l;
81 0 : uint8_t *pnt = (uint8_t *)label_pnt;
82 :
83 0 : l = ((uint32_t)*pnt++ << 12);
84 0 : l |= (uint32_t)*pnt++ << 4;
85 0 : l |= (uint32_t)((*pnt & 0xf0) >> 4);
86 0 : return l;
87 : }
88 :
89 0 : void encode_label(mpls_label_t label, mpls_label_t *label_pnt)
90 : {
91 0 : uint8_t *pnt = (uint8_t *)label_pnt;
92 0 : if (pnt == NULL)
93 : return;
94 0 : if (label == BGP_PREVENT_VRF_2_VRF_LEAK) {
95 0 : *label_pnt = label;
96 0 : return;
97 : }
98 0 : *pnt++ = (label >> 12) & 0xff;
99 0 : *pnt++ = (label >> 4) & 0xff;
100 0 : *pnt++ = ((label << 4) + 1) & 0xff; /* S=1 */
101 : }
102 :
103 0 : int bgp_nlri_parse_vpn(struct peer *peer, struct attr *attr,
104 : struct bgp_nlri *packet)
105 : {
106 0 : struct prefix p;
107 0 : uint8_t psize = 0;
108 0 : uint8_t prefixlen;
109 0 : uint16_t type;
110 0 : struct rd_as rd_as;
111 0 : struct rd_ip rd_ip;
112 0 : struct prefix_rd prd = {0};
113 0 : mpls_label_t label = {0};
114 0 : afi_t afi;
115 0 : safi_t safi;
116 0 : bool addpath_capable;
117 0 : uint32_t addpath_id;
118 0 : int ret = 0;
119 :
120 : /* Make prefix_rd */
121 0 : prd.family = AF_UNSPEC;
122 0 : prd.prefixlen = 64;
123 :
124 0 : struct stream *data = stream_new(packet->length);
125 0 : stream_put(data, packet->nlri, packet->length);
126 0 : afi = packet->afi;
127 0 : safi = packet->safi;
128 0 : addpath_id = 0;
129 :
130 0 : addpath_capable = bgp_addpath_encode_rx(peer, afi, safi);
131 :
132 : #define VPN_PREFIXLEN_MIN_BYTES (3 + 8) /* label + RD */
133 0 : while (STREAM_READABLE(data) > 0) {
134 : /* Clear prefix structure. */
135 0 : memset(&p, 0, sizeof(p));
136 :
137 0 : if (addpath_capable) {
138 0 : STREAM_GET(&addpath_id, data, BGP_ADDPATH_ID_LEN);
139 0 : addpath_id = ntohl(addpath_id);
140 : }
141 :
142 0 : if (STREAM_READABLE(data) < 1) {
143 0 : flog_err(
144 : EC_BGP_UPDATE_RCV,
145 : "%s [Error] Update packet error / VPN (truncated NLRI of size %u; no prefix length)",
146 : peer->host, packet->length);
147 0 : ret = BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
148 0 : goto done;
149 : }
150 :
151 : /* Fetch prefix length. */
152 0 : STREAM_GETC(data, prefixlen);
153 0 : p.family = afi2family(packet->afi);
154 0 : psize = PSIZE(prefixlen);
155 :
156 0 : if (prefixlen < VPN_PREFIXLEN_MIN_BYTES * 8) {
157 0 : flog_err(
158 : EC_BGP_UPDATE_RCV,
159 : "%s [Error] Update packet error / VPN (prefix length %d less than VPN min length)",
160 : peer->host, prefixlen);
161 0 : ret = BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
162 0 : goto done;
163 : }
164 :
165 : /* sanity check against packet data */
166 0 : if (STREAM_READABLE(data) < psize) {
167 0 : flog_err(
168 : EC_BGP_UPDATE_RCV,
169 : "%s [Error] Update packet error / VPN (prefix length %d exceeds packet size %u)",
170 : peer->host, prefixlen, packet->length);
171 0 : ret = BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
172 0 : goto done;
173 : }
174 :
175 : /* sanity check against storage for the IP address portion */
176 0 : if ((psize - VPN_PREFIXLEN_MIN_BYTES) > (ssize_t)sizeof(p.u)) {
177 : flog_err(
178 : EC_BGP_UPDATE_RCV,
179 : "%s [Error] Update packet error / VPN (psize %d exceeds storage size %zu)",
180 : peer->host,
181 : prefixlen - VPN_PREFIXLEN_MIN_BYTES * 8,
182 : sizeof(p.u));
183 : ret = BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
184 : goto done;
185 : }
186 :
187 : /* Sanity check against max bitlen of the address family */
188 0 : if ((psize - VPN_PREFIXLEN_MIN_BYTES) > prefix_blen(&p)) {
189 0 : flog_err(
190 : EC_BGP_UPDATE_RCV,
191 : "%s [Error] Update packet error / VPN (psize %d exceeds family (%u) max byte len %u)",
192 : peer->host,
193 : prefixlen - VPN_PREFIXLEN_MIN_BYTES * 8,
194 : p.family, prefix_blen(&p));
195 0 : ret = BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
196 0 : goto done;
197 : }
198 :
199 : /* Copy label to prefix. */
200 0 : if (STREAM_READABLE(data) < BGP_LABEL_BYTES) {
201 0 : flog_err(
202 : EC_BGP_UPDATE_RCV,
203 : "%s [Error] Update packet error / VPN (truncated NLRI of size %u; no label)",
204 : peer->host, packet->length);
205 0 : ret = BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
206 0 : goto done;
207 : }
208 :
209 0 : STREAM_GET(&label, data, BGP_LABEL_BYTES);
210 0 : bgp_set_valid_label(&label);
211 :
212 : /* Copy routing distinguisher to rd. */
213 0 : if (STREAM_READABLE(data) < 8) {
214 0 : flog_err(
215 : EC_BGP_UPDATE_RCV,
216 : "%s [Error] Update packet error / VPN (truncated NLRI of size %u; no RD)",
217 : peer->host, packet->length);
218 0 : ret = BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
219 0 : goto done;
220 : }
221 0 : STREAM_GET(&prd.val, data, 8);
222 :
223 : /* Decode RD type. */
224 0 : type = decode_rd_type(prd.val);
225 :
226 0 : switch (type) {
227 0 : case RD_TYPE_AS:
228 0 : decode_rd_as(&prd.val[2], &rd_as);
229 0 : break;
230 :
231 0 : case RD_TYPE_AS4:
232 0 : decode_rd_as4(&prd.val[2], &rd_as);
233 0 : break;
234 :
235 0 : case RD_TYPE_IP:
236 0 : decode_rd_ip(&prd.val[2], &rd_ip);
237 0 : break;
238 :
239 : #ifdef ENABLE_BGP_VNC
240 : case RD_TYPE_VNC_ETH:
241 : break;
242 : #endif
243 :
244 0 : default:
245 0 : flog_err(EC_BGP_UPDATE_RCV, "Unknown RD type %d", type);
246 0 : break; /* just report */
247 : }
248 :
249 : /* exclude label & RD */
250 0 : p.prefixlen = prefixlen - VPN_PREFIXLEN_MIN_BYTES * 8;
251 0 : STREAM_GET(p.u.val, data, psize - VPN_PREFIXLEN_MIN_BYTES);
252 :
253 0 : if (attr) {
254 0 : bgp_update(peer, &p, addpath_id, attr, packet->afi,
255 : SAFI_MPLS_VPN, ZEBRA_ROUTE_BGP,
256 : BGP_ROUTE_NORMAL, &prd, &label, 1, 0, NULL);
257 : } else {
258 0 : bgp_withdraw(peer, &p, addpath_id, attr, packet->afi,
259 : SAFI_MPLS_VPN, ZEBRA_ROUTE_BGP,
260 : BGP_ROUTE_NORMAL, &prd, &label, 1, NULL);
261 : }
262 : }
263 : /* Packet length consistency check. */
264 0 : if (STREAM_READABLE(data) != 0) {
265 : flog_err(
266 : EC_BGP_UPDATE_RCV,
267 : "%s [Error] Update packet error / VPN (%zu data remaining after parsing)",
268 : peer->host, STREAM_READABLE(data));
269 : return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
270 : }
271 :
272 0 : goto done;
273 :
274 0 : stream_failure:
275 0 : flog_err(
276 : EC_BGP_UPDATE_RCV,
277 : "%s [Error] Update packet error / VPN (NLRI of size %u - length error)",
278 : peer->host, packet->length);
279 0 : ret = BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
280 :
281 0 : done:
282 0 : stream_free(data);
283 0 : return ret;
284 :
285 : #undef VPN_PREFIXLEN_MIN_BYTES
286 : }
287 :
288 : /*
289 : * This function informs zebra of the label this vrf sets on routes
290 : * leaked to VPN. Zebra should install this label in the kernel with
291 : * an action of "pop label and then use this vrf's IP FIB to route the PDU."
292 : *
293 : * Sending this vrf-label association is qualified by a) whether vrf->vpn
294 : * exporting is active ("export vpn" is enabled, vpn-policy RD and RT list
295 : * are set) and b) whether vpn-policy label is set.
296 : *
297 : * If any of these conditions do not hold, then we send MPLS_LABEL_NONE
298 : * for this vrf, which zebra interprets to mean "delete this vrf-label
299 : * association."
300 : */
301 0 : void vpn_leak_zebra_vrf_label_update(struct bgp *bgp, afi_t afi)
302 : {
303 0 : mpls_label_t label = MPLS_LABEL_NONE;
304 0 : int debug = BGP_DEBUG(vpn, VPN_LEAK_LABEL);
305 :
306 0 : if (bgp->vrf_id == VRF_UNKNOWN) {
307 0 : if (debug) {
308 0 : zlog_debug(
309 : "%s: vrf %s: afi %s: vrf_id not set, can't set zebra vrf label",
310 : __func__, bgp->name_pretty, afi2str(afi));
311 : }
312 0 : return;
313 : }
314 :
315 0 : if (vpn_leak_to_vpn_active(bgp, afi, NULL)) {
316 0 : label = bgp->vpn_policy[afi].tovpn_label;
317 : }
318 :
319 0 : if (debug) {
320 0 : zlog_debug("%s: vrf %s: afi %s: setting label %d for vrf id %d",
321 : __func__, bgp->name_pretty, afi2str(afi), label,
322 : bgp->vrf_id);
323 : }
324 :
325 0 : if (label == BGP_PREVENT_VRF_2_VRF_LEAK)
326 0 : label = MPLS_LABEL_NONE;
327 0 : zclient_send_vrf_label(zclient, bgp->vrf_id, afi, label, ZEBRA_LSP_BGP);
328 0 : bgp->vpn_policy[afi].tovpn_zebra_vrf_label_last_sent = label;
329 : }
330 :
331 : /*
332 : * If zebra tells us vrf has become unconfigured, tell zebra not to
333 : * use this label to forward to the vrf anymore
334 : */
335 8 : void vpn_leak_zebra_vrf_label_withdraw(struct bgp *bgp, afi_t afi)
336 : {
337 8 : mpls_label_t label = MPLS_LABEL_NONE;
338 8 : int debug = BGP_DEBUG(vpn, VPN_LEAK_LABEL);
339 :
340 8 : if (bgp->vrf_id == VRF_UNKNOWN) {
341 0 : if (debug) {
342 0 : zlog_debug(
343 : "%s: vrf_id not set, can't delete zebra vrf label",
344 : __func__);
345 : }
346 0 : return;
347 : }
348 :
349 8 : if (debug) {
350 0 : zlog_debug("%s: deleting label for vrf %s (id=%d)", __func__,
351 : bgp->name_pretty, bgp->vrf_id);
352 : }
353 :
354 8 : zclient_send_vrf_label(zclient, bgp->vrf_id, afi, label, ZEBRA_LSP_BGP);
355 8 : bgp->vpn_policy[afi].tovpn_zebra_vrf_label_last_sent = label;
356 : }
357 :
358 : /*
359 : * This function informs zebra of the srv6-function this vrf sets on routes
360 : * leaked to VPN. Zebra should install this srv6-function in the kernel with
361 : * an action of "End.DT4/6's IP FIB to route the PDU."
362 : */
363 0 : void vpn_leak_zebra_vrf_sid_update_per_af(struct bgp *bgp, afi_t afi)
364 : {
365 0 : int debug = BGP_DEBUG(vpn, VPN_LEAK_LABEL);
366 0 : enum seg6local_action_t act;
367 0 : struct seg6local_context ctx = {};
368 0 : struct in6_addr *tovpn_sid = NULL;
369 0 : struct in6_addr *tovpn_sid_ls = NULL;
370 0 : struct vrf *vrf;
371 :
372 0 : if (bgp->vrf_id == VRF_UNKNOWN) {
373 0 : if (debug)
374 0 : zlog_debug("%s: vrf %s: afi %s: vrf_id not set, can't set zebra vrf label",
375 : __func__, bgp->name_pretty, afi2str(afi));
376 0 : return;
377 : }
378 :
379 0 : tovpn_sid = bgp->vpn_policy[afi].tovpn_sid;
380 0 : if (!tovpn_sid) {
381 0 : if (debug)
382 0 : zlog_debug("%s: vrf %s: afi %s: sid not set", __func__,
383 : bgp->name_pretty, afi2str(afi));
384 0 : return;
385 : }
386 :
387 0 : if (debug)
388 0 : zlog_debug("%s: vrf %s: afi %s: setting sid %pI6 for vrf id %d",
389 : __func__, bgp->name_pretty, afi2str(afi), tovpn_sid,
390 : bgp->vrf_id);
391 :
392 0 : vrf = vrf_lookup_by_id(bgp->vrf_id);
393 0 : if (!vrf)
394 : return;
395 :
396 0 : ctx.table = vrf->data.l.table_id;
397 0 : act = afi == AFI_IP ? ZEBRA_SEG6_LOCAL_ACTION_END_DT4
398 0 : : ZEBRA_SEG6_LOCAL_ACTION_END_DT6;
399 0 : zclient_send_localsid(zclient, tovpn_sid, bgp->vrf_id, act, &ctx);
400 :
401 0 : tovpn_sid_ls = XCALLOC(MTYPE_BGP_SRV6_SID, sizeof(struct in6_addr));
402 0 : *tovpn_sid_ls = *tovpn_sid;
403 0 : bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent = tovpn_sid_ls;
404 : }
405 :
406 : /*
407 : * This function informs zebra of the srv6-function this vrf sets on routes
408 : * leaked to VPN. Zebra should install this srv6-function in the kernel with
409 : * an action of "End.DT46's IP FIB to route the PDU."
410 : */
411 0 : void vpn_leak_zebra_vrf_sid_update_per_vrf(struct bgp *bgp)
412 : {
413 0 : int debug = BGP_DEBUG(vpn, VPN_LEAK_LABEL);
414 0 : enum seg6local_action_t act;
415 0 : struct seg6local_context ctx = {};
416 0 : struct in6_addr *tovpn_sid = NULL;
417 0 : struct in6_addr *tovpn_sid_ls = NULL;
418 0 : struct vrf *vrf;
419 :
420 0 : if (bgp->vrf_id == VRF_UNKNOWN) {
421 0 : if (debug)
422 0 : zlog_debug(
423 : "%s: vrf %s: vrf_id not set, can't set zebra vrf label",
424 : __func__, bgp->name_pretty);
425 0 : return;
426 : }
427 :
428 0 : tovpn_sid = bgp->tovpn_sid;
429 0 : if (!tovpn_sid) {
430 0 : if (debug)
431 0 : zlog_debug("%s: vrf %s: sid not set", __func__,
432 : bgp->name_pretty);
433 0 : return;
434 : }
435 :
436 0 : if (debug)
437 0 : zlog_debug("%s: vrf %s: setting sid %pI6 for vrf id %d",
438 : __func__, bgp->name_pretty, tovpn_sid, bgp->vrf_id);
439 :
440 0 : vrf = vrf_lookup_by_id(bgp->vrf_id);
441 0 : if (!vrf)
442 : return;
443 :
444 0 : ctx.table = vrf->data.l.table_id;
445 0 : act = ZEBRA_SEG6_LOCAL_ACTION_END_DT46;
446 0 : zclient_send_localsid(zclient, tovpn_sid, bgp->vrf_id, act, &ctx);
447 :
448 0 : tovpn_sid_ls = XCALLOC(MTYPE_BGP_SRV6_SID, sizeof(struct in6_addr));
449 0 : *tovpn_sid_ls = *tovpn_sid;
450 0 : bgp->tovpn_zebra_vrf_sid_last_sent = tovpn_sid_ls;
451 : }
452 :
453 : /*
454 : * This function informs zebra of the srv6-function this vrf sets on routes
455 : * leaked to VPN. Zebra should install this srv6-function in the kernel with
456 : * an action of "End.DT4/6/46's IP FIB to route the PDU."
457 : */
458 0 : void vpn_leak_zebra_vrf_sid_update(struct bgp *bgp, afi_t afi)
459 : {
460 0 : int debug = BGP_DEBUG(vpn, VPN_LEAK_LABEL);
461 :
462 0 : if (bgp->vpn_policy[afi].tovpn_sid)
463 0 : return vpn_leak_zebra_vrf_sid_update_per_af(bgp, afi);
464 :
465 0 : if (bgp->tovpn_sid)
466 0 : return vpn_leak_zebra_vrf_sid_update_per_vrf(bgp);
467 :
468 0 : if (debug)
469 0 : zlog_debug("%s: vrf %s: afi %s: sid not set", __func__,
470 : bgp->name_pretty, afi2str(afi));
471 : }
472 :
473 : /*
474 : * If zebra tells us vrf has become unconfigured, tell zebra not to
475 : * use this srv6-function to forward to the vrf anymore
476 : */
477 0 : void vpn_leak_zebra_vrf_sid_withdraw_per_af(struct bgp *bgp, afi_t afi)
478 : {
479 0 : int debug = BGP_DEBUG(vpn, VPN_LEAK_LABEL);
480 :
481 0 : if (bgp->vrf_id == VRF_UNKNOWN) {
482 0 : if (debug)
483 0 : zlog_debug("%s: vrf %s: afi %s: vrf_id not set, can't set zebra vrf label",
484 : __func__, bgp->name_pretty, afi2str(afi));
485 0 : return;
486 : }
487 :
488 0 : if (debug)
489 0 : zlog_debug("%s: deleting sid for vrf %s afi (id=%d)", __func__,
490 : bgp->name_pretty, bgp->vrf_id);
491 :
492 0 : zclient_send_localsid(zclient,
493 0 : bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent,
494 0 : bgp->vrf_id, ZEBRA_SEG6_LOCAL_ACTION_UNSPEC, NULL);
495 0 : XFREE(MTYPE_BGP_SRV6_SID,
496 : bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent);
497 : }
498 :
499 : /*
500 : * If zebra tells us vrf has become unconfigured, tell zebra not to
501 : * use this srv6-function to forward to the vrf anymore
502 : */
503 0 : void vpn_leak_zebra_vrf_sid_withdraw_per_vrf(struct bgp *bgp)
504 : {
505 0 : int debug = BGP_DEBUG(vpn, VPN_LEAK_LABEL);
506 :
507 0 : if (bgp->vrf_id == VRF_UNKNOWN) {
508 0 : if (debug)
509 0 : zlog_debug(
510 : "%s: vrf %s: vrf_id not set, can't set zebra vrf label",
511 : __func__, bgp->name_pretty);
512 0 : return;
513 : }
514 :
515 0 : if (debug)
516 0 : zlog_debug("%s: deleting sid for vrf %s (id=%d)", __func__,
517 : bgp->name_pretty, bgp->vrf_id);
518 :
519 0 : zclient_send_localsid(zclient, bgp->tovpn_zebra_vrf_sid_last_sent,
520 0 : bgp->vrf_id, ZEBRA_SEG6_LOCAL_ACTION_UNSPEC,
521 : NULL);
522 0 : XFREE(MTYPE_BGP_SRV6_SID, bgp->tovpn_zebra_vrf_sid_last_sent);
523 : }
524 :
525 : /*
526 : * If zebra tells us vrf has become unconfigured, tell zebra not to
527 : * use this srv6-function to forward to the vrf anymore
528 : */
529 0 : void vpn_leak_zebra_vrf_sid_withdraw(struct bgp *bgp, afi_t afi)
530 : {
531 0 : if (bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent)
532 0 : vpn_leak_zebra_vrf_sid_withdraw_per_af(bgp, afi);
533 :
534 0 : if (bgp->tovpn_zebra_vrf_sid_last_sent)
535 0 : vpn_leak_zebra_vrf_sid_withdraw_per_vrf(bgp);
536 0 : }
537 :
538 0 : int vpn_leak_label_callback(
539 : mpls_label_t label,
540 : void *labelid,
541 : bool allocated)
542 : {
543 0 : struct vpn_policy *vp = (struct vpn_policy *)labelid;
544 0 : int debug = BGP_DEBUG(vpn, VPN_LEAK_LABEL);
545 :
546 0 : if (debug)
547 0 : zlog_debug("%s: label=%u, allocated=%d",
548 : __func__, label, allocated);
549 :
550 0 : if (!allocated) {
551 : /*
552 : * previously-allocated label is now invalid
553 : */
554 0 : if (CHECK_FLAG(vp->flags, BGP_VPN_POLICY_TOVPN_LABEL_AUTO) &&
555 0 : (vp->tovpn_label != MPLS_LABEL_NONE)) {
556 :
557 0 : vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN,
558 : vp->afi, bgp_get_default(), vp->bgp);
559 0 : vp->tovpn_label = MPLS_LABEL_NONE;
560 0 : vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN,
561 : vp->afi, bgp_get_default(), vp->bgp);
562 : }
563 0 : return 0;
564 : }
565 :
566 : /*
567 : * New label allocation
568 : */
569 0 : if (!CHECK_FLAG(vp->flags, BGP_VPN_POLICY_TOVPN_LABEL_AUTO)) {
570 :
571 : /*
572 : * not currently configured for auto label, reject allocation
573 : */
574 : return -1;
575 : }
576 :
577 0 : if (vp->tovpn_label != MPLS_LABEL_NONE) {
578 0 : if (label == vp->tovpn_label) {
579 : /* already have same label, accept but do nothing */
580 : return 0;
581 : }
582 : /* Shouldn't happen: different label allocation */
583 0 : flog_err(EC_BGP_LABEL,
584 : "%s: %s had label %u but got new assignment %u",
585 : __func__, vp->bgp->name_pretty, vp->tovpn_label,
586 : label);
587 : /* use new one */
588 : }
589 :
590 0 : vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN,
591 : vp->afi, bgp_get_default(), vp->bgp);
592 0 : vp->tovpn_label = label;
593 0 : vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN,
594 : vp->afi, bgp_get_default(), vp->bgp);
595 :
596 0 : return 0;
597 : }
598 :
599 0 : static void sid_register(struct bgp *bgp, const struct in6_addr *sid,
600 : const char *locator_name)
601 : {
602 0 : struct bgp_srv6_function *func;
603 0 : func = XCALLOC(MTYPE_BGP_SRV6_FUNCTION,
604 : sizeof(struct bgp_srv6_function));
605 0 : func->sid = *sid;
606 0 : snprintf(func->locator_name, sizeof(func->locator_name),
607 : "%s", locator_name);
608 0 : listnode_add(bgp->srv6_functions, func);
609 0 : }
610 :
611 0 : static void sid_unregister(struct bgp *bgp, const struct in6_addr *sid)
612 : {
613 0 : struct listnode *node, *nnode;
614 0 : struct bgp_srv6_function *func;
615 :
616 0 : for (ALL_LIST_ELEMENTS(bgp->srv6_functions, node, nnode, func))
617 0 : if (sid_same(&func->sid, sid)) {
618 0 : listnode_delete(bgp->srv6_functions, func);
619 0 : XFREE(MTYPE_BGP_SRV6_FUNCTION, func);
620 : }
621 0 : }
622 :
623 0 : static bool sid_exist(struct bgp *bgp, const struct in6_addr *sid)
624 : {
625 0 : struct listnode *node;
626 0 : struct bgp_srv6_function *func;
627 :
628 0 : for (ALL_LIST_ELEMENTS_RO(bgp->srv6_functions, node, func))
629 0 : if (sid_same(&func->sid, sid))
630 : return true;
631 : return false;
632 : }
633 :
634 : /*
635 : * This function generates a new SID based on bgp->srv6_locator_chunks and
636 : * index. The locator and generated SID are stored in arguments sid_locator
637 : * and sid, respectively.
638 : *
639 : * if index != 0: try to allocate as index-mode
640 : * else: try to allocate as auto-mode
641 : */
642 0 : static uint32_t alloc_new_sid(struct bgp *bgp, uint32_t index,
643 : struct srv6_locator_chunk *sid_locator_chunk,
644 : struct in6_addr *sid)
645 : {
646 0 : int debug = BGP_DEBUG(vpn, VPN_LEAK_LABEL);
647 0 : struct listnode *node;
648 0 : struct srv6_locator_chunk *chunk;
649 0 : bool alloced = false;
650 0 : int label = 0;
651 0 : uint8_t offset = 0;
652 0 : uint8_t func_len = 0, shift_len = 0;
653 0 : uint32_t index_max = 0;
654 :
655 0 : if (!bgp || !sid_locator_chunk || !sid)
656 : return false;
657 :
658 0 : for (ALL_LIST_ELEMENTS_RO(bgp->srv6_locator_chunks, node, chunk)) {
659 0 : if (chunk->function_bits_length >
660 : BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH) {
661 0 : if (debug)
662 0 : zlog_debug(
663 : "%s: invalid SRv6 Locator chunk (%pFX): Function Length must be less or equal to %d",
664 : __func__, &chunk->prefix,
665 : BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH);
666 0 : continue;
667 : }
668 :
669 0 : index_max = (1 << chunk->function_bits_length) - 1;
670 :
671 0 : if (index > index_max) {
672 0 : if (debug)
673 0 : zlog_debug(
674 : "%s: skipped SRv6 Locator chunk (%pFX): Function Length is too short to support specified index (%u)",
675 : __func__, &chunk->prefix, index);
676 0 : continue;
677 : }
678 :
679 0 : *sid = chunk->prefix.prefix;
680 0 : *sid_locator_chunk = *chunk;
681 0 : offset = chunk->block_bits_length + chunk->node_bits_length;
682 0 : func_len = chunk->function_bits_length;
683 0 : shift_len = BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH - func_len;
684 :
685 0 : if (index != 0) {
686 0 : label = index << shift_len;
687 0 : if (label < MPLS_LABEL_UNRESERVED_MIN) {
688 0 : if (debug)
689 0 : zlog_debug(
690 : "%s: skipped to allocate SRv6 SID (%pFX): Label (%u) is too small to use",
691 : __func__, &chunk->prefix,
692 : label);
693 0 : continue;
694 : }
695 :
696 0 : transpose_sid(sid, label, offset, func_len);
697 0 : if (sid_exist(bgp, sid))
698 0 : continue;
699 : alloced = true;
700 : break;
701 : }
702 :
703 0 : for (uint32_t i = 1; i < index_max; i++) {
704 0 : label = i << shift_len;
705 0 : if (label < MPLS_LABEL_UNRESERVED_MIN) {
706 0 : if (debug)
707 0 : zlog_debug(
708 : "%s: skipped to allocate SRv6 SID (%pFX): Label (%u) is too small to use",
709 : __func__, &chunk->prefix,
710 : label);
711 0 : continue;
712 : }
713 0 : transpose_sid(sid, label, offset, func_len);
714 0 : if (sid_exist(bgp, sid))
715 0 : continue;
716 : alloced = true;
717 : break;
718 : }
719 : }
720 :
721 0 : if (!alloced)
722 : return 0;
723 :
724 0 : sid_register(bgp, sid, bgp->srv6_locator_name);
725 0 : return label;
726 : }
727 :
728 0 : void ensure_vrf_tovpn_sid_per_af(struct bgp *bgp_vpn, struct bgp *bgp_vrf,
729 : afi_t afi)
730 : {
731 0 : int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF);
732 0 : struct srv6_locator_chunk *tovpn_sid_locator;
733 0 : struct in6_addr *tovpn_sid;
734 0 : uint32_t tovpn_sid_index = 0, tovpn_sid_transpose_label;
735 0 : bool tovpn_sid_auto = false;
736 :
737 0 : if (debug)
738 0 : zlog_debug("%s: try to allocate new SID for vrf %s: afi %s",
739 : __func__, bgp_vrf->name_pretty, afi2str(afi));
740 :
741 : /* skip when tovpn sid is already allocated on vrf instance */
742 0 : if (bgp_vrf->vpn_policy[afi].tovpn_sid)
743 0 : return;
744 :
745 : /*
746 : * skip when bgp vpn instance ins't allocated
747 : * or srv6 locator chunk isn't allocated
748 : */
749 0 : if (!bgp_vpn || !bgp_vpn->srv6_locator_chunks)
750 : return;
751 :
752 0 : tovpn_sid_index = bgp_vrf->vpn_policy[afi].tovpn_sid_index;
753 0 : tovpn_sid_auto = CHECK_FLAG(bgp_vrf->vpn_policy[afi].flags,
754 : BGP_VPN_POLICY_TOVPN_SID_AUTO);
755 :
756 : /* skip when VPN isn't configured on vrf-instance */
757 0 : if (tovpn_sid_index == 0 && !tovpn_sid_auto)
758 : return;
759 :
760 : /* check invalid case both configured index and auto */
761 0 : if (tovpn_sid_index != 0 && tovpn_sid_auto) {
762 0 : zlog_err("%s: index-mode and auto-mode both selected. ignored.",
763 : __func__);
764 0 : return;
765 : }
766 :
767 0 : tovpn_sid_locator = srv6_locator_chunk_alloc();
768 0 : tovpn_sid = XCALLOC(MTYPE_BGP_SRV6_SID, sizeof(struct in6_addr));
769 :
770 0 : tovpn_sid_transpose_label = alloc_new_sid(bgp_vpn, tovpn_sid_index,
771 : tovpn_sid_locator, tovpn_sid);
772 :
773 0 : if (tovpn_sid_transpose_label == 0) {
774 0 : if (debug)
775 0 : zlog_debug(
776 : "%s: not allocated new sid for vrf %s: afi %s",
777 : __func__, bgp_vrf->name_pretty, afi2str(afi));
778 0 : srv6_locator_chunk_free(&tovpn_sid_locator);
779 0 : XFREE(MTYPE_BGP_SRV6_SID, tovpn_sid);
780 0 : return;
781 : }
782 :
783 0 : if (debug)
784 0 : zlog_debug("%s: new sid %pI6 allocated for vrf %s: afi %s",
785 : __func__, tovpn_sid, bgp_vrf->name_pretty,
786 : afi2str(afi));
787 :
788 0 : bgp_vrf->vpn_policy[afi].tovpn_sid = tovpn_sid;
789 0 : bgp_vrf->vpn_policy[afi].tovpn_sid_locator = tovpn_sid_locator;
790 0 : bgp_vrf->vpn_policy[afi].tovpn_sid_transpose_label =
791 : tovpn_sid_transpose_label;
792 : }
793 :
794 0 : void ensure_vrf_tovpn_sid_per_vrf(struct bgp *bgp_vpn, struct bgp *bgp_vrf)
795 : {
796 0 : int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF);
797 0 : struct srv6_locator_chunk *tovpn_sid_locator;
798 0 : struct in6_addr *tovpn_sid;
799 0 : uint32_t tovpn_sid_index = 0, tovpn_sid_transpose_label;
800 0 : bool tovpn_sid_auto = false;
801 :
802 0 : if (debug)
803 0 : zlog_debug("%s: try to allocate new SID for vrf %s", __func__,
804 : bgp_vrf->name_pretty);
805 :
806 : /* skip when tovpn sid is already allocated on vrf instance */
807 0 : if (bgp_vrf->tovpn_sid)
808 0 : return;
809 :
810 : /*
811 : * skip when bgp vpn instance ins't allocated
812 : * or srv6 locator chunk isn't allocated
813 : */
814 0 : if (!bgp_vpn || !bgp_vpn->srv6_locator_chunks)
815 : return;
816 :
817 0 : tovpn_sid_index = bgp_vrf->tovpn_sid_index;
818 0 : tovpn_sid_auto = CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_TOVPN_SID_AUTO);
819 :
820 : /* skip when VPN isn't configured on vrf-instance */
821 0 : if (tovpn_sid_index == 0 && !tovpn_sid_auto)
822 : return;
823 :
824 : /* check invalid case both configured index and auto */
825 0 : if (tovpn_sid_index != 0 && tovpn_sid_auto) {
826 0 : zlog_err("%s: index-mode and auto-mode both selected. ignored.",
827 : __func__);
828 0 : return;
829 : }
830 :
831 0 : tovpn_sid_locator = srv6_locator_chunk_alloc();
832 0 : tovpn_sid = XCALLOC(MTYPE_BGP_SRV6_SID, sizeof(struct in6_addr));
833 :
834 0 : tovpn_sid_transpose_label = alloc_new_sid(bgp_vpn, tovpn_sid_index,
835 : tovpn_sid_locator, tovpn_sid);
836 :
837 0 : if (tovpn_sid_transpose_label == 0) {
838 0 : if (debug)
839 0 : zlog_debug("%s: not allocated new sid for vrf %s",
840 : __func__, bgp_vrf->name_pretty);
841 0 : srv6_locator_chunk_free(&tovpn_sid_locator);
842 0 : XFREE(MTYPE_BGP_SRV6_SID, tovpn_sid);
843 0 : return;
844 : }
845 :
846 0 : if (debug)
847 0 : zlog_debug("%s: new sid %pI6 allocated for vrf %s", __func__,
848 : tovpn_sid, bgp_vrf->name_pretty);
849 :
850 0 : bgp_vrf->tovpn_sid = tovpn_sid;
851 0 : bgp_vrf->tovpn_sid_locator = tovpn_sid_locator;
852 0 : bgp_vrf->tovpn_sid_transpose_label = tovpn_sid_transpose_label;
853 : }
854 :
855 0 : void ensure_vrf_tovpn_sid(struct bgp *bgp_vpn, struct bgp *bgp_vrf, afi_t afi)
856 : {
857 : /* per-af sid */
858 0 : if (bgp_vrf->vpn_policy[afi].tovpn_sid_index != 0 ||
859 0 : CHECK_FLAG(bgp_vrf->vpn_policy[afi].flags,
860 : BGP_VPN_POLICY_TOVPN_SID_AUTO))
861 0 : return ensure_vrf_tovpn_sid_per_af(bgp_vpn, bgp_vrf, afi);
862 :
863 : /* per-vrf sid */
864 0 : if (bgp_vrf->tovpn_sid_index != 0 ||
865 0 : CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_TOVPN_SID_AUTO))
866 0 : return ensure_vrf_tovpn_sid_per_vrf(bgp_vpn, bgp_vrf);
867 : }
868 :
869 0 : void delete_vrf_tovpn_sid_per_af(struct bgp *bgp_vpn, struct bgp *bgp_vrf,
870 : afi_t afi)
871 : {
872 0 : int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF);
873 0 : uint32_t tovpn_sid_index = 0;
874 0 : bool tovpn_sid_auto = false;
875 :
876 0 : if (debug)
877 0 : zlog_debug("%s: try to remove SID for vrf %s: afi %s", __func__,
878 : bgp_vrf->name_pretty, afi2str(afi));
879 :
880 0 : tovpn_sid_index = bgp_vrf->vpn_policy[afi].tovpn_sid_index;
881 0 : tovpn_sid_auto = CHECK_FLAG(bgp_vrf->vpn_policy[afi].flags,
882 : BGP_VPN_POLICY_TOVPN_SID_AUTO);
883 :
884 : /* skip when VPN is configured on vrf-instance */
885 0 : if (tovpn_sid_index != 0 || tovpn_sid_auto)
886 : return;
887 :
888 0 : srv6_locator_chunk_free(&bgp_vrf->vpn_policy[afi].tovpn_sid_locator);
889 :
890 0 : if (bgp_vrf->vpn_policy[afi].tovpn_sid) {
891 0 : sid_unregister(bgp_vpn, bgp_vrf->vpn_policy[afi].tovpn_sid);
892 0 : XFREE(MTYPE_BGP_SRV6_SID, bgp_vrf->vpn_policy[afi].tovpn_sid);
893 : }
894 0 : bgp_vrf->vpn_policy[afi].tovpn_sid_transpose_label = 0;
895 : }
896 :
897 0 : void delete_vrf_tovpn_sid_per_vrf(struct bgp *bgp_vpn, struct bgp *bgp_vrf)
898 : {
899 0 : int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF);
900 0 : uint32_t tovpn_sid_index = 0;
901 0 : bool tovpn_sid_auto = false;
902 :
903 0 : if (debug)
904 0 : zlog_debug("%s: try to remove SID for vrf %s", __func__,
905 : bgp_vrf->name_pretty);
906 :
907 0 : tovpn_sid_index = bgp_vrf->tovpn_sid_index;
908 0 : tovpn_sid_auto =
909 0 : CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VPN_POLICY_TOVPN_SID_AUTO);
910 :
911 : /* skip when VPN is configured on vrf-instance */
912 0 : if (tovpn_sid_index != 0 || tovpn_sid_auto)
913 : return;
914 :
915 0 : srv6_locator_chunk_free(&bgp_vrf->tovpn_sid_locator);
916 :
917 0 : if (bgp_vrf->tovpn_sid) {
918 0 : sid_unregister(bgp_vpn, bgp_vrf->tovpn_sid);
919 0 : XFREE(MTYPE_BGP_SRV6_SID, bgp_vrf->tovpn_sid);
920 : }
921 0 : bgp_vrf->tovpn_sid_transpose_label = 0;
922 : }
923 :
924 0 : void delete_vrf_tovpn_sid(struct bgp *bgp_vpn, struct bgp *bgp_vrf, afi_t afi)
925 : {
926 0 : delete_vrf_tovpn_sid_per_af(bgp_vpn, bgp_vrf, afi);
927 0 : delete_vrf_tovpn_sid_per_vrf(bgp_vpn, bgp_vrf);
928 0 : }
929 :
930 : /*
931 : * This function embeds upper `len` bits of `label` in `sid`,
932 : * starting at offset `offset` as seen from the MSB of `sid`.
933 : *
934 : * e.g. Given that `label` is 0x12345 and `len` is 16,
935 : * then `label` will be embedded in `sid` as follows:
936 : *
937 : * <---- len ----->
938 : * label: 0001 0002 0003 0004 0005
939 : * sid: .... 0001 0002 0003 0004
940 : * <---- len ----->
941 : * ^
942 : * |
943 : * offset from MSB
944 : *
945 : * e.g. Given that `label` is 0x12345 and `len` is 8,
946 : * `label` will be embedded in `sid` as follows:
947 : *
948 : * <- len ->
949 : * label: 0001 0002 0003 0004 0005
950 : * sid: .... 0001 0002 0000 0000
951 : * <- len ->
952 : * ^
953 : * |
954 : * offset from MSB
955 : */
956 0 : void transpose_sid(struct in6_addr *sid, uint32_t label, uint8_t offset,
957 : uint8_t len)
958 : {
959 0 : for (uint8_t idx = 0; idx < len; idx++) {
960 0 : uint8_t tidx = offset + idx;
961 0 : sid->s6_addr[tidx / 8] &= ~(0x1 << (7 - tidx % 8));
962 0 : if (label >> (19 - idx) & 0x1)
963 0 : sid->s6_addr[tidx / 8] |= 0x1 << (7 - tidx % 8);
964 : }
965 0 : }
966 :
967 0 : static bool labels_same(struct bgp_path_info *bpi, mpls_label_t *label,
968 : uint32_t n)
969 : {
970 0 : uint32_t i;
971 :
972 0 : if (!bpi->extra) {
973 0 : if (!n)
974 : return true;
975 : else
976 0 : return false;
977 : }
978 :
979 0 : if (n != bpi->extra->num_labels)
980 : return false;
981 :
982 0 : for (i = 0; i < n; ++i) {
983 0 : if (label[i] != bpi->extra->label[i])
984 : return false;
985 : }
986 : return true;
987 : }
988 :
989 : /*
990 : * make encoded route labels match specified encoded label set
991 : */
992 0 : static void setlabels(struct bgp_path_info *bpi,
993 : mpls_label_t *label, /* array of labels */
994 : uint32_t num_labels)
995 : {
996 0 : if (num_labels)
997 0 : assert(label);
998 0 : assert(num_labels <= BGP_MAX_LABELS);
999 :
1000 0 : if (!num_labels) {
1001 0 : if (bpi->extra)
1002 0 : bpi->extra->num_labels = 0;
1003 0 : return;
1004 : }
1005 :
1006 0 : struct bgp_path_info_extra *extra = bgp_path_info_extra_get(bpi);
1007 0 : uint32_t i;
1008 :
1009 0 : for (i = 0; i < num_labels; ++i) {
1010 0 : extra->label[i] = label[i];
1011 0 : if (!bgp_is_valid_label(&label[i])) {
1012 0 : bgp_set_valid_label(&extra->label[i]);
1013 : }
1014 : }
1015 0 : extra->num_labels = num_labels;
1016 : }
1017 :
1018 : /*
1019 : * make encoded route SIDs match specified encoded sid set
1020 : */
1021 0 : static void setsids(struct bgp_path_info *bpi,
1022 : struct in6_addr *sid,
1023 : uint32_t num_sids)
1024 : {
1025 0 : uint32_t i;
1026 0 : struct bgp_path_info_extra *extra;
1027 :
1028 0 : if (num_sids)
1029 0 : assert(sid);
1030 0 : assert(num_sids <= BGP_MAX_SIDS);
1031 :
1032 0 : if (!num_sids) {
1033 0 : if (bpi->extra)
1034 0 : bpi->extra->num_sids = 0;
1035 0 : return;
1036 : }
1037 :
1038 0 : extra = bgp_path_info_extra_get(bpi);
1039 0 : for (i = 0; i < num_sids; i++)
1040 0 : memcpy(&extra->sid[i].sid, &sid[i], sizeof(struct in6_addr));
1041 0 : extra->num_sids = num_sids;
1042 : }
1043 :
1044 0 : static void unsetsids(struct bgp_path_info *bpi)
1045 : {
1046 0 : struct bgp_path_info_extra *extra;
1047 :
1048 0 : extra = bgp_path_info_extra_get(bpi);
1049 0 : extra->num_sids = 0;
1050 0 : memset(extra->sid, 0, sizeof(extra->sid));
1051 0 : }
1052 :
1053 0 : static bool leak_update_nexthop_valid(struct bgp *to_bgp, struct bgp_dest *bn,
1054 : struct attr *new_attr, afi_t afi,
1055 : safi_t safi,
1056 : struct bgp_path_info *source_bpi,
1057 : struct bgp_path_info *bpi,
1058 : struct bgp *bgp_orig,
1059 : const struct prefix *p, int debug)
1060 : {
1061 0 : struct bgp_path_info *bpi_ultimate;
1062 0 : struct bgp *bgp_nexthop;
1063 0 : bool nh_valid;
1064 :
1065 0 : bpi_ultimate = bgp_get_imported_bpi_ultimate(source_bpi);
1066 :
1067 0 : if (bpi->extra && bpi->extra->bgp_orig)
1068 0 : bgp_nexthop = bpi->extra->bgp_orig;
1069 : else
1070 : bgp_nexthop = bgp_orig;
1071 :
1072 : /*
1073 : * No nexthop tracking for redistributed routes, for
1074 : * EVPN-imported routes that get leaked, or for routes
1075 : * leaked between VRFs with accept-own community.
1076 : */
1077 0 : if (bpi_ultimate->sub_type == BGP_ROUTE_REDISTRIBUTE ||
1078 0 : is_pi_family_evpn(bpi_ultimate) ||
1079 0 : CHECK_FLAG(bpi_ultimate->flags, BGP_PATH_ACCEPT_OWN))
1080 : nh_valid = true;
1081 : else
1082 : /*
1083 : * TBD do we need to do anything about the
1084 : * 'connected' parameter?
1085 : */
1086 0 : nh_valid = bgp_find_or_add_nexthop(to_bgp, bgp_nexthop, afi,
1087 : safi, bpi, NULL, 0, p);
1088 :
1089 : /*
1090 : * If you are using SRv6 VPN instead of MPLS, it need to check
1091 : * the SID allocation. If the sid is not allocated, the rib
1092 : * will be invalid.
1093 : */
1094 0 : if (to_bgp->srv6_enabled &&
1095 0 : (!new_attr->srv6_l3vpn && !new_attr->srv6_vpn)) {
1096 0 : nh_valid = false;
1097 : }
1098 :
1099 0 : if (debug)
1100 0 : zlog_debug("%s: %pFX nexthop is %svalid (in %s)", __func__, p,
1101 : (nh_valid ? "" : "not "), bgp_nexthop->name_pretty);
1102 :
1103 0 : return nh_valid;
1104 : }
1105 :
1106 : /*
1107 : * returns pointer to new bgp_path_info upon success
1108 : */
1109 : static struct bgp_path_info *
1110 0 : leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
1111 : struct attr *new_attr, /* already interned */
1112 : afi_t afi, safi_t safi, struct bgp_path_info *source_bpi,
1113 : mpls_label_t *label, uint32_t num_labels, struct bgp *bgp_orig,
1114 : struct prefix *nexthop_orig, int nexthop_self_flag, int debug)
1115 : {
1116 0 : const struct prefix *p = bgp_dest_get_prefix(bn);
1117 0 : struct bgp_path_info *bpi;
1118 0 : struct bgp_path_info *new;
1119 0 : struct bgp_path_info_extra *extra;
1120 0 : uint32_t num_sids = 0;
1121 0 : void *parent = source_bpi;
1122 :
1123 0 : if (new_attr->srv6_l3vpn || new_attr->srv6_vpn)
1124 0 : num_sids = 1;
1125 :
1126 0 : if (debug)
1127 0 : zlog_debug(
1128 : "%s: entry: leak-to=%s, p=%pBD, type=%d, sub_type=%d",
1129 : __func__, to_bgp->name_pretty, bn, source_bpi->type,
1130 : source_bpi->sub_type);
1131 :
1132 : /*
1133 : * Routes that are redistributed into BGP from zebra do not get
1134 : * nexthop tracking. However, if those routes are subsequently
1135 : * imported to other RIBs within BGP, the leaked routes do not
1136 : * carry the original BGP_ROUTE_REDISTRIBUTE sub_type. Therefore,
1137 : * in order to determine if the route we are currently leaking
1138 : * should have nexthop tracking, we must find the ultimate
1139 : * parent so we can check its sub_type.
1140 : *
1141 : * As of now, source_bpi may at most be a second-generation route
1142 : * (only one hop back to ultimate parent for vrf-vpn-vrf scheme).
1143 : * Using a loop here supports more complex intra-bgp import-export
1144 : * schemes that could be implemented in the future.
1145 : *
1146 : */
1147 :
1148 : /*
1149 : * match parent
1150 : */
1151 0 : for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next) {
1152 0 : if (bpi->extra && bpi->extra->parent == parent)
1153 : break;
1154 : }
1155 :
1156 0 : if (bpi) {
1157 0 : bool labelssame = labels_same(bpi, label, num_labels);
1158 :
1159 0 : if (CHECK_FLAG(source_bpi->flags, BGP_PATH_REMOVED)
1160 0 : && CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
1161 0 : if (debug) {
1162 0 : zlog_debug(
1163 : "%s: ->%s(s_flags: 0x%x b_flags: 0x%x): %pFX: Found route, being removed, not leaking",
1164 : __func__, to_bgp->name_pretty,
1165 : source_bpi->flags, bpi->flags, p);
1166 : }
1167 0 : return NULL;
1168 : }
1169 :
1170 0 : if (attrhash_cmp(bpi->attr, new_attr) && labelssame
1171 0 : && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
1172 :
1173 0 : bgp_attr_unintern(&new_attr);
1174 0 : if (debug)
1175 0 : zlog_debug(
1176 : "%s: ->%s: %pBD: Found route, no change",
1177 : __func__, to_bgp->name_pretty, bn);
1178 0 : return NULL;
1179 : }
1180 :
1181 : /* If the RT was changed via extended communities as an
1182 : * import/export list, we should withdraw implicitly the old
1183 : * path from VRFs.
1184 : * For instance, RT list was modified using route-maps:
1185 : * route-map test permit 10
1186 : * set extcommunity rt none
1187 : */
1188 0 : if (CHECK_FLAG(bpi->attr->flag,
1189 0 : ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) &&
1190 0 : CHECK_FLAG(new_attr->flag,
1191 : ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
1192 0 : if (!ecommunity_cmp(
1193 0 : bgp_attr_get_ecommunity(bpi->attr),
1194 0 : bgp_attr_get_ecommunity(new_attr))) {
1195 0 : vpn_leak_to_vrf_withdraw(bpi);
1196 0 : bgp_aggregate_decrement(to_bgp, p, bpi, afi,
1197 : safi);
1198 0 : bgp_path_info_delete(bn, bpi);
1199 : }
1200 : }
1201 :
1202 : /* attr is changed */
1203 0 : bgp_path_info_set_flag(bn, bpi, BGP_PATH_ATTR_CHANGED);
1204 :
1205 : /* Rewrite BGP route information. */
1206 0 : if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
1207 0 : bgp_path_info_restore(bn, bpi);
1208 : else
1209 0 : bgp_aggregate_decrement(to_bgp, p, bpi, afi, safi);
1210 0 : bgp_attr_unintern(&bpi->attr);
1211 0 : bpi->attr = new_attr;
1212 0 : bpi->uptime = monotime(NULL);
1213 :
1214 : /*
1215 : * rewrite labels
1216 : */
1217 0 : if (!labelssame)
1218 0 : setlabels(bpi, label, num_labels);
1219 :
1220 : /*
1221 : * rewrite sid
1222 : */
1223 0 : if (num_sids) {
1224 0 : if (new_attr->srv6_l3vpn) {
1225 0 : setsids(bpi, &new_attr->srv6_l3vpn->sid,
1226 : num_sids);
1227 :
1228 0 : extra = bgp_path_info_extra_get(bpi);
1229 :
1230 0 : extra->sid[0].loc_block_len =
1231 0 : new_attr->srv6_l3vpn->loc_block_len;
1232 0 : extra->sid[0].loc_node_len =
1233 0 : new_attr->srv6_l3vpn->loc_node_len;
1234 0 : extra->sid[0].func_len =
1235 0 : new_attr->srv6_l3vpn->func_len;
1236 0 : extra->sid[0].arg_len =
1237 0 : new_attr->srv6_l3vpn->arg_len;
1238 0 : extra->sid[0].transposition_len =
1239 0 : new_attr->srv6_l3vpn->transposition_len;
1240 0 : extra->sid[0].transposition_offset =
1241 : new_attr->srv6_l3vpn
1242 0 : ->transposition_offset;
1243 0 : } else if (new_attr->srv6_vpn)
1244 0 : setsids(bpi, &new_attr->srv6_vpn->sid,
1245 : num_sids);
1246 : } else
1247 0 : unsetsids(bpi);
1248 :
1249 0 : if (nexthop_self_flag)
1250 0 : bgp_path_info_set_flag(bn, bpi, BGP_PATH_ANNC_NH_SELF);
1251 :
1252 0 : if (CHECK_FLAG(source_bpi->flags, BGP_PATH_ACCEPT_OWN))
1253 0 : bgp_path_info_set_flag(bn, bpi, BGP_PATH_ACCEPT_OWN);
1254 :
1255 0 : if (leak_update_nexthop_valid(to_bgp, bn, new_attr, afi, safi,
1256 : source_bpi, bpi, bgp_orig, p,
1257 : debug))
1258 0 : bgp_path_info_set_flag(bn, bpi, BGP_PATH_VALID);
1259 : else
1260 0 : bgp_path_info_unset_flag(bn, bpi, BGP_PATH_VALID);
1261 :
1262 : /* Process change. */
1263 0 : bgp_aggregate_increment(to_bgp, p, bpi, afi, safi);
1264 0 : bgp_process(to_bgp, bn, afi, safi);
1265 0 : bgp_dest_unlock_node(bn);
1266 :
1267 0 : if (debug)
1268 0 : zlog_debug("%s: ->%s: %pBD Found route, changed attr",
1269 : __func__, to_bgp->name_pretty, bn);
1270 :
1271 0 : return bpi;
1272 : }
1273 :
1274 0 : if (CHECK_FLAG(source_bpi->flags, BGP_PATH_REMOVED)) {
1275 0 : if (debug) {
1276 0 : zlog_debug(
1277 : "%s: ->%s(s_flags: 0x%x): %pFX: New route, being removed, not leaking",
1278 : __func__, to_bgp->name_pretty,
1279 : source_bpi->flags, p);
1280 : }
1281 0 : return NULL;
1282 : }
1283 :
1284 0 : new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_IMPORTED, 0,
1285 : to_bgp->peer_self, new_attr, bn);
1286 :
1287 0 : if (source_bpi->peer) {
1288 0 : extra = bgp_path_info_extra_get(new);
1289 0 : extra->peer_orig = peer_lock(source_bpi->peer);
1290 : }
1291 :
1292 0 : if (nexthop_self_flag)
1293 0 : bgp_path_info_set_flag(bn, new, BGP_PATH_ANNC_NH_SELF);
1294 :
1295 0 : if (CHECK_FLAG(source_bpi->flags, BGP_PATH_ACCEPT_OWN))
1296 0 : bgp_path_info_set_flag(bn, new, BGP_PATH_ACCEPT_OWN);
1297 :
1298 0 : bgp_path_info_extra_get(new);
1299 :
1300 : /*
1301 : * rewrite sid
1302 : */
1303 0 : if (num_sids) {
1304 0 : if (new_attr->srv6_l3vpn) {
1305 0 : setsids(new, &new_attr->srv6_l3vpn->sid, num_sids);
1306 :
1307 0 : extra = bgp_path_info_extra_get(new);
1308 :
1309 0 : extra->sid[0].loc_block_len =
1310 0 : new_attr->srv6_l3vpn->loc_block_len;
1311 0 : extra->sid[0].loc_node_len =
1312 0 : new_attr->srv6_l3vpn->loc_node_len;
1313 0 : extra->sid[0].func_len = new_attr->srv6_l3vpn->func_len;
1314 0 : extra->sid[0].arg_len = new_attr->srv6_l3vpn->arg_len;
1315 0 : extra->sid[0].transposition_len =
1316 0 : new_attr->srv6_l3vpn->transposition_len;
1317 0 : extra->sid[0].transposition_offset =
1318 0 : new_attr->srv6_l3vpn->transposition_offset;
1319 0 : } else if (new_attr->srv6_vpn)
1320 0 : setsids(new, &new_attr->srv6_vpn->sid, num_sids);
1321 : } else
1322 0 : unsetsids(new);
1323 :
1324 0 : if (num_labels)
1325 0 : setlabels(new, label, num_labels);
1326 :
1327 0 : new->extra->parent = bgp_path_info_lock(parent);
1328 0 : bgp_dest_lock_node(
1329 : (struct bgp_dest *)((struct bgp_path_info *)parent)->net);
1330 0 : if (bgp_orig)
1331 0 : new->extra->bgp_orig = bgp_lock(bgp_orig);
1332 0 : if (nexthop_orig)
1333 0 : new->extra->nexthop_orig = *nexthop_orig;
1334 :
1335 0 : if (leak_update_nexthop_valid(to_bgp, bn, new_attr, afi, safi,
1336 : source_bpi, new, bgp_orig, p, debug))
1337 0 : bgp_path_info_set_flag(bn, new, BGP_PATH_VALID);
1338 : else
1339 0 : bgp_path_info_unset_flag(bn, new, BGP_PATH_VALID);
1340 :
1341 0 : bgp_aggregate_increment(to_bgp, p, new, afi, safi);
1342 0 : bgp_path_info_add(bn, new);
1343 :
1344 0 : bgp_dest_unlock_node(bn);
1345 0 : bgp_process(to_bgp, bn, afi, safi);
1346 :
1347 0 : if (debug)
1348 0 : zlog_debug("%s: ->%s: %pBD: Added new route", __func__,
1349 : to_bgp->name_pretty, bn);
1350 :
1351 : return new;
1352 : }
1353 :
1354 : /* cf vnc_import_bgp_add_route_mode_nvegroup() and add_vnc_route() */
1355 14 : void vpn_leak_from_vrf_update(struct bgp *to_bgp, /* to */
1356 : struct bgp *from_bgp, /* from */
1357 : struct bgp_path_info *path_vrf) /* route */
1358 : {
1359 14 : int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF);
1360 14 : const struct prefix *p = bgp_dest_get_prefix(path_vrf->net);
1361 14 : afi_t afi = family2afi(p->family);
1362 14 : struct attr static_attr = {0};
1363 14 : struct attr *new_attr = NULL;
1364 14 : safi_t safi = SAFI_MPLS_VPN;
1365 14 : mpls_label_t label_val;
1366 14 : mpls_label_t label;
1367 14 : struct bgp_dest *bn;
1368 14 : const char *debugmsg;
1369 14 : int nexthop_self_flag = 0;
1370 :
1371 14 : if (debug)
1372 0 : zlog_debug("%s: from vrf %s", __func__, from_bgp->name_pretty);
1373 :
1374 0 : if (debug && bgp_attr_get_ecommunity(path_vrf->attr)) {
1375 0 : char *s = ecommunity_ecom2str(
1376 0 : bgp_attr_get_ecommunity(path_vrf->attr),
1377 : ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
1378 :
1379 0 : zlog_debug("%s: %s path_vrf->type=%d, EC{%s}", __func__,
1380 : from_bgp->name, path_vrf->type, s);
1381 0 : XFREE(MTYPE_ECOMMUNITY_STR, s);
1382 : }
1383 :
1384 14 : if (!to_bgp)
1385 14 : return;
1386 :
1387 14 : if (!afi) {
1388 0 : if (debug)
1389 0 : zlog_debug("%s: can't get afi of prefix", __func__);
1390 0 : return;
1391 : }
1392 :
1393 : /* Is this route exportable into the VPN table? */
1394 14 : if (!is_route_injectable_into_vpn(path_vrf))
1395 : return;
1396 :
1397 14 : if (!vpn_leak_to_vpn_active(from_bgp, afi, &debugmsg)) {
1398 14 : if (debug)
1399 0 : zlog_debug("%s: %s skipping: %s", __func__,
1400 : from_bgp->name, debugmsg);
1401 14 : return;
1402 : }
1403 :
1404 : /* shallow copy */
1405 0 : static_attr = *path_vrf->attr;
1406 :
1407 : /*
1408 : * route map handling
1409 : */
1410 0 : if (from_bgp->vpn_policy[afi].rmap[BGP_VPN_POLICY_DIR_TOVPN]) {
1411 0 : struct bgp_path_info info;
1412 0 : route_map_result_t ret;
1413 :
1414 0 : memset(&info, 0, sizeof(info));
1415 0 : info.peer = to_bgp->peer_self;
1416 0 : info.attr = &static_attr;
1417 0 : ret = route_map_apply(from_bgp->vpn_policy[afi]
1418 : .rmap[BGP_VPN_POLICY_DIR_TOVPN],
1419 : p, &info);
1420 0 : if (RMAP_DENYMATCH == ret) {
1421 0 : bgp_attr_flush(&static_attr); /* free any added parts */
1422 0 : if (debug)
1423 0 : zlog_debug(
1424 : "%s: vrf %s route map \"%s\" says DENY, returning",
1425 : __func__, from_bgp->name_pretty,
1426 : from_bgp->vpn_policy[afi]
1427 : .rmap[BGP_VPN_POLICY_DIR_TOVPN]
1428 : ->name);
1429 0 : return;
1430 : }
1431 : }
1432 :
1433 0 : if (debug && bgp_attr_get_ecommunity(&static_attr)) {
1434 0 : char *s = ecommunity_ecom2str(
1435 : bgp_attr_get_ecommunity(&static_attr),
1436 : ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
1437 :
1438 0 : zlog_debug("%s: post route map static_attr.ecommunity{%s}",
1439 : __func__, s);
1440 0 : XFREE(MTYPE_ECOMMUNITY_STR, s);
1441 : }
1442 :
1443 : /*
1444 : * Add the vpn-policy rt-list
1445 : */
1446 0 : struct ecommunity *old_ecom;
1447 0 : struct ecommunity *new_ecom;
1448 :
1449 : /* Export with the 'from' instance's export RTs. */
1450 : /* If doing VRF-to-VRF leaking, strip existing RTs first. */
1451 0 : old_ecom = bgp_attr_get_ecommunity(&static_attr);
1452 0 : if (old_ecom) {
1453 0 : new_ecom = ecommunity_dup(old_ecom);
1454 0 : if (CHECK_FLAG(from_bgp->af_flags[afi][SAFI_UNICAST],
1455 : BGP_CONFIG_VRF_TO_VRF_EXPORT))
1456 0 : ecommunity_strip_rts(new_ecom);
1457 0 : new_ecom = ecommunity_merge(
1458 : new_ecom, from_bgp->vpn_policy[afi]
1459 : .rtlist[BGP_VPN_POLICY_DIR_TOVPN]);
1460 0 : if (!old_ecom->refcnt)
1461 0 : ecommunity_free(&old_ecom);
1462 : } else {
1463 0 : new_ecom = ecommunity_dup(
1464 : from_bgp->vpn_policy[afi]
1465 : .rtlist[BGP_VPN_POLICY_DIR_TOVPN]);
1466 : }
1467 0 : bgp_attr_set_ecommunity(&static_attr, new_ecom);
1468 :
1469 0 : if (debug && bgp_attr_get_ecommunity(&static_attr)) {
1470 0 : char *s = ecommunity_ecom2str(
1471 : bgp_attr_get_ecommunity(&static_attr),
1472 : ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
1473 :
1474 0 : zlog_debug("%s: post merge static_attr.ecommunity{%s}",
1475 : __func__, s);
1476 0 : XFREE(MTYPE_ECOMMUNITY_STR, s);
1477 : }
1478 :
1479 0 : community_strip_accept_own(&static_attr);
1480 :
1481 : /* Nexthop */
1482 : /* if policy nexthop not set, use 0 */
1483 0 : if (CHECK_FLAG(from_bgp->vpn_policy[afi].flags,
1484 : BGP_VPN_POLICY_TOVPN_NEXTHOP_SET)) {
1485 0 : struct prefix *nexthop =
1486 : &from_bgp->vpn_policy[afi].tovpn_nexthop;
1487 :
1488 0 : switch (nexthop->family) {
1489 0 : case AF_INET:
1490 : /* prevent mp_nexthop_global_in <- self in bgp_route.c
1491 : */
1492 0 : static_attr.nexthop.s_addr = nexthop->u.prefix4.s_addr;
1493 :
1494 0 : static_attr.mp_nexthop_global_in = nexthop->u.prefix4;
1495 0 : static_attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
1496 0 : break;
1497 :
1498 0 : case AF_INET6:
1499 0 : static_attr.mp_nexthop_global = nexthop->u.prefix6;
1500 0 : static_attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
1501 0 : break;
1502 :
1503 : default:
1504 0 : assert(0);
1505 : }
1506 : } else {
1507 0 : if (!CHECK_FLAG(from_bgp->af_flags[afi][SAFI_UNICAST],
1508 : BGP_CONFIG_VRF_TO_VRF_EXPORT)) {
1509 0 : if (afi == AFI_IP &&
1510 0 : !BGP_ATTR_NEXTHOP_AFI_IP6(path_vrf->attr)) {
1511 : /*
1512 : * For ipv4, copy to multiprotocol
1513 : * nexthop field
1514 : */
1515 0 : static_attr.mp_nexthop_global_in =
1516 : static_attr.nexthop;
1517 0 : static_attr.mp_nexthop_len =
1518 : BGP_ATTR_NHLEN_IPV4;
1519 : /*
1520 : * XXX Leave static_attr.nexthop
1521 : * intact for NHT
1522 : */
1523 0 : static_attr.flag &=
1524 : ~ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
1525 : }
1526 : } else {
1527 : /* Update based on next-hop family to account for
1528 : * RFC 5549 (BGP unnumbered) scenario. Note that
1529 : * specific action is only needed for the case of
1530 : * IPv4 nexthops as the attr has been copied
1531 : * otherwise.
1532 : */
1533 0 : if (afi == AFI_IP
1534 0 : && !BGP_ATTR_NEXTHOP_AFI_IP6(path_vrf->attr)) {
1535 0 : static_attr.mp_nexthop_global_in.s_addr =
1536 0 : static_attr.nexthop.s_addr;
1537 0 : static_attr.mp_nexthop_len =
1538 : BGP_ATTR_NHLEN_IPV4;
1539 0 : static_attr.flag |=
1540 : ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
1541 : }
1542 : }
1543 : nexthop_self_flag = 1;
1544 : }
1545 :
1546 0 : label_val = from_bgp->vpn_policy[afi].tovpn_label;
1547 0 : if (label_val == MPLS_LABEL_NONE) {
1548 0 : encode_label(MPLS_LABEL_IMPLICIT_NULL, &label);
1549 : } else {
1550 0 : encode_label(label_val, &label);
1551 : }
1552 :
1553 : /* Set originator ID to "me" */
1554 0 : SET_FLAG(static_attr.flag, ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID));
1555 0 : static_attr.originator_id = to_bgp->router_id;
1556 :
1557 : /* Set SID for SRv6 VPN */
1558 0 : if (from_bgp->vpn_policy[afi].tovpn_sid_locator) {
1559 0 : struct srv6_locator_chunk *locator =
1560 : from_bgp->vpn_policy[afi].tovpn_sid_locator;
1561 0 : encode_label(
1562 : from_bgp->vpn_policy[afi].tovpn_sid_transpose_label,
1563 : &label);
1564 0 : static_attr.srv6_l3vpn = XCALLOC(MTYPE_BGP_SRV6_L3VPN,
1565 : sizeof(struct bgp_attr_srv6_l3vpn));
1566 0 : static_attr.srv6_l3vpn->sid_flags = 0x00;
1567 0 : static_attr.srv6_l3vpn->endpoint_behavior =
1568 : afi == AFI_IP
1569 0 : ? (CHECK_FLAG(locator->flags, SRV6_LOCATOR_USID)
1570 : ? SRV6_ENDPOINT_BEHAVIOR_END_DT4_USID
1571 : : SRV6_ENDPOINT_BEHAVIOR_END_DT4)
1572 0 : : (CHECK_FLAG(locator->flags, SRV6_LOCATOR_USID)
1573 : ? SRV6_ENDPOINT_BEHAVIOR_END_DT6_USID
1574 : : SRV6_ENDPOINT_BEHAVIOR_END_DT6);
1575 0 : static_attr.srv6_l3vpn->loc_block_len =
1576 : from_bgp->vpn_policy[afi]
1577 0 : .tovpn_sid_locator->block_bits_length;
1578 0 : static_attr.srv6_l3vpn->loc_node_len =
1579 : from_bgp->vpn_policy[afi]
1580 0 : .tovpn_sid_locator->node_bits_length;
1581 0 : static_attr.srv6_l3vpn->func_len =
1582 : from_bgp->vpn_policy[afi]
1583 0 : .tovpn_sid_locator->function_bits_length;
1584 0 : static_attr.srv6_l3vpn->arg_len =
1585 : from_bgp->vpn_policy[afi]
1586 0 : .tovpn_sid_locator->argument_bits_length;
1587 0 : static_attr.srv6_l3vpn->transposition_len =
1588 : from_bgp->vpn_policy[afi]
1589 : .tovpn_sid_locator->function_bits_length;
1590 0 : static_attr.srv6_l3vpn->transposition_offset =
1591 : from_bgp->vpn_policy[afi]
1592 0 : .tovpn_sid_locator->block_bits_length +
1593 : from_bgp->vpn_policy[afi]
1594 : .tovpn_sid_locator->node_bits_length;
1595 0 : ;
1596 0 : memcpy(&static_attr.srv6_l3vpn->sid,
1597 : &from_bgp->vpn_policy[afi]
1598 : .tovpn_sid_locator->prefix.prefix,
1599 : sizeof(struct in6_addr));
1600 0 : } else if (from_bgp->tovpn_sid_locator) {
1601 0 : struct srv6_locator_chunk *locator =
1602 : from_bgp->tovpn_sid_locator;
1603 0 : encode_label(from_bgp->tovpn_sid_transpose_label, &label);
1604 0 : static_attr.srv6_l3vpn =
1605 0 : XCALLOC(MTYPE_BGP_SRV6_L3VPN,
1606 : sizeof(struct bgp_attr_srv6_l3vpn));
1607 0 : static_attr.srv6_l3vpn->sid_flags = 0x00;
1608 0 : static_attr.srv6_l3vpn->endpoint_behavior =
1609 0 : CHECK_FLAG(locator->flags, SRV6_LOCATOR_USID)
1610 : ? SRV6_ENDPOINT_BEHAVIOR_END_DT46_USID
1611 : : SRV6_ENDPOINT_BEHAVIOR_END_DT46;
1612 0 : static_attr.srv6_l3vpn->loc_block_len =
1613 0 : from_bgp->tovpn_sid_locator->block_bits_length;
1614 0 : static_attr.srv6_l3vpn->loc_node_len =
1615 0 : from_bgp->tovpn_sid_locator->node_bits_length;
1616 0 : static_attr.srv6_l3vpn->func_len =
1617 0 : from_bgp->tovpn_sid_locator->function_bits_length;
1618 0 : static_attr.srv6_l3vpn->arg_len =
1619 0 : from_bgp->tovpn_sid_locator->argument_bits_length;
1620 0 : static_attr.srv6_l3vpn->transposition_len =
1621 : from_bgp->tovpn_sid_locator->function_bits_length;
1622 0 : static_attr.srv6_l3vpn->transposition_offset =
1623 0 : from_bgp->tovpn_sid_locator->block_bits_length +
1624 : from_bgp->tovpn_sid_locator->node_bits_length;
1625 0 : memcpy(&static_attr.srv6_l3vpn->sid,
1626 : &from_bgp->tovpn_sid_locator->prefix.prefix,
1627 : sizeof(struct in6_addr));
1628 : }
1629 :
1630 :
1631 0 : new_attr = bgp_attr_intern(
1632 : &static_attr); /* hashed refcounted everything */
1633 0 : bgp_attr_flush(&static_attr); /* free locally-allocated parts */
1634 :
1635 0 : if (debug && bgp_attr_get_ecommunity(new_attr)) {
1636 0 : char *s = ecommunity_ecom2str(bgp_attr_get_ecommunity(new_attr),
1637 : ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
1638 :
1639 0 : zlog_debug("%s: new_attr->ecommunity{%s}", __func__, s);
1640 0 : XFREE(MTYPE_ECOMMUNITY_STR, s);
1641 : }
1642 :
1643 : /* Now new_attr is an allocated interned attr */
1644 :
1645 0 : bn = bgp_afi_node_get(to_bgp->rib[afi][safi], afi, safi, p,
1646 : &(from_bgp->vpn_policy[afi].tovpn_rd));
1647 :
1648 0 : struct bgp_path_info *new_info;
1649 :
1650 0 : new_info =
1651 0 : leak_update(to_bgp, bn, new_attr, afi, safi, path_vrf, &label,
1652 : 1, from_bgp, NULL, nexthop_self_flag, debug);
1653 :
1654 : /*
1655 : * Routes actually installed in the vpn RIB must also be
1656 : * offered to all vrfs (because now they originate from
1657 : * the vpn RIB).
1658 : *
1659 : * Acceptance into other vrfs depends on rt-lists.
1660 : * Originating vrf will not accept the looped back route
1661 : * because of loop checking.
1662 : */
1663 0 : if (new_info)
1664 0 : vpn_leak_to_vrf_update(from_bgp, new_info, NULL);
1665 : }
1666 :
1667 12 : void vpn_leak_from_vrf_withdraw(struct bgp *to_bgp, /* to */
1668 : struct bgp *from_bgp, /* from */
1669 : struct bgp_path_info *path_vrf) /* route */
1670 : {
1671 12 : int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF);
1672 12 : const struct prefix *p = bgp_dest_get_prefix(path_vrf->net);
1673 12 : afi_t afi = family2afi(p->family);
1674 12 : safi_t safi = SAFI_MPLS_VPN;
1675 12 : struct bgp_path_info *bpi;
1676 12 : struct bgp_dest *bn;
1677 12 : const char *debugmsg;
1678 :
1679 12 : if (debug) {
1680 0 : zlog_debug(
1681 : "%s: entry: leak-from=%s, p=%pBD, type=%d, sub_type=%d",
1682 : __func__, from_bgp->name_pretty, path_vrf->net,
1683 : path_vrf->type, path_vrf->sub_type);
1684 : }
1685 :
1686 12 : if (!to_bgp)
1687 12 : return;
1688 :
1689 12 : if (!afi) {
1690 0 : if (debug)
1691 0 : zlog_debug("%s: can't get afi of prefix", __func__);
1692 0 : return;
1693 : }
1694 :
1695 : /* Is this route exportable into the VPN table? */
1696 12 : if (!is_route_injectable_into_vpn(path_vrf))
1697 : return;
1698 :
1699 12 : if (!vpn_leak_to_vpn_active(from_bgp, afi, &debugmsg)) {
1700 12 : if (debug)
1701 0 : zlog_debug("%s: skipping: %s", __func__, debugmsg);
1702 12 : return;
1703 : }
1704 :
1705 0 : if (debug)
1706 0 : zlog_debug("%s: withdrawing (path_vrf=%p)", __func__, path_vrf);
1707 :
1708 0 : bn = bgp_afi_node_get(to_bgp->rib[afi][safi], afi, safi, p,
1709 : &(from_bgp->vpn_policy[afi].tovpn_rd));
1710 :
1711 0 : if (!bn)
1712 : return;
1713 : /*
1714 : * vrf -> vpn
1715 : * match original bpi imported from
1716 : */
1717 0 : for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next) {
1718 0 : if (bpi->extra && bpi->extra->parent == path_vrf) {
1719 : break;
1720 : }
1721 : }
1722 :
1723 0 : if (bpi) {
1724 : /* withdraw from looped vrfs as well */
1725 0 : vpn_leak_to_vrf_withdraw(bpi);
1726 :
1727 0 : bgp_aggregate_decrement(to_bgp, p, bpi, afi, safi);
1728 0 : bgp_path_info_delete(bn, bpi);
1729 0 : bgp_process(to_bgp, bn, afi, safi);
1730 : }
1731 0 : bgp_dest_unlock_node(bn);
1732 : }
1733 :
1734 0 : void vpn_leak_from_vrf_withdraw_all(struct bgp *to_bgp, struct bgp *from_bgp,
1735 : afi_t afi)
1736 : {
1737 0 : int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF);
1738 0 : struct bgp_dest *pdest;
1739 0 : safi_t safi = SAFI_MPLS_VPN;
1740 :
1741 : /*
1742 : * Walk vpn table, delete bpi with bgp_orig == from_bgp
1743 : */
1744 0 : for (pdest = bgp_table_top(to_bgp->rib[afi][safi]); pdest;
1745 0 : pdest = bgp_route_next(pdest)) {
1746 :
1747 0 : struct bgp_table *table;
1748 0 : struct bgp_dest *bn;
1749 0 : struct bgp_path_info *bpi;
1750 :
1751 : /* This is the per-RD table of prefixes */
1752 0 : table = bgp_dest_get_bgp_table_info(pdest);
1753 :
1754 0 : if (!table)
1755 0 : continue;
1756 :
1757 0 : for (bn = bgp_table_top(table); bn; bn = bgp_route_next(bn)) {
1758 0 : bpi = bgp_dest_get_bgp_path_info(bn);
1759 0 : if (debug && bpi) {
1760 0 : zlog_debug("%s: looking at prefix %pBD",
1761 : __func__, bn);
1762 : }
1763 :
1764 0 : for (; bpi; bpi = bpi->next) {
1765 0 : if (debug)
1766 0 : zlog_debug("%s: type %d, sub_type %d",
1767 : __func__, bpi->type,
1768 : bpi->sub_type);
1769 0 : if (bpi->sub_type != BGP_ROUTE_IMPORTED)
1770 0 : continue;
1771 0 : if (!bpi->extra)
1772 0 : continue;
1773 0 : if ((struct bgp *)bpi->extra->bgp_orig ==
1774 : from_bgp) {
1775 : /* delete route */
1776 0 : if (debug)
1777 0 : zlog_debug("%s: deleting it",
1778 : __func__);
1779 : /* withdraw from leak-to vrfs as well */
1780 0 : vpn_leak_to_vrf_withdraw(bpi);
1781 0 : bgp_aggregate_decrement(
1782 : to_bgp, bgp_dest_get_prefix(bn),
1783 : bpi, afi, safi);
1784 0 : bgp_path_info_delete(bn, bpi);
1785 0 : bgp_process(to_bgp, bn, afi, safi);
1786 : }
1787 : }
1788 : }
1789 : }
1790 0 : }
1791 :
1792 0 : void vpn_leak_from_vrf_update_all(struct bgp *to_bgp, struct bgp *from_bgp,
1793 : afi_t afi)
1794 : {
1795 0 : struct bgp_dest *bn;
1796 0 : struct bgp_path_info *bpi;
1797 0 : int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF);
1798 :
1799 0 : if (debug)
1800 0 : zlog_debug("%s: entry, afi=%d, vrf=%s", __func__, afi,
1801 : from_bgp->name_pretty);
1802 :
1803 0 : for (bn = bgp_table_top(from_bgp->rib[afi][SAFI_UNICAST]); bn;
1804 0 : bn = bgp_route_next(bn)) {
1805 :
1806 0 : if (debug)
1807 0 : zlog_debug("%s: node=%p", __func__, bn);
1808 :
1809 0 : for (bpi = bgp_dest_get_bgp_path_info(bn); bpi;
1810 0 : bpi = bpi->next) {
1811 0 : if (debug)
1812 0 : zlog_debug(
1813 : "%s: calling vpn_leak_from_vrf_update",
1814 : __func__);
1815 0 : vpn_leak_from_vrf_update(to_bgp, from_bgp, bpi);
1816 : }
1817 : }
1818 0 : }
1819 :
1820 0 : static struct bgp *bgp_lookup_by_rd(struct bgp_path_info *bpi,
1821 : struct prefix_rd *rd, afi_t afi)
1822 : {
1823 0 : struct listnode *node, *nnode;
1824 0 : struct bgp *bgp;
1825 :
1826 0 : if (!rd)
1827 : return NULL;
1828 :
1829 : /* If ACCEPT_OWN is not enabled for this path - return. */
1830 0 : if (!CHECK_FLAG(bpi->flags, BGP_PATH_ACCEPT_OWN))
1831 : return NULL;
1832 :
1833 0 : for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
1834 0 : if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
1835 0 : continue;
1836 :
1837 0 : if (!CHECK_FLAG(bgp->vpn_policy[afi].flags,
1838 : BGP_VPN_POLICY_TOVPN_RD_SET))
1839 0 : continue;
1840 :
1841 : /* Check if we have source VRF by RD value */
1842 0 : if (memcmp(&bgp->vpn_policy[afi].tovpn_rd.val, rd->val,
1843 : ECOMMUNITY_SIZE) == 0)
1844 0 : return bgp;
1845 : }
1846 :
1847 : return NULL;
1848 : }
1849 :
1850 0 : static bool vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
1851 : struct bgp *from_bgp, /* from */
1852 : struct bgp_path_info *path_vpn,
1853 : struct prefix_rd *prd)
1854 : {
1855 0 : const struct prefix *p = bgp_dest_get_prefix(path_vpn->net);
1856 0 : afi_t afi = family2afi(p->family);
1857 :
1858 0 : struct attr static_attr = {0};
1859 0 : struct attr *new_attr = NULL;
1860 0 : struct bgp_dest *bn;
1861 0 : safi_t safi = SAFI_UNICAST;
1862 0 : const char *debugmsg;
1863 0 : struct prefix nexthop_orig;
1864 0 : mpls_label_t *pLabels = NULL;
1865 0 : uint32_t num_labels = 0;
1866 0 : int nexthop_self_flag = 1;
1867 0 : struct bgp_path_info *bpi_ultimate = NULL;
1868 0 : int origin_local = 0;
1869 0 : struct bgp *src_vrf;
1870 0 : struct interface *ifp;
1871 :
1872 0 : int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF);
1873 :
1874 0 : if (!vpn_leak_from_vpn_active(to_bgp, afi, &debugmsg)) {
1875 0 : if (debug)
1876 0 : zlog_debug(
1877 : "%s: from vpn (%s) to vrf (%s), skipping: %s",
1878 : __func__, from_bgp->name_pretty,
1879 : to_bgp->name_pretty, debugmsg);
1880 0 : return false;
1881 : }
1882 :
1883 : /*
1884 : * For VRF-2-VRF route-leaking,
1885 : * the source will be the originating VRF.
1886 : *
1887 : * If ACCEPT_OWN mechanism is enabled, then we SHOULD(?)
1888 : * get the source VRF (BGP) by looking at the RD.
1889 : */
1890 0 : struct bgp *src_bgp = bgp_lookup_by_rd(path_vpn, prd, afi);
1891 :
1892 0 : if (path_vpn->extra && path_vpn->extra->bgp_orig)
1893 : src_vrf = path_vpn->extra->bgp_orig;
1894 0 : else if (src_bgp)
1895 : src_vrf = src_bgp;
1896 : else
1897 0 : src_vrf = from_bgp;
1898 :
1899 : /* Check for intersection of route targets */
1900 0 : if (!ecommunity_include(
1901 : to_bgp->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_FROMVPN],
1902 0 : bgp_attr_get_ecommunity(path_vpn->attr))) {
1903 0 : if (debug)
1904 0 : zlog_debug(
1905 : "from vpn (%s) to vrf (%s), skipping after no intersection of route targets",
1906 : from_bgp->name_pretty, to_bgp->name_pretty);
1907 0 : return false;
1908 : }
1909 :
1910 : /* A route MUST NOT ever be accepted back into its source VRF, even if
1911 : * it carries one or more RTs that match that VRF.
1912 : */
1913 0 : if (CHECK_FLAG(path_vpn->flags, BGP_PATH_ACCEPT_OWN) && prd &&
1914 0 : memcmp(&prd->val, &to_bgp->vpn_policy[afi].tovpn_rd.val,
1915 : ECOMMUNITY_SIZE) == 0) {
1916 0 : if (debug)
1917 0 : zlog_debug(
1918 : "%s: skipping import, match RD (%pRD) of src VRF (%s) and the prefix (%pFX)",
1919 : __func__, prd, to_bgp->name_pretty, p);
1920 :
1921 0 : return false;
1922 : }
1923 :
1924 0 : if (debug)
1925 0 : zlog_debug("%s: updating RD %pRD, %pFX to %s", __func__, prd, p,
1926 : to_bgp->name_pretty);
1927 :
1928 : /* shallow copy */
1929 0 : static_attr = *path_vpn->attr;
1930 :
1931 0 : struct ecommunity *old_ecom;
1932 0 : struct ecommunity *new_ecom;
1933 :
1934 : /* If doing VRF-to-VRF leaking, strip RTs. */
1935 0 : old_ecom = bgp_attr_get_ecommunity(&static_attr);
1936 0 : if (old_ecom && CHECK_FLAG(to_bgp->af_flags[afi][safi],
1937 : BGP_CONFIG_VRF_TO_VRF_IMPORT)) {
1938 0 : new_ecom = ecommunity_dup(old_ecom);
1939 0 : ecommunity_strip_rts(new_ecom);
1940 0 : bgp_attr_set_ecommunity(&static_attr, new_ecom);
1941 :
1942 0 : if (new_ecom->size == 0) {
1943 0 : ecommunity_free(&new_ecom);
1944 0 : bgp_attr_set_ecommunity(&static_attr, NULL);
1945 : }
1946 :
1947 0 : if (!old_ecom->refcnt)
1948 0 : ecommunity_free(&old_ecom);
1949 : }
1950 :
1951 0 : community_strip_accept_own(&static_attr);
1952 :
1953 : /*
1954 : * Nexthop: stash and clear
1955 : *
1956 : * Nexthop is valid in context of VPN core, but not in destination vrf.
1957 : * Stash it for later label resolution by vrf ingress path and then
1958 : * overwrite with 0, i.e., "me", for the sake of vrf advertisement.
1959 : */
1960 0 : uint8_t nhfamily = NEXTHOP_FAMILY(path_vpn->attr->mp_nexthop_len);
1961 :
1962 0 : memset(&nexthop_orig, 0, sizeof(nexthop_orig));
1963 0 : nexthop_orig.family = nhfamily;
1964 :
1965 : /* If the path has accept-own community and the source VRF
1966 : * is valid, reset next-hop to self, to allow importing own
1967 : * routes between different VRFs on the same node.
1968 : * Set the nh ifindex to VRF's interface, not the real interface.
1969 : * Let the kernel to decide with double lookup the real next-hop
1970 : * interface when installing the route.
1971 : */
1972 0 : if (src_bgp) {
1973 0 : subgroup_announce_reset_nhop(nhfamily, &static_attr);
1974 0 : ifp = if_get_vrf_loopback(src_vrf->vrf_id);
1975 0 : if (ifp)
1976 0 : static_attr.nh_ifindex = ifp->ifindex;
1977 : }
1978 :
1979 0 : switch (nhfamily) {
1980 0 : case AF_INET:
1981 : /* save */
1982 0 : nexthop_orig.u.prefix4 = path_vpn->attr->mp_nexthop_global_in;
1983 0 : nexthop_orig.prefixlen = IPV4_MAX_BITLEN;
1984 :
1985 0 : if (CHECK_FLAG(to_bgp->af_flags[afi][safi],
1986 : BGP_CONFIG_VRF_TO_VRF_IMPORT)) {
1987 0 : static_attr.nexthop.s_addr =
1988 0 : nexthop_orig.u.prefix4.s_addr;
1989 :
1990 0 : static_attr.mp_nexthop_global_in =
1991 : path_vpn->attr->mp_nexthop_global_in;
1992 0 : static_attr.mp_nexthop_len =
1993 0 : path_vpn->attr->mp_nexthop_len;
1994 : }
1995 0 : static_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
1996 0 : break;
1997 0 : case AF_INET6:
1998 : /* save */
1999 0 : nexthop_orig.u.prefix6 = path_vpn->attr->mp_nexthop_global;
2000 0 : nexthop_orig.prefixlen = IPV6_MAX_BITLEN;
2001 :
2002 0 : if (CHECK_FLAG(to_bgp->af_flags[afi][safi],
2003 : BGP_CONFIG_VRF_TO_VRF_IMPORT)) {
2004 0 : static_attr.mp_nexthop_global = nexthop_orig.u.prefix6;
2005 : }
2006 : break;
2007 : }
2008 :
2009 : /*
2010 : * route map handling
2011 : */
2012 0 : if (to_bgp->vpn_policy[afi].rmap[BGP_VPN_POLICY_DIR_FROMVPN]) {
2013 0 : struct bgp_path_info info;
2014 0 : route_map_result_t ret;
2015 :
2016 0 : memset(&info, 0, sizeof(info));
2017 0 : info.peer = to_bgp->peer_self;
2018 0 : info.attr = &static_attr;
2019 0 : info.extra = path_vpn->extra; /* Used for source-vrf filter */
2020 0 : ret = route_map_apply(to_bgp->vpn_policy[afi]
2021 : .rmap[BGP_VPN_POLICY_DIR_FROMVPN],
2022 : p, &info);
2023 0 : if (RMAP_DENYMATCH == ret) {
2024 0 : bgp_attr_flush(&static_attr); /* free any added parts */
2025 0 : if (debug)
2026 0 : zlog_debug(
2027 : "%s: vrf %s vpn-policy route map \"%s\" says DENY, returning",
2028 : __func__, to_bgp->name_pretty,
2029 : to_bgp->vpn_policy[afi]
2030 : .rmap[BGP_VPN_POLICY_DIR_FROMVPN]
2031 : ->name);
2032 0 : return false;
2033 : }
2034 : /*
2035 : * if route-map changed nexthop, don't nexthop-self on output
2036 : */
2037 0 : if (!CHECK_FLAG(static_attr.rmap_change_flags,
2038 : BATTR_RMAP_NEXTHOP_UNCHANGED))
2039 0 : nexthop_self_flag = 0;
2040 : }
2041 :
2042 0 : new_attr = bgp_attr_intern(&static_attr);
2043 0 : bgp_attr_flush(&static_attr);
2044 :
2045 0 : bn = bgp_afi_node_get(to_bgp->rib[afi][safi], afi, safi, p, NULL);
2046 :
2047 : /*
2048 : * ensure labels are copied
2049 : *
2050 : * However, there is a special case: if the route originated in
2051 : * another local VRF (as opposed to arriving via VPN), then the
2052 : * nexthop is reached by hairpinning through this router (me)
2053 : * using IP forwarding only (no LSP). Therefore, the route
2054 : * imported to the VRF should not have labels attached. Note
2055 : * that nexthop tracking is also involved: eliminating the
2056 : * labels for these routes enables the non-labeled nexthops
2057 : * from the originating VRF to be considered valid for this route.
2058 : */
2059 0 : if (!CHECK_FLAG(to_bgp->af_flags[afi][safi],
2060 : BGP_CONFIG_VRF_TO_VRF_IMPORT)) {
2061 : /* work back to original route */
2062 0 : bpi_ultimate = bgp_get_imported_bpi_ultimate(path_vpn);
2063 :
2064 : /*
2065 : * if original route was unicast,
2066 : * then it did not arrive over vpn
2067 : */
2068 0 : if (bpi_ultimate->net) {
2069 0 : struct bgp_table *table;
2070 :
2071 0 : table = bgp_dest_table(bpi_ultimate->net);
2072 0 : if (table && (table->safi == SAFI_UNICAST))
2073 : origin_local = 1;
2074 : }
2075 :
2076 : /* copy labels */
2077 0 : if (!origin_local && path_vpn->extra
2078 0 : && path_vpn->extra->num_labels) {
2079 0 : num_labels = path_vpn->extra->num_labels;
2080 0 : if (num_labels > BGP_MAX_LABELS)
2081 : num_labels = BGP_MAX_LABELS;
2082 0 : pLabels = path_vpn->extra->label;
2083 : }
2084 : }
2085 :
2086 0 : if (debug)
2087 0 : zlog_debug("%s: pfx %pBD: num_labels %d", __func__,
2088 : path_vpn->net, num_labels);
2089 :
2090 0 : leak_update(to_bgp, bn, new_attr, afi, safi, path_vpn, pLabels,
2091 : num_labels, src_vrf, &nexthop_orig, nexthop_self_flag,
2092 : debug);
2093 0 : return true;
2094 : }
2095 :
2096 0 : bool vpn_leak_to_vrf_update(struct bgp *from_bgp,
2097 : struct bgp_path_info *path_vpn,
2098 : struct prefix_rd *prd)
2099 : {
2100 0 : struct listnode *mnode, *mnnode;
2101 0 : struct bgp *bgp;
2102 0 : bool leak_success = false;
2103 :
2104 0 : int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF);
2105 :
2106 0 : if (debug)
2107 0 : zlog_debug("%s: start (path_vpn=%p)", __func__, path_vpn);
2108 :
2109 : /* Loop over VRFs */
2110 0 : for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
2111 :
2112 0 : if (!path_vpn->extra
2113 0 : || path_vpn->extra->bgp_orig != bgp) { /* no loop */
2114 0 : leak_success |= vpn_leak_to_vrf_update_onevrf(
2115 : bgp, from_bgp, path_vpn, prd);
2116 : }
2117 : }
2118 0 : return leak_success;
2119 : }
2120 :
2121 0 : void vpn_leak_to_vrf_withdraw(struct bgp_path_info *path_vpn)
2122 : {
2123 0 : const struct prefix *p;
2124 0 : afi_t afi;
2125 0 : safi_t safi = SAFI_UNICAST;
2126 0 : struct bgp *bgp;
2127 0 : struct listnode *mnode, *mnnode;
2128 0 : struct bgp_dest *bn;
2129 0 : struct bgp_path_info *bpi;
2130 0 : const char *debugmsg;
2131 :
2132 0 : int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF);
2133 :
2134 0 : if (debug)
2135 0 : zlog_debug("%s: entry: p=%pBD, type=%d, sub_type=%d", __func__,
2136 : path_vpn->net, path_vpn->type, path_vpn->sub_type);
2137 :
2138 0 : if (debug)
2139 0 : zlog_debug("%s: start (path_vpn=%p)", __func__, path_vpn);
2140 :
2141 0 : if (!path_vpn->net) {
2142 : #ifdef ENABLE_BGP_VNC
2143 : /* BGP_ROUTE_RFP routes do not have path_vpn->net set (yet) */
2144 0 : if (path_vpn->type == ZEBRA_ROUTE_BGP
2145 0 : && path_vpn->sub_type == BGP_ROUTE_RFP) {
2146 :
2147 0 : return;
2148 : }
2149 : #endif
2150 0 : if (debug)
2151 0 : zlog_debug(
2152 : "%s: path_vpn->net unexpectedly NULL, no prefix, bailing",
2153 : __func__);
2154 0 : return;
2155 : }
2156 :
2157 0 : p = bgp_dest_get_prefix(path_vpn->net);
2158 0 : afi = family2afi(p->family);
2159 :
2160 : /* Loop over VRFs */
2161 0 : for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
2162 0 : if (!vpn_leak_from_vpn_active(bgp, afi, &debugmsg)) {
2163 0 : if (debug)
2164 0 : zlog_debug("%s: from %s, skipping: %s",
2165 : __func__, bgp->name_pretty,
2166 : debugmsg);
2167 0 : continue;
2168 : }
2169 :
2170 : /* Check for intersection of route targets */
2171 0 : if (!ecommunity_include(
2172 : bgp->vpn_policy[afi]
2173 : .rtlist[BGP_VPN_POLICY_DIR_FROMVPN],
2174 0 : bgp_attr_get_ecommunity(path_vpn->attr))) {
2175 :
2176 0 : continue;
2177 : }
2178 :
2179 0 : if (debug)
2180 0 : zlog_debug("%s: withdrawing from vrf %s", __func__,
2181 : bgp->name_pretty);
2182 :
2183 0 : bn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
2184 :
2185 0 : for (bpi = bgp_dest_get_bgp_path_info(bn); bpi;
2186 0 : bpi = bpi->next) {
2187 0 : if (bpi->extra
2188 0 : && (struct bgp_path_info *)bpi->extra->parent
2189 : == path_vpn) {
2190 : break;
2191 : }
2192 : }
2193 :
2194 0 : if (bpi) {
2195 0 : if (debug)
2196 0 : zlog_debug("%s: deleting bpi %p", __func__,
2197 : bpi);
2198 0 : bgp_aggregate_decrement(bgp, p, bpi, afi, safi);
2199 0 : bgp_path_info_delete(bn, bpi);
2200 0 : bgp_process(bgp, bn, afi, safi);
2201 : }
2202 0 : bgp_dest_unlock_node(bn);
2203 : }
2204 : }
2205 :
2206 0 : void vpn_leak_to_vrf_withdraw_all(struct bgp *to_bgp, afi_t afi)
2207 : {
2208 0 : struct bgp_dest *bn;
2209 0 : struct bgp_path_info *bpi;
2210 0 : safi_t safi = SAFI_UNICAST;
2211 0 : int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF);
2212 :
2213 0 : if (debug)
2214 0 : zlog_debug("%s: entry", __func__);
2215 : /*
2216 : * Walk vrf table, delete bpi with bgp_orig in a different vrf
2217 : */
2218 0 : for (bn = bgp_table_top(to_bgp->rib[afi][safi]); bn;
2219 0 : bn = bgp_route_next(bn)) {
2220 :
2221 0 : for (bpi = bgp_dest_get_bgp_path_info(bn); bpi;
2222 0 : bpi = bpi->next) {
2223 0 : if (bpi->extra && bpi->extra->bgp_orig != to_bgp &&
2224 0 : bpi->extra->parent &&
2225 0 : is_pi_family_vpn(bpi->extra->parent)) {
2226 :
2227 : /* delete route */
2228 0 : bgp_aggregate_decrement(to_bgp,
2229 : bgp_dest_get_prefix(bn),
2230 : bpi, afi, safi);
2231 0 : bgp_path_info_delete(bn, bpi);
2232 0 : bgp_process(to_bgp, bn, afi, safi);
2233 : }
2234 : }
2235 : }
2236 0 : }
2237 :
2238 0 : void vpn_leak_to_vrf_update_all(struct bgp *to_bgp, struct bgp *vpn_from,
2239 : afi_t afi)
2240 : {
2241 0 : struct bgp_dest *pdest;
2242 0 : safi_t safi = SAFI_MPLS_VPN;
2243 :
2244 0 : assert(vpn_from);
2245 :
2246 : /*
2247 : * Walk vpn table
2248 : */
2249 0 : for (pdest = bgp_table_top(vpn_from->rib[afi][safi]); pdest;
2250 0 : pdest = bgp_route_next(pdest)) {
2251 0 : struct bgp_table *table;
2252 0 : struct bgp_dest *bn;
2253 0 : struct bgp_path_info *bpi;
2254 :
2255 : /* This is the per-RD table of prefixes */
2256 0 : table = bgp_dest_get_bgp_table_info(pdest);
2257 :
2258 0 : if (!table)
2259 0 : continue;
2260 :
2261 0 : for (bn = bgp_table_top(table); bn; bn = bgp_route_next(bn)) {
2262 :
2263 0 : for (bpi = bgp_dest_get_bgp_path_info(bn); bpi;
2264 0 : bpi = bpi->next) {
2265 :
2266 0 : if (bpi->extra &&
2267 0 : bpi->extra->bgp_orig == to_bgp)
2268 0 : continue;
2269 :
2270 0 : vpn_leak_to_vrf_update_onevrf(to_bgp, vpn_from,
2271 : bpi, NULL);
2272 : }
2273 : }
2274 : }
2275 0 : }
2276 :
2277 : /*
2278 : * This function is called for definition/deletion/change to a route-map
2279 : */
2280 0 : static void vpn_policy_routemap_update(struct bgp *bgp, const char *rmap_name)
2281 : {
2282 0 : int debug = BGP_DEBUG(vpn, VPN_LEAK_RMAP_EVENT);
2283 0 : afi_t afi;
2284 0 : struct route_map *rmap;
2285 :
2286 0 : if (bgp->inst_type != BGP_INSTANCE_TYPE_DEFAULT
2287 : && bgp->inst_type != BGP_INSTANCE_TYPE_VRF) {
2288 :
2289 : return;
2290 : }
2291 :
2292 0 : rmap = route_map_lookup_by_name(rmap_name); /* NULL if deleted */
2293 :
2294 0 : for (afi = 0; afi < AFI_MAX; ++afi) {
2295 :
2296 0 : if (bgp->vpn_policy[afi].rmap_name[BGP_VPN_POLICY_DIR_TOVPN]
2297 0 : && !strcmp(rmap_name,
2298 : bgp->vpn_policy[afi]
2299 : .rmap_name[BGP_VPN_POLICY_DIR_TOVPN])) {
2300 :
2301 0 : if (debug)
2302 0 : zlog_debug(
2303 : "%s: rmap \"%s\" matches vrf-policy tovpn for as %d afi %s",
2304 : __func__, rmap_name, bgp->as,
2305 : afi2str(afi));
2306 :
2307 0 : vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi,
2308 : bgp_get_default(), bgp);
2309 0 : if (debug)
2310 0 : zlog_debug("%s: after vpn_leak_prechange",
2311 : __func__);
2312 :
2313 : /* in case of definition/deletion */
2314 0 : bgp->vpn_policy[afi].rmap[BGP_VPN_POLICY_DIR_TOVPN] =
2315 : rmap;
2316 :
2317 0 : vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi,
2318 : bgp_get_default(), bgp);
2319 :
2320 0 : if (debug)
2321 0 : zlog_debug("%s: after vpn_leak_postchange",
2322 : __func__);
2323 : }
2324 :
2325 0 : if (bgp->vpn_policy[afi].rmap_name[BGP_VPN_POLICY_DIR_FROMVPN]
2326 0 : && !strcmp(rmap_name,
2327 : bgp->vpn_policy[afi]
2328 : .rmap_name[BGP_VPN_POLICY_DIR_FROMVPN])) {
2329 :
2330 0 : if (debug) {
2331 0 : zlog_debug("%s: rmap \"%s\" matches vrf-policy fromvpn for as %d afi %s",
2332 : __func__, rmap_name, bgp->as,
2333 : afi2str(afi));
2334 : }
2335 :
2336 0 : vpn_leak_prechange(BGP_VPN_POLICY_DIR_FROMVPN, afi,
2337 : bgp_get_default(), bgp);
2338 :
2339 : /* in case of definition/deletion */
2340 0 : bgp->vpn_policy[afi].rmap[BGP_VPN_POLICY_DIR_FROMVPN] =
2341 : rmap;
2342 :
2343 0 : vpn_leak_postchange(BGP_VPN_POLICY_DIR_FROMVPN, afi,
2344 : bgp_get_default(), bgp);
2345 : }
2346 : }
2347 : }
2348 :
2349 : /* This API is used during router-id change, reflect VPNs
2350 : * auto RD and RT values and readvertise routes to VPN table.
2351 : */
2352 8 : void vpn_handle_router_id_update(struct bgp *bgp, bool withdraw,
2353 : bool is_config)
2354 : {
2355 8 : afi_t afi;
2356 8 : int debug = (BGP_DEBUG(vpn, VPN_LEAK_TO_VRF)
2357 8 : | BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF));
2358 8 : char *vname;
2359 8 : const char *export_name;
2360 8 : char buf[RD_ADDRSTRLEN];
2361 8 : struct bgp *bgp_import;
2362 8 : struct listnode *node;
2363 8 : struct ecommunity *ecom;
2364 8 : enum vpn_policy_direction idir, edir;
2365 :
2366 : /*
2367 : * Router-id change that is not explicitly configured
2368 : * (a change from zebra, frr restart for example)
2369 : * should not replace a configured vpn RD/RT.
2370 : */
2371 8 : if (!is_config) {
2372 0 : if (debug)
2373 0 : zlog_debug("%s: skipping non explicit router-id change",
2374 : __func__);
2375 0 : return;
2376 : }
2377 :
2378 8 : if (bgp->inst_type != BGP_INSTANCE_TYPE_DEFAULT
2379 : && bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
2380 : return;
2381 :
2382 8 : export_name = bgp->name ? bgp->name : VRF_DEFAULT_NAME;
2383 8 : idir = BGP_VPN_POLICY_DIR_FROMVPN;
2384 8 : edir = BGP_VPN_POLICY_DIR_TOVPN;
2385 :
2386 40 : for (afi = 0; afi < AFI_MAX; ++afi) {
2387 32 : if (!vpn_leak_to_vpn_active(bgp, afi, NULL))
2388 32 : continue;
2389 :
2390 0 : if (withdraw) {
2391 0 : vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN,
2392 : afi, bgp_get_default(), bgp);
2393 0 : if (debug)
2394 0 : zlog_debug("%s: %s after to_vpn vpn_leak_prechange",
2395 : __func__, export_name);
2396 :
2397 : /* Remove import RT from VRFs */
2398 0 : ecom = bgp->vpn_policy[afi].rtlist[edir];
2399 0 : for (ALL_LIST_ELEMENTS_RO(bgp->vpn_policy[afi].
2400 : export_vrf, node, vname)) {
2401 0 : if (strcmp(vname, VRF_DEFAULT_NAME) == 0)
2402 0 : bgp_import = bgp_get_default();
2403 : else
2404 0 : bgp_import = bgp_lookup_by_name(vname);
2405 0 : if (!bgp_import)
2406 0 : continue;
2407 :
2408 0 : ecommunity_del_val(
2409 : bgp_import->vpn_policy[afi]
2410 : .rtlist[idir],
2411 0 : (struct ecommunity_val *)ecom->val);
2412 : }
2413 : } else {
2414 : /* New router-id derive auto RD and RT and export
2415 : * to VPN
2416 : */
2417 0 : form_auto_rd(bgp->router_id, bgp->vrf_rd_id,
2418 : &bgp->vrf_prd_auto);
2419 0 : bgp->vpn_policy[afi].tovpn_rd = bgp->vrf_prd_auto;
2420 0 : prefix_rd2str(&bgp->vpn_policy[afi].tovpn_rd, buf,
2421 : sizeof(buf));
2422 :
2423 : /* free up pre-existing memory if any and allocate
2424 : * the ecommunity attribute with new RD/RT
2425 : */
2426 0 : if (bgp->vpn_policy[afi].rtlist[edir])
2427 0 : ecommunity_free(
2428 : &bgp->vpn_policy[afi].rtlist[edir]);
2429 0 : bgp->vpn_policy[afi].rtlist[edir] = ecommunity_str2com(
2430 : buf, ECOMMUNITY_ROUTE_TARGET, 0);
2431 :
2432 : /* Update import_vrf rt_list */
2433 0 : ecom = bgp->vpn_policy[afi].rtlist[edir];
2434 0 : for (ALL_LIST_ELEMENTS_RO(bgp->vpn_policy[afi].
2435 : export_vrf, node, vname)) {
2436 0 : if (strcmp(vname, VRF_DEFAULT_NAME) == 0)
2437 0 : bgp_import = bgp_get_default();
2438 : else
2439 0 : bgp_import = bgp_lookup_by_name(vname);
2440 0 : if (!bgp_import)
2441 0 : continue;
2442 0 : if (bgp_import->vpn_policy[afi].rtlist[idir])
2443 0 : bgp_import->vpn_policy[afi].rtlist[idir]
2444 0 : = ecommunity_merge(
2445 : bgp_import->vpn_policy[afi]
2446 : .rtlist[idir], ecom);
2447 : else
2448 0 : bgp_import->vpn_policy[afi].rtlist[idir]
2449 0 : = ecommunity_dup(ecom);
2450 : }
2451 :
2452 : /* Update routes to VPN */
2453 0 : vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN,
2454 : afi, bgp_get_default(),
2455 : bgp);
2456 0 : if (debug)
2457 32 : zlog_debug("%s: %s after to_vpn vpn_leak_postchange",
2458 : __func__, export_name);
2459 : }
2460 : }
2461 : }
2462 :
2463 0 : void vpn_policy_routemap_event(const char *rmap_name)
2464 : {
2465 0 : int debug = BGP_DEBUG(vpn, VPN_LEAK_RMAP_EVENT);
2466 0 : struct listnode *mnode, *mnnode;
2467 0 : struct bgp *bgp;
2468 :
2469 0 : if (debug)
2470 0 : zlog_debug("%s: entry", __func__);
2471 :
2472 0 : if (bm->bgp == NULL) /* may be called during cleanup */
2473 : return;
2474 :
2475 0 : for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp))
2476 0 : vpn_policy_routemap_update(bgp, rmap_name);
2477 : }
2478 :
2479 0 : void vrf_import_from_vrf(struct bgp *to_bgp, struct bgp *from_bgp,
2480 : afi_t afi, safi_t safi)
2481 : {
2482 0 : const char *export_name;
2483 0 : enum vpn_policy_direction idir, edir;
2484 0 : char *vname, *tmp_name;
2485 0 : char buf[RD_ADDRSTRLEN];
2486 0 : struct ecommunity *ecom;
2487 0 : bool first_export = false;
2488 0 : int debug;
2489 0 : struct listnode *node;
2490 0 : bool is_inst_match = false;
2491 :
2492 0 : export_name = to_bgp->name ? to_bgp->name : VRF_DEFAULT_NAME;
2493 0 : idir = BGP_VPN_POLICY_DIR_FROMVPN;
2494 0 : edir = BGP_VPN_POLICY_DIR_TOVPN;
2495 :
2496 0 : debug = (BGP_DEBUG(vpn, VPN_LEAK_TO_VRF) |
2497 : BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF));
2498 :
2499 : /*
2500 : * Cross-ref both VRFs. Also, note if this is the first time
2501 : * any VRF is importing from "import_vrf".
2502 : */
2503 0 : vname = (from_bgp->name ? XSTRDUP(MTYPE_TMP, from_bgp->name)
2504 0 : : XSTRDUP(MTYPE_TMP, VRF_DEFAULT_NAME));
2505 :
2506 : /* Check the import_vrf list of destination vrf for the source vrf name,
2507 : * insert otherwise.
2508 : */
2509 0 : for (ALL_LIST_ELEMENTS_RO(to_bgp->vpn_policy[afi].import_vrf,
2510 : node, tmp_name)) {
2511 0 : if (strcmp(vname, tmp_name) == 0) {
2512 : is_inst_match = true;
2513 : break;
2514 : }
2515 : }
2516 0 : if (!is_inst_match)
2517 0 : listnode_add(to_bgp->vpn_policy[afi].import_vrf,
2518 : vname);
2519 : else
2520 0 : XFREE(MTYPE_TMP, vname);
2521 :
2522 : /* Check if the source vrf already exports to any vrf,
2523 : * first time export requires to setup auto derived RD/RT values.
2524 : * Add the destination vrf name to export vrf list if it is
2525 : * not present.
2526 : */
2527 0 : is_inst_match = false;
2528 0 : vname = XSTRDUP(MTYPE_TMP, export_name);
2529 0 : if (!listcount(from_bgp->vpn_policy[afi].export_vrf)) {
2530 : first_export = true;
2531 : } else {
2532 0 : for (ALL_LIST_ELEMENTS_RO(from_bgp->vpn_policy[afi].export_vrf,
2533 : node, tmp_name)) {
2534 0 : if (strcmp(vname, tmp_name) == 0) {
2535 : is_inst_match = true;
2536 : break;
2537 : }
2538 : }
2539 : }
2540 0 : if (!is_inst_match)
2541 0 : listnode_add(from_bgp->vpn_policy[afi].export_vrf,
2542 : vname);
2543 : else
2544 0 : XFREE(MTYPE_TMP, vname);
2545 :
2546 : /* Update import RT for current VRF using export RT of the VRF we're
2547 : * importing from. First though, make sure "import_vrf" has that
2548 : * set.
2549 : */
2550 0 : if (first_export) {
2551 0 : form_auto_rd(from_bgp->router_id, from_bgp->vrf_rd_id,
2552 : &from_bgp->vrf_prd_auto);
2553 0 : from_bgp->vpn_policy[afi].tovpn_rd = from_bgp->vrf_prd_auto;
2554 0 : SET_FLAG(from_bgp->vpn_policy[afi].flags,
2555 : BGP_VPN_POLICY_TOVPN_RD_SET);
2556 0 : prefix_rd2str(&from_bgp->vpn_policy[afi].tovpn_rd,
2557 : buf, sizeof(buf));
2558 0 : from_bgp->vpn_policy[afi].rtlist[edir] =
2559 0 : ecommunity_str2com(buf, ECOMMUNITY_ROUTE_TARGET, 0);
2560 0 : SET_FLAG(from_bgp->af_flags[afi][safi],
2561 : BGP_CONFIG_VRF_TO_VRF_EXPORT);
2562 0 : from_bgp->vpn_policy[afi].tovpn_label =
2563 : BGP_PREVENT_VRF_2_VRF_LEAK;
2564 : }
2565 0 : ecom = from_bgp->vpn_policy[afi].rtlist[edir];
2566 0 : if (to_bgp->vpn_policy[afi].rtlist[idir])
2567 0 : to_bgp->vpn_policy[afi].rtlist[idir] =
2568 0 : ecommunity_merge(to_bgp->vpn_policy[afi]
2569 : .rtlist[idir], ecom);
2570 : else
2571 0 : to_bgp->vpn_policy[afi].rtlist[idir] = ecommunity_dup(ecom);
2572 0 : SET_FLAG(to_bgp->af_flags[afi][safi], BGP_CONFIG_VRF_TO_VRF_IMPORT);
2573 :
2574 0 : if (debug) {
2575 0 : const char *from_name;
2576 0 : char *ecom1, *ecom2;
2577 :
2578 0 : from_name = from_bgp->name ? from_bgp->name :
2579 0 : VRF_DEFAULT_NAME;
2580 :
2581 0 : ecom1 = ecommunity_ecom2str(
2582 : to_bgp->vpn_policy[afi].rtlist[idir],
2583 : ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
2584 :
2585 0 : ecom2 = ecommunity_ecom2str(
2586 : to_bgp->vpn_policy[afi].rtlist[edir],
2587 : ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
2588 :
2589 0 : zlog_debug(
2590 : "%s from %s to %s first_export %u import-rt %s export-rt %s",
2591 : __func__, from_name, export_name, first_export, ecom1,
2592 : ecom2);
2593 :
2594 0 : ecommunity_strfree(&ecom1);
2595 0 : ecommunity_strfree(&ecom2);
2596 : }
2597 :
2598 : /* Does "import_vrf" first need to export its routes or that
2599 : * is already done and we just need to import those routes
2600 : * from the global table?
2601 : */
2602 0 : if (first_export)
2603 0 : vpn_leak_postchange(edir, afi, bgp_get_default(), from_bgp);
2604 : else
2605 0 : vpn_leak_postchange(idir, afi, bgp_get_default(), to_bgp);
2606 0 : }
2607 :
2608 0 : void vrf_unimport_from_vrf(struct bgp *to_bgp, struct bgp *from_bgp,
2609 : afi_t afi, safi_t safi)
2610 : {
2611 0 : const char *export_name, *tmp_name;
2612 0 : enum vpn_policy_direction idir, edir;
2613 0 : char *vname;
2614 0 : struct ecommunity *ecom = NULL;
2615 0 : struct listnode *node;
2616 0 : int debug;
2617 :
2618 0 : export_name = to_bgp->name ? to_bgp->name : VRF_DEFAULT_NAME;
2619 0 : tmp_name = from_bgp->name ? from_bgp->name : VRF_DEFAULT_NAME;
2620 0 : idir = BGP_VPN_POLICY_DIR_FROMVPN;
2621 0 : edir = BGP_VPN_POLICY_DIR_TOVPN;
2622 :
2623 0 : debug = (BGP_DEBUG(vpn, VPN_LEAK_TO_VRF) |
2624 : BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF));
2625 :
2626 : /* Were we importing from "import_vrf"? */
2627 0 : for (ALL_LIST_ELEMENTS_RO(to_bgp->vpn_policy[afi].import_vrf, node,
2628 : vname)) {
2629 0 : if (strcmp(vname, tmp_name) == 0)
2630 : break;
2631 : }
2632 :
2633 : /*
2634 : * We do not check in the cli if the passed in bgp
2635 : * instance is actually imported into us before
2636 : * we call this function. As such if we do not
2637 : * find this in the import_vrf list than
2638 : * we just need to return safely.
2639 : */
2640 0 : if (!vname)
2641 : return;
2642 :
2643 0 : if (debug)
2644 0 : zlog_debug("%s from %s to %s", __func__, tmp_name, export_name);
2645 :
2646 : /* Remove "import_vrf" from our import list. */
2647 0 : listnode_delete(to_bgp->vpn_policy[afi].import_vrf, vname);
2648 0 : XFREE(MTYPE_TMP, vname);
2649 :
2650 : /* Remove routes imported from "import_vrf". */
2651 : /* TODO: In the current logic, we have to first remove all
2652 : * imported routes and then (if needed) import back routes
2653 : */
2654 0 : vpn_leak_prechange(idir, afi, bgp_get_default(), to_bgp);
2655 :
2656 0 : if (to_bgp->vpn_policy[afi].import_vrf->count == 0) {
2657 0 : if (!to_bgp->vpn_policy[afi].rmap[idir])
2658 0 : UNSET_FLAG(to_bgp->af_flags[afi][safi],
2659 : BGP_CONFIG_VRF_TO_VRF_IMPORT);
2660 0 : if (to_bgp->vpn_policy[afi].rtlist[idir])
2661 0 : ecommunity_free(&to_bgp->vpn_policy[afi].rtlist[idir]);
2662 : } else {
2663 0 : ecom = from_bgp->vpn_policy[afi].rtlist[edir];
2664 0 : if (ecom)
2665 0 : ecommunity_del_val(to_bgp->vpn_policy[afi].rtlist[idir],
2666 0 : (struct ecommunity_val *)ecom->val);
2667 0 : vpn_leak_postchange(idir, afi, bgp_get_default(), to_bgp);
2668 : }
2669 :
2670 : /*
2671 : * What?
2672 : * So SA is assuming that since the ALL_LIST_ELEMENTS_RO
2673 : * below is checking for NULL that export_vrf can be
2674 : * NULL, consequently it is complaining( like a cabbage )
2675 : * that we could dereference and crash in the listcount(..)
2676 : * check below.
2677 : * So make it happy, under protest, with liberty and justice
2678 : * for all.
2679 : */
2680 0 : assert(from_bgp->vpn_policy[afi].export_vrf);
2681 :
2682 : /* Remove us from "import_vrf's" export list. If no other VRF
2683 : * is importing from "import_vrf", cleanup appropriately.
2684 : */
2685 0 : for (ALL_LIST_ELEMENTS_RO(from_bgp->vpn_policy[afi].export_vrf,
2686 : node, vname)) {
2687 0 : if (strcmp(vname, export_name) == 0)
2688 : break;
2689 : }
2690 :
2691 : /*
2692 : * If we have gotten to this point then the vname must
2693 : * exist. If not, we are in a world of trouble and
2694 : * have slag sitting around.
2695 : *
2696 : * import_vrf and export_vrf must match in having
2697 : * the in/out names as appropriate.
2698 : * export_vrf list could have been cleaned up
2699 : * as part of no router bgp source instnace.
2700 : */
2701 0 : if (!vname)
2702 : return;
2703 :
2704 0 : listnode_delete(from_bgp->vpn_policy[afi].export_vrf, vname);
2705 0 : XFREE(MTYPE_TMP, vname);
2706 :
2707 0 : if (!listcount(from_bgp->vpn_policy[afi].export_vrf)) {
2708 0 : vpn_leak_prechange(edir, afi, bgp_get_default(), from_bgp);
2709 0 : ecommunity_free(&from_bgp->vpn_policy[afi].rtlist[edir]);
2710 0 : UNSET_FLAG(from_bgp->af_flags[afi][safi],
2711 : BGP_CONFIG_VRF_TO_VRF_EXPORT);
2712 0 : memset(&from_bgp->vpn_policy[afi].tovpn_rd, 0,
2713 : sizeof(struct prefix_rd));
2714 0 : UNSET_FLAG(from_bgp->vpn_policy[afi].flags,
2715 : BGP_VPN_POLICY_TOVPN_RD_SET);
2716 0 : from_bgp->vpn_policy[afi].tovpn_label = MPLS_LABEL_NONE;
2717 :
2718 : }
2719 : }
2720 :
2721 : /* For testing purpose, static route of MPLS-VPN. */
2722 0 : DEFUN (vpnv4_network,
2723 : vpnv4_network_cmd,
2724 : "network A.B.C.D/M rd ASN:NN_OR_IP-ADDRESS:NN <tag|label> (0-1048575)",
2725 : "Specify a network to announce via BGP\n"
2726 : "IPv4 prefix\n"
2727 : "Specify Route Distinguisher\n"
2728 : "VPN Route Distinguisher\n"
2729 : "VPN NLRI label (tag)\n"
2730 : "VPN NLRI label (tag)\n"
2731 : "Label value\n")
2732 : {
2733 0 : int idx_ipv4_prefixlen = 1;
2734 0 : int idx_ext_community = 3;
2735 0 : int idx_label = 5;
2736 0 : return bgp_static_set_safi(
2737 0 : AFI_IP, SAFI_MPLS_VPN, vty, argv[idx_ipv4_prefixlen]->arg,
2738 0 : argv[idx_ext_community]->arg, argv[idx_label]->arg, NULL, 0,
2739 : NULL, NULL, NULL, NULL);
2740 : }
2741 :
2742 0 : DEFUN (vpnv4_network_route_map,
2743 : vpnv4_network_route_map_cmd,
2744 : "network A.B.C.D/M rd ASN:NN_OR_IP-ADDRESS:NN <tag|label> (0-1048575) route-map RMAP_NAME",
2745 : "Specify a network to announce via BGP\n"
2746 : "IPv4 prefix\n"
2747 : "Specify Route Distinguisher\n"
2748 : "VPN Route Distinguisher\n"
2749 : "VPN NLRI label (tag)\n"
2750 : "VPN NLRI label (tag)\n"
2751 : "Label value\n"
2752 : "route map\n"
2753 : "route map name\n")
2754 : {
2755 0 : int idx_ipv4_prefixlen = 1;
2756 0 : int idx_ext_community = 3;
2757 0 : int idx_label = 5;
2758 0 : int idx_word_2 = 7;
2759 0 : return bgp_static_set_safi(
2760 0 : AFI_IP, SAFI_MPLS_VPN, vty, argv[idx_ipv4_prefixlen]->arg,
2761 0 : argv[idx_ext_community]->arg, argv[idx_label]->arg,
2762 0 : argv[idx_word_2]->arg, 0, NULL, NULL, NULL, NULL);
2763 : }
2764 :
2765 : /* For testing purpose, static route of MPLS-VPN. */
2766 0 : DEFUN (no_vpnv4_network,
2767 : no_vpnv4_network_cmd,
2768 : "no network A.B.C.D/M rd ASN:NN_OR_IP-ADDRESS:NN <tag|label> (0-1048575)",
2769 : NO_STR
2770 : "Specify a network to announce via BGP\n"
2771 : "IPv4 prefix\n"
2772 : "Specify Route Distinguisher\n"
2773 : "VPN Route Distinguisher\n"
2774 : "VPN NLRI label (tag)\n"
2775 : "VPN NLRI label (tag)\n"
2776 : "Label value\n")
2777 : {
2778 0 : int idx_ipv4_prefixlen = 2;
2779 0 : int idx_ext_community = 4;
2780 0 : int idx_label = 6;
2781 0 : return bgp_static_unset_safi(AFI_IP, SAFI_MPLS_VPN, vty,
2782 0 : argv[idx_ipv4_prefixlen]->arg,
2783 0 : argv[idx_ext_community]->arg,
2784 0 : argv[idx_label]->arg, 0, NULL, NULL, NULL);
2785 : }
2786 :
2787 0 : DEFUN (vpnv6_network,
2788 : vpnv6_network_cmd,
2789 : "network X:X::X:X/M rd ASN:NN_OR_IP-ADDRESS:NN <tag|label> (0-1048575) [route-map RMAP_NAME]",
2790 : "Specify a network to announce via BGP\n"
2791 : "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
2792 : "Specify Route Distinguisher\n"
2793 : "VPN Route Distinguisher\n"
2794 : "VPN NLRI label (tag)\n"
2795 : "VPN NLRI label (tag)\n"
2796 : "Label value\n"
2797 : "route map\n"
2798 : "route map name\n")
2799 : {
2800 0 : int idx_ipv6_prefix = 1;
2801 0 : int idx_ext_community = 3;
2802 0 : int idx_label = 5;
2803 0 : int idx_word_2 = 7;
2804 0 : if (argc == 8)
2805 0 : return bgp_static_set_safi(
2806 0 : AFI_IP6, SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg,
2807 0 : argv[idx_ext_community]->arg, argv[idx_label]->arg,
2808 0 : argv[idx_word_2]->arg, 0, NULL, NULL, NULL, NULL);
2809 : else
2810 0 : return bgp_static_set_safi(
2811 0 : AFI_IP6, SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg,
2812 0 : argv[idx_ext_community]->arg, argv[idx_label]->arg,
2813 : NULL, 0, NULL, NULL, NULL, NULL);
2814 : }
2815 :
2816 : /* For testing purpose, static route of MPLS-VPN. */
2817 0 : DEFUN (no_vpnv6_network,
2818 : no_vpnv6_network_cmd,
2819 : "no network X:X::X:X/M rd ASN:NN_OR_IP-ADDRESS:NN <tag|label> (0-1048575)",
2820 : NO_STR
2821 : "Specify a network to announce via BGP\n"
2822 : "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
2823 : "Specify Route Distinguisher\n"
2824 : "VPN Route Distinguisher\n"
2825 : "VPN NLRI label (tag)\n"
2826 : "VPN NLRI label (tag)\n"
2827 : "Label value\n")
2828 : {
2829 0 : int idx_ipv6_prefix = 2;
2830 0 : int idx_ext_community = 4;
2831 0 : int idx_label = 6;
2832 0 : return bgp_static_unset_safi(AFI_IP6, SAFI_MPLS_VPN, vty,
2833 0 : argv[idx_ipv6_prefix]->arg,
2834 0 : argv[idx_ext_community]->arg,
2835 0 : argv[idx_label]->arg, 0, NULL, NULL, NULL);
2836 : }
2837 :
2838 0 : int bgp_show_mpls_vpn(struct vty *vty, afi_t afi, struct prefix_rd *prd,
2839 : enum bgp_show_type type, void *output_arg, int tags,
2840 : bool use_json)
2841 : {
2842 0 : struct bgp *bgp;
2843 0 : struct bgp_table *table;
2844 0 : uint16_t show_flags = 0;
2845 :
2846 0 : if (use_json)
2847 0 : SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
2848 :
2849 0 : bgp = bgp_get_default();
2850 0 : if (bgp == NULL) {
2851 0 : if (!use_json)
2852 0 : vty_out(vty, "No BGP process is configured\n");
2853 : else
2854 0 : vty_out(vty, "{}\n");
2855 0 : return CMD_WARNING;
2856 : }
2857 0 : table = bgp->rib[afi][SAFI_MPLS_VPN];
2858 0 : return bgp_show_table_rd(vty, bgp, SAFI_MPLS_VPN, table, prd, type,
2859 : output_arg, show_flags);
2860 : }
2861 :
2862 0 : DEFUN (show_bgp_ip_vpn_all_rd,
2863 : show_bgp_ip_vpn_all_rd_cmd,
2864 : "show bgp "BGP_AFI_CMD_STR" vpn all [rd <ASN:NN_OR_IP-ADDRESS:NN|all>] [json]",
2865 : SHOW_STR
2866 : BGP_STR
2867 : BGP_VPNVX_HELP_STR
2868 : "Display VPN NLRI specific information\n"
2869 : "Display VPN NLRI specific information\n"
2870 : "Display information for a route distinguisher\n"
2871 : "VPN Route Distinguisher\n"
2872 : "All VPN Route Distinguishers\n"
2873 : JSON_STR)
2874 : {
2875 0 : int ret;
2876 0 : struct prefix_rd prd;
2877 0 : afi_t afi;
2878 0 : int idx = 0;
2879 :
2880 0 : if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
2881 : /* Constrain search if user supplies RD && RD != "all" */
2882 0 : if (argv_find(argv, argc, "rd", &idx)
2883 0 : && strcmp(argv[idx + 1]->arg, "all")) {
2884 0 : ret = str2prefix_rd(argv[idx + 1]->arg, &prd);
2885 0 : if (!ret) {
2886 0 : vty_out(vty,
2887 : "%% Malformed Route Distinguisher\n");
2888 0 : return CMD_WARNING;
2889 : }
2890 0 : return bgp_show_mpls_vpn(vty, afi, &prd,
2891 : bgp_show_type_normal, NULL, 0,
2892 0 : use_json(argc, argv));
2893 : } else {
2894 0 : return bgp_show_mpls_vpn(vty, afi, NULL,
2895 : bgp_show_type_normal, NULL, 0,
2896 0 : use_json(argc, argv));
2897 : }
2898 : }
2899 : return CMD_SUCCESS;
2900 : }
2901 :
2902 : ALIAS(show_bgp_ip_vpn_all_rd,
2903 : show_bgp_ip_vpn_rd_cmd,
2904 : "show bgp "BGP_AFI_CMD_STR" vpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> [json]",
2905 : SHOW_STR
2906 : BGP_STR
2907 : BGP_VPNVX_HELP_STR
2908 : "Display VPN NLRI specific information\n"
2909 : "Display information for a route distinguisher\n"
2910 : "VPN Route Distinguisher\n"
2911 : "All VPN Route Distinguishers\n"
2912 : JSON_STR)
2913 :
2914 : #ifdef KEEP_OLD_VPN_COMMANDS
2915 : DEFUN (show_ip_bgp_vpn_rd,
2916 : show_ip_bgp_vpn_rd_cmd,
2917 : "show ip bgp "BGP_AFI_CMD_STR" vpn rd <ASN:NN_OR_IP-ADDRESS:NN|all>",
2918 : SHOW_STR
2919 : IP_STR
2920 : BGP_STR
2921 : BGP_AFI_HELP_STR
2922 : BGP_AF_MODIFIER_STR
2923 : "Display information for a route distinguisher\n"
2924 : "VPN Route Distinguisher\n"
2925 : "All VPN Route Distinguishers\n")
2926 : {
2927 : int idx_ext_community = argc - 1;
2928 : int ret;
2929 : struct prefix_rd prd;
2930 : afi_t afi;
2931 : int idx = 0;
2932 :
2933 : if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
2934 : if (!strcmp(argv[idx_ext_community]->arg, "all"))
2935 : return bgp_show_mpls_vpn(vty, afi, NULL,
2936 : bgp_show_type_normal, NULL, 0,
2937 : 0);
2938 : ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
2939 : if (!ret) {
2940 : vty_out(vty, "%% Malformed Route Distinguisher\n");
2941 : return CMD_WARNING;
2942 : }
2943 : return bgp_show_mpls_vpn(vty, afi, &prd, bgp_show_type_normal,
2944 : NULL, 0, 0);
2945 : }
2946 : return CMD_SUCCESS;
2947 : }
2948 :
2949 : DEFUN (show_ip_bgp_vpn_all,
2950 : show_ip_bgp_vpn_all_cmd,
2951 : "show [ip] bgp <vpnv4|vpnv6>",
2952 : SHOW_STR
2953 : IP_STR
2954 : BGP_STR
2955 : BGP_VPNVX_HELP_STR)
2956 : {
2957 : afi_t afi;
2958 : int idx = 0;
2959 :
2960 : if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi))
2961 : return bgp_show_mpls_vpn(vty, afi, NULL, bgp_show_type_normal,
2962 : NULL, 0, 0);
2963 : return CMD_SUCCESS;
2964 : }
2965 :
2966 : DEFUN (show_ip_bgp_vpn_all_tags,
2967 : show_ip_bgp_vpn_all_tags_cmd,
2968 : "show [ip] bgp <vpnv4|vpnv6> all tags",
2969 : SHOW_STR
2970 : IP_STR
2971 : BGP_STR
2972 : BGP_VPNVX_HELP_STR
2973 : "Display information about all VPNv4/VPNV6 NLRIs\n"
2974 : "Display BGP tags for prefixes\n")
2975 : {
2976 : afi_t afi;
2977 : int idx = 0;
2978 :
2979 : if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi))
2980 : return bgp_show_mpls_vpn(vty, afi, NULL, bgp_show_type_normal,
2981 : NULL, 1, 0);
2982 : return CMD_SUCCESS;
2983 : }
2984 :
2985 : DEFUN (show_ip_bgp_vpn_rd_tags,
2986 : show_ip_bgp_vpn_rd_tags_cmd,
2987 : "show [ip] bgp <vpnv4|vpnv6> rd <ASN:NN_OR_IP-ADDRESS:NN|all> tags",
2988 : SHOW_STR
2989 : IP_STR
2990 : BGP_STR
2991 : BGP_VPNVX_HELP_STR
2992 : "Display information for a route distinguisher\n"
2993 : "VPN Route Distinguisher\n"
2994 : "All VPN Route Distinguishers\n"
2995 : "Display BGP tags for prefixes\n")
2996 : {
2997 : int idx_ext_community = 5;
2998 : int ret;
2999 : struct prefix_rd prd;
3000 : afi_t afi;
3001 : int idx = 0;
3002 :
3003 : if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
3004 : if (!strcmp(argv[idx_ext_community]->arg, "all"))
3005 : return bgp_show_mpls_vpn(vty, afi, NULL,
3006 : bgp_show_type_normal, NULL, 1,
3007 : 0);
3008 : ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
3009 : if (!ret) {
3010 : vty_out(vty, "%% Malformed Route Distinguisher\n");
3011 : return CMD_WARNING;
3012 : }
3013 : return bgp_show_mpls_vpn(vty, afi, &prd, bgp_show_type_normal,
3014 : NULL, 1, 0);
3015 : }
3016 : return CMD_SUCCESS;
3017 : }
3018 :
3019 : DEFUN (show_ip_bgp_vpn_all_neighbor_routes,
3020 : show_ip_bgp_vpn_all_neighbor_routes_cmd,
3021 : "show [ip] bgp <vpnv4|vpnv6> all neighbors A.B.C.D routes [json]",
3022 : SHOW_STR
3023 : IP_STR
3024 : BGP_STR
3025 : BGP_VPNVX_HELP_STR
3026 : "Display information about all VPNv4/VPNv6 NLRIs\n"
3027 : "Detailed information on TCP and BGP neighbor connections\n"
3028 : "Neighbor to display information about\n"
3029 : "Display routes learned from neighbor\n"
3030 : JSON_STR)
3031 : {
3032 : int idx_ipv4 = 6;
3033 : union sockunion su;
3034 : struct peer *peer;
3035 : int ret;
3036 : bool uj = use_json(argc, argv);
3037 : afi_t afi;
3038 : int idx = 0;
3039 :
3040 : if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
3041 : ret = str2sockunion(argv[idx_ipv4]->arg, &su);
3042 : if (ret < 0) {
3043 : if (uj) {
3044 : json_object *json_no = NULL;
3045 : json_no = json_object_new_object();
3046 : json_object_string_add(json_no, "warning",
3047 : "Malformed address");
3048 : vty_out(vty, "%s\n",
3049 : json_object_to_json_string(json_no));
3050 : json_object_free(json_no);
3051 : } else
3052 : vty_out(vty, "Malformed address: %s\n",
3053 : argv[idx_ipv4]->arg);
3054 : return CMD_WARNING;
3055 : }
3056 :
3057 : peer = peer_lookup(NULL, &su);
3058 : if (!peer || !peer->afc[afi][SAFI_MPLS_VPN]) {
3059 : if (uj) {
3060 : json_object *json_no = NULL;
3061 : json_no = json_object_new_object();
3062 : json_object_string_add(
3063 : json_no, "warning",
3064 : "No such neighbor or address family");
3065 : vty_out(vty, "%s\n",
3066 : json_object_to_json_string(json_no));
3067 : json_object_free(json_no);
3068 : } else
3069 : vty_out(vty,
3070 : "%% No such neighbor or address family\n");
3071 : return CMD_WARNING;
3072 : }
3073 :
3074 : return bgp_show_mpls_vpn(vty, afi, NULL, bgp_show_type_neighbor,
3075 : &su, 0, uj);
3076 : }
3077 : return CMD_SUCCESS;
3078 : }
3079 :
3080 : DEFUN (show_ip_bgp_vpn_rd_neighbor_routes,
3081 : show_ip_bgp_vpn_rd_neighbor_routes_cmd,
3082 : "show [ip] bgp <vpnv4|vpnv6> rd <ASN:NN_OR_IP-ADDRESS:NN|all> neighbors A.B.C.D routes [json]",
3083 : SHOW_STR
3084 : IP_STR
3085 : BGP_STR
3086 : BGP_VPNVX_HELP_STR
3087 : "Display information for a route distinguisher\n"
3088 : "VPN Route Distinguisher\n"
3089 : "All VPN Route Distinguishers\n"
3090 : "Detailed information on TCP and BGP neighbor connections\n"
3091 : "Neighbor to display information about\n"
3092 : "Display routes learned from neighbor\n"
3093 : JSON_STR)
3094 : {
3095 : int idx_ext_community = 5;
3096 : int idx_ipv4 = 7;
3097 : int ret;
3098 : union sockunion su;
3099 : struct peer *peer;
3100 : struct prefix_rd prd;
3101 : bool prefix_rd_all = false;
3102 : bool uj = use_json(argc, argv);
3103 : afi_t afi;
3104 : int idx = 0;
3105 :
3106 : if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
3107 : if (!strcmp(argv[idx_ext_community]->arg, "all"))
3108 : prefix_rd_all = true;
3109 : else {
3110 : ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
3111 : if (!ret) {
3112 : if (uj) {
3113 : json_object *json_no = NULL;
3114 : json_no = json_object_new_object();
3115 : json_object_string_add(
3116 : json_no, "warning",
3117 : "Malformed Route Distinguisher");
3118 : vty_out(vty, "%s\n",
3119 : json_object_to_json_string(
3120 : json_no));
3121 : json_object_free(json_no);
3122 : } else
3123 : vty_out(vty,
3124 : "%% Malformed Route Distinguisher\n");
3125 : return CMD_WARNING;
3126 : }
3127 : }
3128 :
3129 : ret = str2sockunion(argv[idx_ipv4]->arg, &su);
3130 : if (ret < 0) {
3131 : if (uj) {
3132 : json_object *json_no = NULL;
3133 : json_no = json_object_new_object();
3134 : json_object_string_add(json_no, "warning",
3135 : "Malformed address");
3136 : vty_out(vty, "%s\n",
3137 : json_object_to_json_string(json_no));
3138 : json_object_free(json_no);
3139 : } else
3140 : vty_out(vty, "Malformed address: %s\n",
3141 : argv[idx_ext_community]->arg);
3142 : return CMD_WARNING;
3143 : }
3144 :
3145 : peer = peer_lookup(NULL, &su);
3146 : if (!peer || !peer->afc[afi][SAFI_MPLS_VPN]) {
3147 : if (uj) {
3148 : json_object *json_no = NULL;
3149 : json_no = json_object_new_object();
3150 : json_object_string_add(
3151 : json_no, "warning",
3152 : "No such neighbor or address family");
3153 : vty_out(vty, "%s\n",
3154 : json_object_to_json_string(json_no));
3155 : json_object_free(json_no);
3156 : } else
3157 : vty_out(vty,
3158 : "%% No such neighbor or address family\n");
3159 : return CMD_WARNING;
3160 : }
3161 :
3162 : if (prefix_rd_all)
3163 : return bgp_show_mpls_vpn(vty, afi, NULL,
3164 : bgp_show_type_neighbor, &su, 0,
3165 : uj);
3166 : else
3167 : return bgp_show_mpls_vpn(vty, afi, &prd,
3168 : bgp_show_type_neighbor, &su, 0,
3169 : uj);
3170 : }
3171 : return CMD_SUCCESS;
3172 : }
3173 :
3174 : DEFUN (show_ip_bgp_vpn_all_neighbor_advertised_routes,
3175 : show_ip_bgp_vpn_all_neighbor_advertised_routes_cmd,
3176 : "show [ip] bgp <vpnv4|vpnv6> all neighbors A.B.C.D advertised-routes [json]",
3177 : SHOW_STR
3178 : IP_STR
3179 : BGP_STR
3180 : BGP_VPNVX_HELP_STR
3181 : "Display information about all VPNv4/VPNv6 NLRIs\n"
3182 : "Detailed information on TCP and BGP neighbor connections\n"
3183 : "Neighbor to display information about\n"
3184 : "Display the routes advertised to a BGP neighbor\n"
3185 : JSON_STR)
3186 : {
3187 : int idx_ipv4 = 6;
3188 : int ret;
3189 : struct peer *peer;
3190 : union sockunion su;
3191 : bool uj = use_json(argc, argv);
3192 : afi_t afi;
3193 : int idx = 0;
3194 :
3195 : if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
3196 : ret = str2sockunion(argv[idx_ipv4]->arg, &su);
3197 : if (ret < 0) {
3198 : if (uj) {
3199 : json_object *json_no = NULL;
3200 : json_no = json_object_new_object();
3201 : json_object_string_add(json_no, "warning",
3202 : "Malformed address");
3203 : vty_out(vty, "%s\n",
3204 : json_object_to_json_string(json_no));
3205 : json_object_free(json_no);
3206 : } else
3207 : vty_out(vty, "Malformed address: %s\n",
3208 : argv[idx_ipv4]->arg);
3209 : return CMD_WARNING;
3210 : }
3211 : peer = peer_lookup(NULL, &su);
3212 : if (!peer || !peer->afc[afi][SAFI_MPLS_VPN]) {
3213 : if (uj) {
3214 : json_object *json_no = NULL;
3215 : json_no = json_object_new_object();
3216 : json_object_string_add(
3217 : json_no, "warning",
3218 : "No such neighbor or address family");
3219 : vty_out(vty, "%s\n",
3220 : json_object_to_json_string(json_no));
3221 : json_object_free(json_no);
3222 : } else
3223 : vty_out(vty,
3224 : "%% No such neighbor or address family\n");
3225 : return CMD_WARNING;
3226 : }
3227 : return show_adj_route_vpn(vty, peer, NULL, AFI_IP,
3228 : SAFI_MPLS_VPN, uj);
3229 : }
3230 : return CMD_SUCCESS;
3231 : }
3232 :
3233 : DEFUN (show_ip_bgp_vpn_rd_neighbor_advertised_routes,
3234 : show_ip_bgp_vpn_rd_neighbor_advertised_routes_cmd,
3235 : "show [ip] bgp <vpnv4|vpnv6> rd <ASN:NN_OR_IP-ADDRESS:NN|all> neighbors A.B.C.D advertised-routes [json]",
3236 : SHOW_STR
3237 : IP_STR
3238 : BGP_STR
3239 : BGP_VPNVX_HELP_STR
3240 : "Display information for a route distinguisher\n"
3241 : "VPN Route Distinguisher\n"
3242 : "All VPN Route Distinguishers\n"
3243 : "Detailed information on TCP and BGP neighbor connections\n"
3244 : "Neighbor to display information about\n"
3245 : "Display the routes advertised to a BGP neighbor\n"
3246 : JSON_STR)
3247 : {
3248 : int idx_ext_community = 5;
3249 : int idx_ipv4 = 7;
3250 : int ret;
3251 : struct peer *peer;
3252 : struct prefix_rd prd;
3253 : union sockunion su;
3254 : bool uj = use_json(argc, argv);
3255 : afi_t afi;
3256 : int idx = 0;
3257 :
3258 : if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
3259 : ret = str2sockunion(argv[idx_ipv4]->arg, &su);
3260 : if (ret < 0) {
3261 : if (uj) {
3262 : json_object *json_no = NULL;
3263 : json_no = json_object_new_object();
3264 : json_object_string_add(json_no, "warning",
3265 : "Malformed address");
3266 : vty_out(vty, "%s\n",
3267 : json_object_to_json_string(json_no));
3268 : json_object_free(json_no);
3269 : } else
3270 : vty_out(vty, "Malformed address: %s\n",
3271 : argv[idx_ext_community]->arg);
3272 : return CMD_WARNING;
3273 : }
3274 : peer = peer_lookup(NULL, &su);
3275 : if (!peer || !peer->afc[afi][SAFI_MPLS_VPN]) {
3276 : if (uj) {
3277 : json_object *json_no = NULL;
3278 : json_no = json_object_new_object();
3279 : json_object_string_add(
3280 : json_no, "warning",
3281 : "No such neighbor or address family");
3282 : vty_out(vty, "%s\n",
3283 : json_object_to_json_string(json_no));
3284 : json_object_free(json_no);
3285 : } else
3286 : vty_out(vty,
3287 : "%% No such neighbor or address family\n");
3288 : return CMD_WARNING;
3289 : }
3290 :
3291 : if (!strcmp(argv[idx_ext_community]->arg, "all"))
3292 : return show_adj_route_vpn(vty, peer, NULL, AFI_IP,
3293 : SAFI_MPLS_VPN, uj);
3294 : ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
3295 : if (!ret) {
3296 : if (uj) {
3297 : json_object *json_no = NULL;
3298 : json_no = json_object_new_object();
3299 : json_object_string_add(
3300 : json_no, "warning",
3301 : "Malformed Route Distinguisher");
3302 : vty_out(vty, "%s\n",
3303 : json_object_to_json_string(json_no));
3304 : json_object_free(json_no);
3305 : } else
3306 : vty_out(vty,
3307 : "%% Malformed Route Distinguisher\n");
3308 : return CMD_WARNING;
3309 : }
3310 :
3311 : return show_adj_route_vpn(vty, peer, &prd, AFI_IP,
3312 : SAFI_MPLS_VPN, uj);
3313 : }
3314 : return CMD_SUCCESS;
3315 : }
3316 : #endif /* KEEP_OLD_VPN_COMMANDS */
3317 :
3318 4 : void bgp_mplsvpn_init(void)
3319 : {
3320 4 : install_element(BGP_VPNV4_NODE, &vpnv4_network_cmd);
3321 4 : install_element(BGP_VPNV4_NODE, &vpnv4_network_route_map_cmd);
3322 4 : install_element(BGP_VPNV4_NODE, &no_vpnv4_network_cmd);
3323 :
3324 4 : install_element(BGP_VPNV6_NODE, &vpnv6_network_cmd);
3325 4 : install_element(BGP_VPNV6_NODE, &no_vpnv6_network_cmd);
3326 :
3327 4 : install_element(VIEW_NODE, &show_bgp_ip_vpn_all_rd_cmd);
3328 4 : install_element(VIEW_NODE, &show_bgp_ip_vpn_rd_cmd);
3329 : #ifdef KEEP_OLD_VPN_COMMANDS
3330 : install_element(VIEW_NODE, &show_ip_bgp_vpn_rd_cmd);
3331 : install_element(VIEW_NODE, &show_ip_bgp_vpn_all_cmd);
3332 : install_element(VIEW_NODE, &show_ip_bgp_vpn_all_tags_cmd);
3333 : install_element(VIEW_NODE, &show_ip_bgp_vpn_rd_tags_cmd);
3334 : install_element(VIEW_NODE, &show_ip_bgp_vpn_all_neighbor_routes_cmd);
3335 : install_element(VIEW_NODE, &show_ip_bgp_vpn_rd_neighbor_routes_cmd);
3336 : install_element(VIEW_NODE,
3337 : &show_ip_bgp_vpn_all_neighbor_advertised_routes_cmd);
3338 : install_element(VIEW_NODE,
3339 : &show_ip_bgp_vpn_rd_neighbor_advertised_routes_cmd);
3340 : #endif /* KEEP_OLD_VPN_COMMANDS */
3341 4 : }
3342 :
3343 0 : vrf_id_t get_first_vrf_for_redirect_with_rt(struct ecommunity *eckey)
3344 : {
3345 0 : struct listnode *mnode, *mnnode;
3346 0 : struct bgp *bgp;
3347 0 : afi_t afi = AFI_IP;
3348 :
3349 0 : if (eckey->unit_size == IPV6_ECOMMUNITY_SIZE)
3350 0 : afi = AFI_IP6;
3351 :
3352 0 : for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
3353 0 : struct ecommunity *ec;
3354 :
3355 0 : if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
3356 0 : continue;
3357 :
3358 0 : ec = bgp->vpn_policy[afi].import_redirect_rtlist;
3359 :
3360 0 : if (ec && eckey->unit_size != ec->unit_size)
3361 0 : continue;
3362 :
3363 0 : if (ecommunity_include(ec, eckey))
3364 0 : return bgp->vrf_id;
3365 : }
3366 : return VRF_UNKNOWN;
3367 : }
3368 :
3369 : /*
3370 : * The purpose of this function is to process leaks that were deferred
3371 : * from earlier per-vrf configuration due to not-yet-existing default
3372 : * vrf, in other words, configuration such as:
3373 : *
3374 : * router bgp MMM vrf FOO
3375 : * address-family ipv4 unicast
3376 : * rd vpn export 1:1
3377 : * exit-address-family
3378 : *
3379 : * router bgp NNN
3380 : * ...
3381 : *
3382 : * This function gets called when the default instance ("router bgp NNN")
3383 : * is created.
3384 : */
3385 4 : void vpn_leak_postchange_all(void)
3386 : {
3387 4 : struct listnode *next;
3388 4 : struct bgp *bgp;
3389 4 : struct bgp *bgp_default = bgp_get_default();
3390 :
3391 4 : assert(bgp_default);
3392 :
3393 : /* First, do any exporting from VRFs to the single VPN RIB */
3394 12 : for (ALL_LIST_ELEMENTS_RO(bm->bgp, next, bgp)) {
3395 :
3396 4 : if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
3397 4 : continue;
3398 :
3399 0 : vpn_leak_postchange(
3400 : BGP_VPN_POLICY_DIR_TOVPN,
3401 : AFI_IP,
3402 : bgp_default,
3403 : bgp);
3404 :
3405 0 : vpn_leak_postchange(
3406 : BGP_VPN_POLICY_DIR_TOVPN,
3407 : AFI_IP6,
3408 : bgp_default,
3409 : bgp);
3410 : }
3411 :
3412 : /* Now, do any importing to VRFs from the single VPN RIB */
3413 12 : for (ALL_LIST_ELEMENTS_RO(bm->bgp, next, bgp)) {
3414 :
3415 4 : if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
3416 4 : continue;
3417 :
3418 0 : vpn_leak_postchange(
3419 : BGP_VPN_POLICY_DIR_FROMVPN,
3420 : AFI_IP,
3421 : bgp_default,
3422 : bgp);
3423 :
3424 0 : vpn_leak_postchange(
3425 : BGP_VPN_POLICY_DIR_FROMVPN,
3426 : AFI_IP6,
3427 : bgp_default,
3428 : bgp);
3429 : }
3430 4 : }
3431 :
3432 : /* When a bgp vrf instance is unconfigured, remove its routes
3433 : * from the VPN table and this vrf could be importing routes from other
3434 : * bgp vrf instnaces, unimport them.
3435 : * VRF X and VRF Y are exporting routes to each other.
3436 : * When VRF X is deleted, unimport its routes from all target vrfs,
3437 : * also VRF Y should unimport its routes from VRF X table.
3438 : * This will ensure VPN table is cleaned up appropriately.
3439 : */
3440 4 : void bgp_vpn_leak_unimport(struct bgp *from_bgp)
3441 : {
3442 4 : struct bgp *to_bgp;
3443 4 : const char *tmp_name;
3444 4 : char *vname;
3445 4 : struct listnode *node, *next;
3446 4 : safi_t safi = SAFI_UNICAST;
3447 4 : afi_t afi;
3448 4 : bool is_vrf_leak_bind;
3449 4 : int debug;
3450 :
3451 4 : if (from_bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
3452 : return;
3453 :
3454 0 : debug = (BGP_DEBUG(vpn, VPN_LEAK_TO_VRF) |
3455 : BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF));
3456 :
3457 0 : tmp_name = from_bgp->name ? from_bgp->name : VRF_DEFAULT_NAME;
3458 :
3459 0 : for (afi = 0; afi < AFI_MAX; ++afi) {
3460 : /* vrf leak is for IPv4 and IPv6 Unicast only */
3461 0 : if (afi != AFI_IP && afi != AFI_IP6)
3462 0 : continue;
3463 :
3464 0 : for (ALL_LIST_ELEMENTS_RO(bm->bgp, next, to_bgp)) {
3465 0 : if (from_bgp == to_bgp)
3466 0 : continue;
3467 :
3468 : /* Unimport and remove source vrf from the
3469 : * other vrfs import list.
3470 : */
3471 0 : struct vpn_policy *to_vpolicy;
3472 :
3473 0 : is_vrf_leak_bind = false;
3474 0 : to_vpolicy = &(to_bgp->vpn_policy[afi]);
3475 0 : for (ALL_LIST_ELEMENTS_RO(to_vpolicy->import_vrf, node,
3476 : vname)) {
3477 0 : if (strcmp(vname, tmp_name) == 0) {
3478 : is_vrf_leak_bind = true;
3479 : break;
3480 : }
3481 : }
3482 : /* skip this bgp instance as there is no leak to this
3483 : * vrf instance.
3484 : */
3485 0 : if (!is_vrf_leak_bind)
3486 0 : continue;
3487 :
3488 0 : if (debug)
3489 0 : zlog_debug("%s: unimport routes from %s to_bgp %s afi %s import vrfs count %u",
3490 : __func__, from_bgp->name_pretty,
3491 : to_bgp->name_pretty, afi2str(afi),
3492 : to_vpolicy->import_vrf->count);
3493 :
3494 0 : vrf_unimport_from_vrf(to_bgp, from_bgp, afi, safi);
3495 :
3496 : /* readd vrf name as unimport removes import vrf name
3497 : * from the destination vrf's import list where the
3498 : * `import vrf` configuration still exist.
3499 : */
3500 0 : vname = XSTRDUP(MTYPE_TMP, tmp_name);
3501 0 : listnode_add(to_bgp->vpn_policy[afi].import_vrf,
3502 : vname);
3503 0 : SET_FLAG(to_bgp->af_flags[afi][safi],
3504 : BGP_CONFIG_VRF_TO_VRF_IMPORT);
3505 :
3506 : /* If to_bgp exports its routes to the bgp vrf
3507 : * which is being deleted, un-import the
3508 : * to_bgp routes from VPN.
3509 : */
3510 0 : for (ALL_LIST_ELEMENTS_RO(to_bgp->vpn_policy[afi]
3511 : .export_vrf, node,
3512 : vname)) {
3513 0 : if (strcmp(vname, tmp_name) == 0) {
3514 0 : vrf_unimport_from_vrf(from_bgp, to_bgp,
3515 : afi, safi);
3516 0 : break;
3517 : }
3518 : }
3519 : }
3520 : }
3521 : return;
3522 : }
3523 :
3524 : /* When a router bgp is configured, there could be a bgp vrf
3525 : * instance importing routes from this newly configured
3526 : * bgp vrf instance. Export routes from configured
3527 : * bgp vrf to VPN.
3528 : * VRF Y has import from bgp vrf x,
3529 : * when a bgp vrf x instance is created, export its routes
3530 : * to VRF Y instance.
3531 : */
3532 0 : void bgp_vpn_leak_export(struct bgp *from_bgp)
3533 : {
3534 0 : afi_t afi;
3535 0 : const char *export_name;
3536 0 : char *vname;
3537 0 : struct listnode *node, *next;
3538 0 : struct ecommunity *ecom;
3539 0 : enum vpn_policy_direction idir, edir;
3540 0 : safi_t safi = SAFI_UNICAST;
3541 0 : struct bgp *to_bgp;
3542 0 : int debug;
3543 :
3544 0 : debug = (BGP_DEBUG(vpn, VPN_LEAK_TO_VRF) |
3545 : BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF));
3546 :
3547 0 : idir = BGP_VPN_POLICY_DIR_FROMVPN;
3548 0 : edir = BGP_VPN_POLICY_DIR_TOVPN;
3549 :
3550 0 : export_name = from_bgp->name ? from_bgp->name : VRF_DEFAULT_NAME;
3551 :
3552 0 : for (afi = 0; afi < AFI_MAX; ++afi) {
3553 : /* vrf leak is for IPv4 and IPv6 Unicast only */
3554 0 : if (afi != AFI_IP && afi != AFI_IP6)
3555 0 : continue;
3556 :
3557 0 : for (ALL_LIST_ELEMENTS_RO(bm->bgp, next, to_bgp)) {
3558 0 : if (from_bgp == to_bgp)
3559 0 : continue;
3560 :
3561 : /* bgp instance has import list, check to see if newly
3562 : * configured bgp instance is the list.
3563 : */
3564 0 : struct vpn_policy *to_vpolicy;
3565 :
3566 0 : to_vpolicy = &(to_bgp->vpn_policy[afi]);
3567 0 : for (ALL_LIST_ELEMENTS_RO(to_vpolicy->import_vrf,
3568 : node, vname)) {
3569 0 : if (strcmp(vname, export_name) != 0)
3570 0 : continue;
3571 :
3572 0 : if (debug)
3573 0 : zlog_debug("%s: found from_bgp %s in to_bgp %s import list, import routes.",
3574 : __func__,
3575 : export_name, to_bgp->name_pretty);
3576 :
3577 0 : ecom = from_bgp->vpn_policy[afi].rtlist[edir];
3578 : /* remove import rt, it will be readded
3579 : * as part of import from vrf.
3580 : */
3581 0 : if (ecom)
3582 0 : ecommunity_del_val(
3583 : to_vpolicy->rtlist[idir],
3584 : (struct ecommunity_val *)
3585 0 : ecom->val);
3586 0 : vrf_import_from_vrf(to_bgp, from_bgp,
3587 : afi, safi);
3588 0 : break;
3589 :
3590 : }
3591 : }
3592 : }
3593 0 : }
|