1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * Copyright 2009-2016, LabN Consulting, L.L.C.
9 #include "lib/prefix.h"
10 #include "lib/agg_table.h"
12 #include "lib/memory.h"
13 #include "lib/routemap.h"
15 #include "lib/linklist.h"
16 #include "lib/command.h"
17 #include "lib/stream.h"
18 #include "lib/ringbuf.h"
19 #include "lib/lib_errors.h"
21 #include "bgpd/bgpd.h"
22 #include "bgpd/bgp_ecommunity.h"
23 #include "bgpd/bgp_attr.h"
25 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
26 #include "bgpd/rfapi/rfapi.h"
27 #include "bgpd/rfapi/rfapi_backend.h"
29 #include "bgpd/bgp_route.h"
30 #include "bgpd/bgp_mplsvpn.h"
31 #include "bgpd/bgp_aspath.h"
32 #include "bgpd/bgp_advertise.h"
33 #include "bgpd/bgp_vnc_types.h"
34 #include "bgpd/bgp_zebra.h"
36 #include "bgpd/rfapi/rfapi_import.h"
37 #include "bgpd/rfapi/rfapi_private.h"
38 #include "bgpd/rfapi/rfapi_monitor.h"
39 #include "bgpd/rfapi/rfapi_vty.h"
40 #include "bgpd/rfapi/vnc_export_bgp.h"
41 #include "bgpd/rfapi/vnc_export_bgp_p.h"
42 #include "bgpd/rfapi/vnc_zebra.h"
43 #include "bgpd/rfapi/vnc_import_bgp.h"
44 #include "bgpd/rfapi/rfapi_rib.h"
45 #include "bgpd/rfapi/rfapi_ap.h"
46 #include "bgpd/rfapi/rfapi_encap_tlv.h"
47 #include "bgpd/rfapi/vnc_debug.h"
49 #ifdef HAVE_GLIBC_BACKTRACE
50 /* for backtrace and friends */
52 #endif /* HAVE_GLIBC_BACKTRACE */
54 struct ethaddr rfapi_ethaddr0
= {{0}};
56 #define DEBUG_RFAPI_STR "RF API debugging/testing command\n"
58 const char *rfapi_error_str(int code
)
64 return "BGP or VNC not configured";
68 return "Handle already open";
70 return "Incomplete configuration";
72 return "Invalid address family";
74 return "Called from within a callback procedure";
76 return "Invalid handle";
78 return "Invalid argument";
80 return "Stale descriptor";
82 return "Unknown error";
86 /*------------------------------------------
87 * rfapi_get_response_lifetime_default
89 * Returns the default lifetime for a response.
90 * rfp_start_val value returned by rfp_start or
91 * NULL (=use default instance)
98 * return value: The bgp instance default lifetime for a response.
99 --------------------------------------------*/
100 int rfapi_get_response_lifetime_default(void *rfp_start_val
)
102 struct bgp
*bgp
= rfapi_bgp_lookup_by_rfp(rfp_start_val
);
104 return bgp
->rfapi_cfg
->default_response_lifetime
;
105 return BGP_VNC_DEFAULT_RESPONSE_LIFETIME_DEFAULT
;
108 /*------------------------------------------
109 * rfapi_is_vnc_configured
111 * Returns if VNC is configured
114 * rfp_start_val value returned by rfp_start or
115 * NULL (=use default instance)
119 * return value: If VNC is configured for the bgpd instance
121 * ENXIO VNC not configured
122 --------------------------------------------*/
123 int rfapi_is_vnc_configured(void *rfp_start_val
)
125 struct bgp
*bgp
= rfapi_bgp_lookup_by_rfp(rfp_start_val
);
126 if (bgp_rfapi_is_vnc_configured(bgp
) == 0)
132 /*------------------------------------------
135 * Get the virtual network address used by an NVE based on it's RFD
138 * rfd: rfapi descriptor returned by rfapi_open or rfapi_create_generic
143 * vn NVE virtual network address
144 *------------------------------------------*/
145 struct rfapi_ip_addr
*rfapi_get_vn_addr(void *rfd
)
147 struct rfapi_descriptor
*rrfd
= (struct rfapi_descriptor
*)rfd
;
148 return &rrfd
->vn_addr
;
151 /*------------------------------------------
154 * Get the underlay network address used by an NVE based on it's RFD
157 * rfd: rfapi descriptor returned by rfapi_open or rfapi_create_generic
162 * un NVE underlay network address
163 *------------------------------------------*/
164 struct rfapi_ip_addr
*rfapi_get_un_addr(void *rfd
)
166 struct rfapi_descriptor
*rrfd
= (struct rfapi_descriptor
*)rfd
;
167 return &rrfd
->un_addr
;
170 int rfapi_ip_addr_cmp(struct rfapi_ip_addr
*a1
, struct rfapi_ip_addr
*a2
)
172 if (a1
->addr_family
!= a2
->addr_family
)
173 return a1
->addr_family
- a2
->addr_family
;
175 if (a1
->addr_family
== AF_INET
) {
176 return IPV4_ADDR_CMP(&a1
->addr
.v4
, &a2
->addr
.v4
);
179 if (a1
->addr_family
== AF_INET6
) {
180 return IPV6_ADDR_CMP(&a1
->addr
.v6
, &a2
->addr
.v6
);
188 static int rfapi_find_node(struct bgp
*bgp
, struct rfapi_ip_addr
*vn_addr
,
189 struct rfapi_ip_addr
*un_addr
,
190 struct agg_node
**node
)
207 afi
= family2afi(un_addr
->addr_family
);
212 if ((rc
= rfapiRaddr2Qprefix(un_addr
, &p
)))
215 rn
= agg_node_lookup(h
->un
[afi
], &p
);
228 int rfapi_find_rfd(struct bgp
*bgp
, struct rfapi_ip_addr
*vn_addr
,
229 struct rfapi_ip_addr
*un_addr
, struct rfapi_descriptor
**rfd
)
234 rc
= rfapi_find_node(bgp
, vn_addr
, un_addr
, &rn
);
239 for (*rfd
= (struct rfapi_descriptor
*)(rn
->info
); *rfd
;
240 *rfd
= (*rfd
)->next
) {
241 if (!rfapi_ip_addr_cmp(&(*rfd
)->vn_addr
, vn_addr
))
251 /*------------------------------------------
255 * un underlay network address
256 * vn virtual network address
259 * pHandle pointer to location to store handle
263 * ENOENT no matching handle
264 * ENXIO BGP or VNC not configured
265 *------------------------------------------*/
266 static int rfapi_find_handle(struct bgp
*bgp
, struct rfapi_ip_addr
*vn_addr
,
267 struct rfapi_ip_addr
*un_addr
,
268 rfapi_handle
*handle
)
270 struct rfapi_descriptor
**rfd
;
272 rfd
= (struct rfapi_descriptor
**)handle
;
274 return rfapi_find_rfd(bgp
, vn_addr
, un_addr
, rfd
);
277 static int rfapi_find_handle_vty(struct vty
*vty
, struct rfapi_ip_addr
*vn_addr
,
278 struct rfapi_ip_addr
*un_addr
,
279 rfapi_handle
*handle
)
282 struct rfapi_descriptor
**rfd
;
284 bgp
= bgp_get_default(); /* assume 1 instance for now */
286 rfd
= (struct rfapi_descriptor
**)handle
;
288 return rfapi_find_rfd(bgp
, vn_addr
, un_addr
, rfd
);
291 static int is_valid_rfd(struct rfapi_descriptor
*rfd
)
295 if (!rfd
|| rfd
->bgp
== NULL
)
300 RFAPI_HD_FLAG_IS_VRF
)) /* assume VRF/internal are valid */
303 if (rfapi_find_handle(rfd
->bgp
, &rfd
->vn_addr
, &rfd
->un_addr
, &hh
))
313 * check status of descriptor
315 int rfapi_check(void *handle
)
317 struct rfapi_descriptor
*rfd
= (struct rfapi_descriptor
*)handle
;
321 if (!rfd
|| rfd
->bgp
== NULL
)
326 RFAPI_HD_FLAG_IS_VRF
)) /* assume VRF/internal are valid */
329 if ((rc
= rfapi_find_handle(rfd
->bgp
, &rfd
->vn_addr
, &rfd
->un_addr
,
343 void del_vnc_route(struct rfapi_descriptor
*rfd
,
344 struct peer
*peer
, /* rfd->peer for RFP regs */
345 struct bgp
*bgp
, safi_t safi
, const struct prefix
*p
,
346 struct prefix_rd
*prd
, uint8_t type
, uint8_t sub_type
,
347 struct rfapi_nexthop
*lnh
, int kill
)
349 afi_t afi
; /* of the VN address */
351 struct bgp_path_info
*bpi
;
352 struct prefix_rd prd0
;
354 afi
= family2afi(p
->family
);
355 assert(afi
== AFI_IP
|| afi
== AFI_IP6
);
357 if (safi
== SAFI_ENCAP
) {
358 memset(&prd0
, 0, sizeof(prd0
));
359 prd0
.family
= AF_UNSPEC
;
363 bn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
365 vnc_zlog_debug_verbose(
366 "%s: peer=%p, prefix=%pFX, prd=%pRDP afi=%d, safi=%d bn=%p, bn->info=%p",
367 __func__
, peer
, p
, prd
, afi
, safi
, bn
,
368 (bn
? bgp_dest_get_bgp_path_info(bn
) : NULL
));
370 for (bpi
= (bn
? bgp_dest_get_bgp_path_info(bn
) : NULL
); bpi
;
373 vnc_zlog_debug_verbose(
374 "%s: trying bpi=%p, bpi->peer=%p, bpi->type=%d, bpi->sub_type=%d, bpi->extra->vnc.export.rfapi_handle=%p, local_pref=%" PRIu64
,
375 __func__
, bpi
, bpi
->peer
, bpi
->type
, bpi
->sub_type
,
376 (bpi
->extra
? bpi
->extra
->vnc
.export
.rfapi_handle
378 CHECK_FLAG(bpi
->attr
->flag
,
379 ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)
380 ? bpi
->attr
->local_pref
: 0));
382 if (bpi
->peer
== peer
&& bpi
->type
== type
383 && bpi
->sub_type
== sub_type
&& bpi
->extra
384 && bpi
->extra
->vnc
.export
.rfapi_handle
== (void *)rfd
) {
386 vnc_zlog_debug_verbose("%s: matched it", __func__
);
394 * lnh set means to JUST delete the local nexthop from this
395 * route. Leave the route itself in place.
396 * TBD add return code reporting of success/failure
398 if (!bpi
|| !bpi
->extra
399 || !bpi
->extra
->vnc
.export
.local_nexthops
) {
403 vnc_zlog_debug_verbose(
404 "%s: lnh list already empty at prefix %pFX",
412 struct listnode
*node
;
413 struct rfapi_nexthop
*pLnh
= NULL
;
415 for (ALL_LIST_ELEMENTS_RO(bpi
->extra
->vnc
.export
.local_nexthops
,
418 if (prefix_same(&pLnh
->addr
, &lnh
->addr
)) {
424 listnode_delete(bpi
->extra
->vnc
.export
.local_nexthops
,
427 /* silly rabbit, listnode_delete doesn't invoke
428 * list->del on data */
429 rfapi_nexthop_free(pLnh
);
431 vnc_zlog_debug_verbose("%s: desired lnh not found %pFX",
438 * loop back to import tables
439 * Do this before removing from BGP RIB because rfapiProcessWithdraw
442 rfapiProcessWithdraw(peer
, rfd
, p
, prd
, NULL
, afi
, safi
, type
, kill
);
445 vnc_zlog_debug_verbose(
446 "%s: Found route (safi=%d) to delete at prefix %pFX",
449 if (safi
== SAFI_MPLS_VPN
) {
450 struct bgp_dest
*pdest
= NULL
;
451 struct bgp_table
*table
= NULL
;
453 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
454 (struct prefix
*)prd
);
455 table
= bgp_dest_get_bgp_table_info(pdest
);
457 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
458 bgp
, prd
, table
, p
, bpi
);
459 bgp_dest_unlock_node(pdest
);
463 * Delete local_nexthops list
465 if (bpi
->extra
&& bpi
->extra
->vnc
.export
.local_nexthops
)
466 list_delete(&bpi
->extra
->vnc
.export
.local_nexthops
);
468 bgp_aggregate_decrement(bgp
, p
, bpi
, afi
, safi
);
469 bgp_path_info_delete(bn
, bpi
);
470 bgp_process(bgp
, bn
, afi
, safi
);
472 vnc_zlog_debug_verbose(
473 "%s: Couldn't find route (safi=%d) at prefix %pFX",
477 bgp_dest_unlock_node(bn
);
480 struct rfapi_nexthop
*rfapi_nexthop_new(struct rfapi_nexthop
*copyme
)
482 struct rfapi_nexthop
*new =
483 XCALLOC(MTYPE_RFAPI_NEXTHOP
, sizeof(struct rfapi_nexthop
));
489 void rfapi_nexthop_free(void *p
)
491 struct rfapi_nexthop
*goner
= p
;
492 XFREE(MTYPE_RFAPI_NEXTHOP
, goner
);
495 struct rfapi_vn_option
*rfapi_vn_options_dup(struct rfapi_vn_option
*existing
)
497 struct rfapi_vn_option
*p
;
498 struct rfapi_vn_option
*head
= NULL
;
499 struct rfapi_vn_option
*tail
= NULL
;
501 for (p
= existing
; p
; p
= p
->next
) {
502 struct rfapi_vn_option
*new;
504 new = XCALLOC(MTYPE_RFAPI_VN_OPTION
,
505 sizeof(struct rfapi_vn_option
));
518 void rfapi_un_options_free(struct rfapi_un_option
*p
)
520 struct rfapi_un_option
*next
;
524 XFREE(MTYPE_RFAPI_UN_OPTION
, p
);
529 void rfapi_vn_options_free(struct rfapi_vn_option
*p
)
531 struct rfapi_vn_option
*next
;
535 XFREE(MTYPE_RFAPI_VN_OPTION
, p
);
540 /* Based on bgp_redistribute_add() */
541 void add_vnc_route(struct rfapi_descriptor
*rfd
, /* cookie, VPN UN addr, peer */
542 struct bgp
*bgp
, int safi
, const struct prefix
*p
,
543 struct prefix_rd
*prd
, struct rfapi_ip_addr
*nexthop
,
544 uint32_t *local_pref
,
545 uint32_t *lifetime
, /* NULL => dont send lifetime */
546 struct bgp_tea_options
*rfp_options
,
547 struct rfapi_un_option
*options_un
,
548 struct rfapi_vn_option
*options_vn
,
549 struct ecommunity
*rt_export_list
, /* Copied, not consumed */
550 uint32_t *med
, /* NULL => don't set med */
551 uint32_t *label
, /* low order 3 bytes */
552 uint8_t type
, uint8_t sub_type
, /* RFP, NORMAL or REDIST */
555 afi_t afi
; /* of the VN address */
556 struct bgp_path_info
*new;
557 struct bgp_path_info
*bpi
;
560 struct attr attr
= {0};
561 struct attr
*new_attr
;
564 struct bgp_attr_encap_subtlv
*encaptlv
;
565 char buf
[PREFIX_STRLEN
];
567 struct rfapi_nexthop
*lnh
= NULL
; /* local nexthop */
568 struct rfapi_vn_option
*vo
;
569 struct rfapi_l2address_option
*l2o
= NULL
;
570 struct rfapi_ip_addr
*un_addr
= &rfd
->un_addr
;
572 bgp_encap_types TunnelType
= BGP_ENCAP_TYPE_RESERVED
;
573 struct bgp_redist
*red
;
575 if (safi
== SAFI_ENCAP
576 && !(bgp
->rfapi_cfg
->flags
& BGP_VNC_CONFIG_ADV_UN_METHOD_ENCAP
)) {
579 * Encap mode not enabled. UN addresses will be communicated
580 * via VNC Tunnel subtlv instead.
582 vnc_zlog_debug_verbose(
583 "%s: encap mode not enabled, not adding SAFI_ENCAP route",
588 for (vo
= options_vn
; vo
; vo
= vo
->next
) {
589 if (RFAPI_VN_OPTION_TYPE_L2ADDR
== vo
->type
) {
591 if (RFAPI_0_ETHERADDR(&l2o
->macaddr
))
592 l2o
= NULL
; /* not MAC resolution */
594 if (RFAPI_VN_OPTION_TYPE_LOCAL_NEXTHOP
== vo
->type
) {
595 lnh
= &vo
->v
.local_nexthop
;
602 label_val
= MPLS_LABEL_IMPLICIT_NULL
;
604 afi
= family2afi(p
->family
);
605 assert(afi
== AFI_IP
|| afi
== AFI_IP6
);
607 vnc_zlog_debug_verbose("%s: afi=%s, safi=%s", __func__
, afi2str(afi
),
610 /* Make default attribute. Produces already-interned attr.aspath */
611 /* Cripes, the memory management of attributes is byzantine */
613 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_INCOMPLETE
);
618 * extra: dynamically allocated, owned by attr
619 * aspath: points to interned hash from aspath hash table
624 * Route-specific un_options get added to the VPN SAFI
625 * advertisement tunnel encap attribute. (the per-NVE
626 * "default" un_options are put into the 1-per-NVE ENCAP
627 * SAFI advertisement). The VPN SAFI also gets the
628 * default un_options if there are no route-specific options.
631 struct rfapi_un_option
*uo
;
633 for (uo
= options_un
; uo
; uo
= uo
->next
) {
634 if (RFAPI_UN_OPTION_TYPE_TUNNELTYPE
== uo
->type
) {
635 TunnelType
= rfapi_tunneltype_option_to_tlv(
636 bgp
, un_addr
, &uo
->v
.tunnel
, &attr
,
643 * These are the NVE-specific "default" un_options which are
644 * put into the 1-per-NVE ENCAP advertisement.
646 if (rfd
->default_tunneltype_option
.type
) {
647 TunnelType
= rfapi_tunneltype_option_to_tlv(
648 bgp
, un_addr
, &rfd
->default_tunneltype_option
,
650 } else /* create default for local addse */
651 if (type
== ZEBRA_ROUTE_BGP
652 && sub_type
== BGP_ROUTE_RFP
)
653 TunnelType
= rfapi_tunneltype_option_to_tlv(
654 bgp
, un_addr
, NULL
, &attr
, l2o
!= NULL
);
657 if (TunnelType
== BGP_ENCAP_TYPE_MPLS
) {
658 if (safi
== SAFI_ENCAP
) {
659 /* Encap SAFI not used with MPLS */
660 vnc_zlog_debug_verbose(
661 "%s: mpls tunnel type, encap safi omitted",
663 aspath_unintern(&attr
.aspath
); /* Unintern original. */
669 attr
.local_pref
= *local_pref
;
670 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
675 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
678 /* override default weight assigned by bgp_attr_default_set() */
679 attr
.weight
= rfd
->peer
? rfd
->peer
->weight
[afi
][safi
] : 0;
682 * NB: ticket 81: do not reset attr.aspath here because it would
683 * cause iBGP peers to drop route
687 * Set originator ID for routes imported from BGP directly.
688 * These routes could be synthetic, and therefore could
689 * reuse the peer pointers of the routes they are derived
690 * from. Setting the originator ID to "us" prevents the
691 * wrong originator ID from being sent when this route is
692 * sent from a route reflector.
694 if (type
== ZEBRA_ROUTE_BGP_DIRECT
695 || type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
) {
696 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
);
697 attr
.originator_id
= bgp
->router_id
;
701 /* Set up vnc attribute (sub-tlv for Prefix Lifetime) */
702 if (lifetime
&& *lifetime
!= RFAPI_INFINITE_LIFETIME
) {
705 encaptlv
= XCALLOC(MTYPE_ENCAP_TLV
,
706 sizeof(struct bgp_attr_encap_subtlv
) + 4);
708 BGP_VNC_SUBTLV_TYPE_LIFETIME
; /* prefix lifetime */
709 encaptlv
->length
= 4;
710 lt
= htonl(*lifetime
);
711 memcpy(encaptlv
->value
, <
, 4);
712 bgp_attr_set_vnc_subtlvs(&attr
, encaptlv
);
713 vnc_zlog_debug_verbose(
714 "%s: set Encap Attr Prefix Lifetime to %d", __func__
,
718 /* add rfp options to vnc attr */
721 if (flags
& RFAPI_AHR_RFPOPT_IS_VNCTLV
) {
722 struct bgp_attr_encap_subtlv
*vnc_subtlvs
=
723 bgp_attr_get_vnc_subtlvs(&attr
);
725 * this flag means we're passing a pointer to an
726 * existing encap tlv chain which we should copy.
727 * It's a hack to avoid adding yet another argument
730 encaptlv
= encap_tlv_dup(
731 (struct bgp_attr_encap_subtlv
*)rfp_options
);
733 vnc_subtlvs
->next
= encaptlv
;
735 bgp_attr_set_vnc_subtlvs(&attr
, encaptlv
);
737 struct bgp_tea_options
*hop
;
738 /* XXX max of one tlv present so far from above code */
739 struct bgp_attr_encap_subtlv
*tail
=
740 bgp_attr_get_vnc_subtlvs(&attr
);
742 for (hop
= rfp_options
; hop
; hop
= hop
->next
) {
749 sizeof(struct bgp_attr_encap_subtlv
) + 2
752 BGP_VNC_SUBTLV_TYPE_RFPOPTION
; /* RFP
755 encaptlv
->length
= 2 + hop
->length
;
756 *((uint8_t *)(encaptlv
->value
) + 0) = hop
->type
;
757 *((uint8_t *)(encaptlv
->value
) + 1) =
759 memcpy(((uint8_t *)encaptlv
->value
) + 2,
760 hop
->value
, hop
->length
);
763 * add to end of subtlv chain
766 tail
->next
= encaptlv
;
768 bgp_attr_set_vnc_subtlvs(&attr
,
778 * extra: dynamically allocated, owned by attr
779 * vnc_subtlvs: dynamic chain, length 1
780 * aspath: points to interned hash from aspath hash table
784 bgp_attr_set_ecommunity(&attr
, ecommunity_new());
785 assert(bgp_attr_get_ecommunity(&attr
));
787 if (TunnelType
!= BGP_ENCAP_TYPE_MPLS
788 && TunnelType
!= BGP_ENCAP_TYPE_RESERVED
) {
790 * Add BGP Encapsulation Extended Community. Format described in
791 * section 4.5 of RFC 5512.
792 * Always include when not MPLS type, to disambiguate this case.
794 struct ecommunity_val beec
;
796 memset(&beec
, 0, sizeof(beec
));
797 beec
.val
[0] = ECOMMUNITY_ENCODE_OPAQUE
;
798 beec
.val
[1] = ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP
;
799 beec
.val
[6] = ((TunnelType
) >> 8) & 0xff;
800 beec
.val
[7] = (TunnelType
)&0xff;
801 ecommunity_add_val(bgp_attr_get_ecommunity(&attr
), &beec
, false,
806 * Add extended community attributes to match rt export list
808 if (rt_export_list
) {
809 bgp_attr_set_ecommunity(
810 &attr
, ecommunity_merge(bgp_attr_get_ecommunity(&attr
),
814 struct ecommunity
*ecomm
= bgp_attr_get_ecommunity(&attr
);
817 ecommunity_free(&ecomm
);
818 bgp_attr_set_ecommunity(&attr
, NULL
);
820 vnc_zlog_debug_verbose("%s: attr.ecommunity=%p", __func__
, ecomm
);
826 * extra: dynamically allocated, owned by attr
827 * vnc_subtlvs: dynamic chain, length 1
828 * ecommunity: dynamic 2-part
829 * aspath: points to interned hash from aspath hash table
832 /* stuff nexthop in attr_extra; which field depends on IPv4 or IPv6 */
833 switch (nexthop
->addr_family
) {
836 * set this field to prevent bgp_route.c code from setting
837 * mp_nexthop_global_in to self
839 attr
.nexthop
.s_addr
= nexthop
->addr
.v4
.s_addr
;
841 attr
.mp_nexthop_global_in
= nexthop
->addr
.v4
;
842 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
846 attr
.mp_nexthop_global
= nexthop
->addr
.v6
;
847 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
855 prefix2str(p
, buf
, sizeof(buf
));
861 * extra: dynamically allocated, owned by attr
862 * vnc_subtlvs: dynamic chain, length 1
863 * ecommunity: dynamic 2-part
864 * aspath: points to interned hash from aspath hash table
867 red
= bgp_redist_lookup(bgp
, afi
, type
, 0);
869 if (red
&& red
->redist_metric_flag
) {
870 attr
.med
= red
->redist_metric
;
871 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
874 bn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
877 * bgp_attr_intern creates a new reference to a cached
878 * attribute, but leaves the following bits of trash:
880 * - old attr->extra (free via bgp_attr_extra_free(attr))
882 * Note that it frees the original attr->extra->ecommunity
883 * but leaves the new attribute pointing to the ORIGINAL
884 * vnc options (which therefore we needn't free from the
887 new_attr
= bgp_attr_intern(&attr
);
889 aspath_unintern(&attr
.aspath
); /* Unintern original. */
895 * extra: dynamically allocated, owned by attr
896 * vnc_subtlvs: dynamic chain, length 1
897 * ecommunity: POINTS TO INTERNED ecom, THIS REF NOT COUNTED
899 * new_attr: an attr that is part of the hash table, distinct
900 * from attr which is static.
901 * extra: dynamically allocated, owned by new_attr (in hash table)
902 * vnc_subtlvs: POINTS TO SAME dynamic chain AS attr
903 * ecommunity: POINTS TO interned/refcounted dynamic 2-part AS attr
904 * aspath: POINTS TO interned/refcounted hashed block
906 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
) {
907 /* probably only need to check
908 * bpi->extra->vnc.export.rfapi_handle */
909 if (bpi
->peer
== rfd
->peer
&& bpi
->type
== type
910 && bpi
->sub_type
== sub_type
&& bpi
->extra
911 && bpi
->extra
->vnc
.export
.rfapi_handle
== (void *)rfd
) {
920 * Adding new local_nexthop, which does not by itself change
921 * what is advertised via BGP
924 if (!bpi
->extra
->vnc
.export
.local_nexthops
) {
925 /* TBD make arrangements to free when needed */
926 bpi
->extra
->vnc
.export
.local_nexthops
=
928 bpi
->extra
->vnc
.export
.local_nexthops
->del
=
935 struct listnode
*node
;
936 struct rfapi_nexthop
*pLnh
= NULL
;
938 for (ALL_LIST_ELEMENTS_RO(
939 bpi
->extra
->vnc
.export
.local_nexthops
,
942 if (prefix_same(&pLnh
->addr
, &lnh
->addr
)) {
948 * Not present, add new one
951 pLnh
= rfapi_nexthop_new(lnh
);
953 bpi
->extra
->vnc
.export
.local_nexthops
,
958 if (attrhash_cmp(bpi
->attr
, new_attr
)
959 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
960 bgp_attr_unintern(&new_attr
);
961 bgp_dest_unlock_node(bn
);
964 "%s: Found route (safi=%d) at prefix %s, no change",
965 __func__
, safi
, buf
);
969 /* The attribute is changed. */
970 bgp_path_info_set_flag(bn
, bpi
, BGP_PATH_ATTR_CHANGED
);
972 if (safi
== SAFI_MPLS_VPN
) {
973 struct bgp_dest
*pdest
= NULL
;
974 struct bgp_table
*table
= NULL
;
976 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
977 (struct prefix
*)prd
);
978 table
= bgp_dest_get_bgp_table_info(pdest
);
980 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
981 bgp
, prd
, table
, p
, bpi
);
982 bgp_dest_unlock_node(pdest
);
985 /* Rewrite BGP route information. */
986 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
987 bgp_path_info_restore(bn
, bpi
);
989 bgp_aggregate_decrement(bgp
, p
, bpi
, afi
, safi
);
990 bgp_attr_unintern(&bpi
->attr
);
991 bpi
->attr
= new_attr
;
992 bpi
->uptime
= monotime(NULL
);
995 if (safi
== SAFI_MPLS_VPN
) {
996 struct bgp_dest
*pdest
= NULL
;
997 struct bgp_table
*table
= NULL
;
999 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
1000 (struct prefix
*)prd
);
1001 table
= bgp_dest_get_bgp_table_info(pdest
);
1003 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
1004 bgp
, prd
, table
, p
, bpi
);
1005 bgp_dest_unlock_node(pdest
);
1008 /* Process change. */
1009 bgp_aggregate_increment(bgp
, p
, bpi
, afi
, safi
);
1010 bgp_process(bgp
, bn
, afi
, safi
);
1011 bgp_dest_unlock_node(bn
);
1014 "%s: Found route (safi=%d) at prefix %s, changed attr",
1015 __func__
, safi
, buf
);
1021 new = info_make(type
, sub_type
, 0, rfd
->peer
, new_attr
, NULL
);
1022 SET_FLAG(new->flags
, BGP_PATH_VALID
);
1024 /* save backref to rfapi handle */
1025 bgp_path_info_extra_get(new);
1026 new->extra
->vnc
.export
.rfapi_handle
= (void *)rfd
;
1027 encode_label(label_val
, &new->extra
->label
[0]);
1031 if (VNC_DEBUG(VERBOSE
)) {
1032 vnc_zlog_debug_verbose("%s: printing BPI", __func__
);
1033 rfapiPrintBi(NULL
, new);
1036 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
1037 bgp_path_info_add(bn
, new);
1039 if (safi
== SAFI_MPLS_VPN
) {
1040 struct bgp_dest
*pdest
= NULL
;
1041 struct bgp_table
*table
= NULL
;
1043 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
1044 table
= bgp_dest_get_bgp_table_info(pdest
);
1046 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
1047 bgp
, prd
, table
, p
, new);
1048 bgp_dest_unlock_node(pdest
);
1049 encode_label(label_val
, &bn
->local_label
);
1052 bgp_dest_unlock_node(bn
);
1053 bgp_process(bgp
, bn
, afi
, safi
);
1056 "%s: Added route (safi=%s) at prefix %s (bn=%p, prd=%pRDP)",
1057 __func__
, safi2str(safi
), buf
, bn
, prd
);
1060 /* Loop back to import tables */
1061 rfapiProcessUpdate(rfd
->peer
, rfd
, p
, prd
, new_attr
, afi
, safi
, type
,
1062 sub_type
, &label_val
);
1063 vnc_zlog_debug_verbose("%s: looped back import route (safi=%d)",
1067 uint32_t rfp_cost_to_localpref(uint8_t cost
)
1072 static void rfapiTunnelRouteAnnounce(struct bgp
*bgp
,
1073 struct rfapi_descriptor
*rfd
,
1074 uint32_t *pLifetime
)
1076 struct prefix_rd prd
;
1077 struct prefix pfx_vn
;
1079 uint32_t local_pref
= rfp_cost_to_localpref(0);
1081 rc
= rfapiRaddr2Qprefix(&(rfd
->vn_addr
), &pfx_vn
);
1085 * Construct route distinguisher = 0
1087 memset(&prd
, 0, sizeof(prd
));
1088 prd
.family
= AF_UNSPEC
;
1091 add_vnc_route(rfd
, /* rfapi descr, for export list & backref */
1092 bgp
, /* which bgp instance */
1093 SAFI_ENCAP
, /* which SAFI */
1094 &pfx_vn
, /* prefix to advertise */
1095 &prd
, /* route distinguisher to use */
1096 &rfd
->un_addr
, /* nexthop */
1098 pLifetime
, /* max lifetime of child VPN routes */
1099 NULL
, /* no rfp options for ENCAP safi */
1100 NULL
, /* rfp un options */
1101 NULL
, /* rfp vn options */
1102 rfd
->rt_export_list
, NULL
, /* med */
1103 NULL
, /* label: default */
1104 ZEBRA_ROUTE_BGP
, BGP_ROUTE_RFP
, 0);
1108 /***********************************************************************
1109 * RFP processing behavior configuration
1110 ***********************************************************************/
1112 /*------------------------------------------
1113 * rfapi_rfp_set_configuration
1115 * This is used to change rfapi's processing behavior based on
1119 * rfp_start_val value returned by rfp_start
1120 * rfapi_rfp_cfg Pointer to configuration structure
1127 * ENXIO Unabled to locate configured BGP/VNC
1128 --------------------------------------------*/
1129 int rfapi_rfp_set_configuration(void *rfp_start_val
, struct rfapi_rfp_cfg
*new)
1131 struct rfapi_rfp_cfg
*rcfg
;
1134 bgp
= rfapi_bgp_lookup_by_rfp(rfp_start_val
);
1136 if (!new || !bgp
|| !bgp
->rfapi_cfg
)
1139 rcfg
= &bgp
->rfapi_cfg
->rfp_cfg
;
1140 rcfg
->download_type
= new->download_type
;
1141 rcfg
->ftd_advertisement_interval
= new->ftd_advertisement_interval
;
1142 rcfg
->holddown_factor
= new->holddown_factor
;
1144 if (rcfg
->use_updated_response
!= new->use_updated_response
) {
1145 rcfg
->use_updated_response
= new->use_updated_response
;
1146 if (rcfg
->use_updated_response
)
1147 rfapiMonitorCallbacksOn(bgp
);
1149 rfapiMonitorCallbacksOff(bgp
);
1151 if (rcfg
->use_removes
!= new->use_removes
) {
1152 rcfg
->use_removes
= new->use_removes
;
1153 if (rcfg
->use_removes
)
1154 rfapiMonitorResponseRemovalOn(bgp
);
1156 rfapiMonitorResponseRemovalOff(bgp
);
1161 /*------------------------------------------
1162 * rfapi_rfp_set_cb_methods
1164 * Change registered callback functions for asynchronous notifications
1165 * from RFAPI to the RFP client.
1168 * rfp_start_val value returned by rfp_start
1169 * methods Pointer to struct rfapi_rfp_cb_methods containing
1170 * pointers to callback methods as described above
1174 * ENXIO BGP or VNC not configured
1175 *------------------------------------------*/
1176 int rfapi_rfp_set_cb_methods(void *rfp_start_val
,
1177 struct rfapi_rfp_cb_methods
*methods
)
1182 bgp
= rfapi_bgp_lookup_by_rfp(rfp_start_val
);
1190 h
->rfp_methods
= *methods
;
1195 /***********************************************************************
1197 ***********************************************************************/
1199 * Caller must supply an already-allocated rfd with the "caller"
1200 * fields already set (vn_addr, un_addr, callback, cookie)
1201 * The advertised_prefixes[] array elements should be NULL to
1202 * have this function set them to newly-allocated radix trees.
1204 static int rfapi_open_inner(struct rfapi_descriptor
*rfd
, struct bgp
*bgp
,
1205 struct rfapi
*h
, struct rfapi_nve_group_cfg
*rfg
)
1209 if (h
->flags
& RFAPI_INCALLBACK
)
1213 * Fill in configured fields
1217 * If group's RD is specified as "auto", then fill in based
1218 * on NVE's VN address
1222 if (rfd
->rd
.family
== AF_UNIX
) {
1223 ret
= rfapi_set_autord_from_vn(&rfd
->rd
, &rfd
->vn_addr
);
1227 rfd
->rt_export_list
= (rfg
->rt_export_list
)
1228 ? ecommunity_dup(rfg
->rt_export_list
)
1230 rfd
->response_lifetime
= rfg
->response_lifetime
;
1234 * Fill in BGP peer structure
1236 rfd
->peer
= peer_new(bgp
);
1237 rfd
->peer
->status
= Established
; /* keep bgp core happy */
1238 bgp_sync_delete(rfd
->peer
); /* don't need these */
1241 * since this peer is not on the I/O thread, this lock is not strictly
1242 * necessary, but serves as a reminder to those who may meddle...
1244 frr_with_mutex (&rfd
->peer
->io_mtx
) {
1245 // we don't need any I/O related facilities
1246 if (rfd
->peer
->ibuf
)
1247 stream_fifo_free(rfd
->peer
->ibuf
);
1248 if (rfd
->peer
->obuf
)
1249 stream_fifo_free(rfd
->peer
->obuf
);
1251 if (rfd
->peer
->ibuf_work
)
1252 ringbuf_del(rfd
->peer
->ibuf_work
);
1253 if (rfd
->peer
->obuf_work
)
1254 stream_free(rfd
->peer
->obuf_work
);
1256 rfd
->peer
->ibuf
= NULL
;
1257 rfd
->peer
->obuf
= NULL
;
1258 rfd
->peer
->obuf_work
= NULL
;
1259 rfd
->peer
->ibuf_work
= NULL
;
1262 { /* base code assumes have valid host pointer */
1263 char buf
[INET6_ADDRSTRLEN
];
1266 if (rfd
->vn_addr
.addr_family
== AF_INET
) {
1267 inet_ntop(AF_INET
, &rfd
->vn_addr
.addr
.v4
, buf
,
1269 } else if (rfd
->vn_addr
.addr_family
== AF_INET6
) {
1270 inet_ntop(AF_INET6
, &rfd
->vn_addr
.addr
.v6
, buf
,
1273 rfd
->peer
->host
= XSTRDUP(MTYPE_BGP_PEER_HOST
, buf
);
1275 /* Mark peer as belonging to HD */
1276 SET_FLAG(rfd
->peer
->flags
, PEER_FLAG_IS_RFAPI_HD
);
1279 * Set min prefix lifetime to max value so it will get set
1280 * upon first rfapi_register()
1282 rfd
->min_prefix_lifetime
= UINT32_MAX
;
1285 * Allocate response tables if needed
1287 #define RFD_RTINIT_AFI(rh, ary, afi) \
1290 ary[afi] = agg_table_init(); \
1291 agg_set_table_info(ary[afi], rh); \
1295 #define RFD_RTINIT(rh, ary) \
1297 RFD_RTINIT_AFI(rh, ary, AFI_IP); \
1298 RFD_RTINIT_AFI(rh, ary, AFI_IP6); \
1299 RFD_RTINIT_AFI(rh, ary, AFI_L2VPN); \
1302 RFD_RTINIT(rfd
, rfd
->rib
);
1303 RFD_RTINIT(rfd
, rfd
->rib_pending
);
1304 RFD_RTINIT(rfd
, rfd
->rsp_times
);
1307 * Link to Import Table
1309 rfd
->import_table
= rfg
->rfapi_import_table
;
1310 rfd
->import_table
->refcount
+= 1;
1312 rfapiApInit(&rfd
->advertised
);
1315 * add this NVE descriptor to the list of NVEs in the NVE group
1318 rfg
->nves
= list_new();
1320 listnode_add(rfg
->nves
, rfd
);
1322 vnc_direct_bgp_add_nve(bgp
, rfd
);
1323 vnc_zebra_add_nve(bgp
, rfd
);
1328 /* moved from rfapi_register */
1329 int rfapi_init_and_open(struct bgp
*bgp
, struct rfapi_descriptor
*rfd
,
1330 struct rfapi_nve_group_cfg
*rfg
)
1332 struct rfapi
*h
= bgp
->rfapi
;
1333 char buf_vn
[BUFSIZ
];
1334 char buf_un
[BUFSIZ
];
1335 afi_t afi_vn
, afi_un
;
1336 struct prefix pfx_un
;
1337 struct agg_node
*rn
;
1339 rfd
->open_time
= monotime(NULL
);
1341 if (rfg
->type
== RFAPI_GROUP_CFG_VRF
)
1342 SET_FLAG(rfd
->flags
, RFAPI_HD_FLAG_IS_VRF
);
1344 rfapiRfapiIpAddr2Str(&rfd
->vn_addr
, buf_vn
, BUFSIZ
);
1345 rfapiRfapiIpAddr2Str(&rfd
->un_addr
, buf_un
, BUFSIZ
);
1347 vnc_zlog_debug_verbose("%s: new RFD with VN=%s UN=%s cookie=%p",
1348 __func__
, buf_vn
, buf_un
, rfd
->cookie
);
1350 if (rfg
->type
!= RFAPI_GROUP_CFG_VRF
) /* unclear if needed for VRF */
1352 listnode_add(&h
->descriptors
, rfd
);
1353 if (h
->descriptors
.count
> h
->stat
.max_descriptors
) {
1354 h
->stat
.max_descriptors
= h
->descriptors
.count
;
1358 * attach to UN radix tree
1360 afi_vn
= family2afi(rfd
->vn_addr
.addr_family
);
1361 afi_un
= family2afi(rfd
->un_addr
.addr_family
);
1362 assert(afi_vn
&& afi_un
);
1363 assert(!rfapiRaddr2Qprefix(&rfd
->un_addr
, &pfx_un
));
1365 rn
= agg_node_get(h
->un
[afi_un
], &pfx_un
);
1367 rfd
->next
= rn
->info
;
1371 return rfapi_open_inner(rfd
, bgp
, h
, rfg
);
1374 struct rfapi_vn_option
*rfapiVnOptionsDup(struct rfapi_vn_option
*orig
)
1376 struct rfapi_vn_option
*head
= NULL
;
1377 struct rfapi_vn_option
*tail
= NULL
;
1378 struct rfapi_vn_option
*vo
= NULL
;
1380 for (vo
= orig
; vo
; vo
= vo
->next
) {
1381 struct rfapi_vn_option
*new;
1383 new = XCALLOC(MTYPE_RFAPI_VN_OPTION
,
1384 sizeof(struct rfapi_vn_option
));
1385 memcpy(new, vo
, sizeof(struct rfapi_vn_option
));
1397 struct rfapi_un_option
*rfapiUnOptionsDup(struct rfapi_un_option
*orig
)
1399 struct rfapi_un_option
*head
= NULL
;
1400 struct rfapi_un_option
*tail
= NULL
;
1401 struct rfapi_un_option
*uo
= NULL
;
1403 for (uo
= orig
; uo
; uo
= uo
->next
) {
1404 struct rfapi_un_option
*new;
1406 new = XCALLOC(MTYPE_RFAPI_UN_OPTION
,
1407 sizeof(struct rfapi_un_option
));
1408 memcpy(new, uo
, sizeof(struct rfapi_un_option
));
1420 struct bgp_tea_options
*rfapiOptionsDup(struct bgp_tea_options
*orig
)
1422 struct bgp_tea_options
*head
= NULL
;
1423 struct bgp_tea_options
*tail
= NULL
;
1424 struct bgp_tea_options
*hop
= NULL
;
1426 for (hop
= orig
; hop
; hop
= hop
->next
) {
1427 struct bgp_tea_options
*new;
1429 new = XCALLOC(MTYPE_BGP_TEA_OPTIONS
,
1430 sizeof(struct bgp_tea_options
));
1431 memcpy(new, hop
, sizeof(struct bgp_tea_options
));
1434 new->value
= XCALLOC(MTYPE_BGP_TEA_OPTIONS_VALUE
,
1436 memcpy(new->value
, hop
->value
, hop
->length
);
1447 void rfapiFreeBgpTeaOptionChain(struct bgp_tea_options
*p
)
1449 struct bgp_tea_options
*next
;
1454 XFREE(MTYPE_BGP_TEA_OPTIONS_VALUE
, p
->value
);
1455 XFREE(MTYPE_BGP_TEA_OPTIONS
, p
);
1461 void rfapiAdbFree(struct rfapi_adb
*adb
)
1463 XFREE(MTYPE_RFAPI_ADB
, adb
);
1467 rfapi_query_inner(void *handle
, struct rfapi_ip_addr
*target
,
1468 struct rfapi_l2address_option
*l2o
, /* may be NULL */
1469 struct rfapi_next_hop_entry
**ppNextHopEntry
)
1473 struct prefix p_original
;
1474 struct agg_node
*rn
;
1475 struct rfapi_descriptor
*rfd
= (struct rfapi_descriptor
*)handle
;
1476 struct bgp
*bgp
= rfd
->bgp
;
1477 struct rfapi_next_hop_entry
*pNHE
= NULL
;
1478 struct rfapi_ip_addr
*self_vn_addr
= NULL
;
1480 int use_eth_resolution
= 0;
1481 struct rfapi_next_hop_entry
*i_nhe
;
1485 vnc_zlog_debug_verbose("%s: No BGP instance, returning ENXIO",
1490 vnc_zlog_debug_verbose("%s: No RFAPI instance, returning ENXIO",
1494 if (bgp
->rfapi
->flags
& RFAPI_INCALLBACK
) {
1495 vnc_zlog_debug_verbose(
1496 "%s: Called during calback, returning EDEADLK",
1501 if (!is_valid_rfd(rfd
)) {
1502 vnc_zlog_debug_verbose("%s: invalid handle, returning EBADF",
1507 rfd
->rsp_counter
++; /* dedup: identify this generation */
1508 rfd
->rsp_time
= monotime(NULL
); /* response content dedup */
1509 rfd
->ftd_last_allowed_time
=
1511 bgp
->rfapi_cfg
->rfp_cfg
.ftd_advertisement_interval
;
1514 if (!memcmp(l2o
->macaddr
.octet
, rfapi_ethaddr0
.octet
,
1518 /* per t/c Paul/Lou 151022 */
1519 if (!eth_is_0
|| l2o
->logical_net_id
) {
1520 use_eth_resolution
= 1;
1525 *ppNextHopEntry
= NULL
;
1528 * Save original target in prefix form. In case of L2-based queries,
1529 * p_original will be modified to reflect the L2 target
1531 assert(!rfapiRaddr2Qprefix(target
, &p_original
));
1533 if (bgp
->rfapi_cfg
->rfp_cfg
.download_type
== RFAPI_RFP_DOWNLOAD_FULL
) {
1534 /* convert query to 0/0 when full-table download is enabled */
1535 memset((char *)&p
, 0, sizeof(p
));
1536 p
.family
= target
->addr_family
;
1544 vnc_zlog_debug_verbose("%s(rfd=%p, target=%pFX, ppNextHop=%p)",
1545 __func__
, rfd
, &p
, ppNextHopEntry
);
1547 s
= ecommunity_ecom2str(rfd
->import_table
->rt_import_list
,
1548 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1549 vnc_zlog_debug_verbose(
1550 "%s rfd->import_table=%p, rfd->import_table->rt_import_list: %s",
1551 __func__
, rfd
->import_table
, s
);
1552 XFREE(MTYPE_ECOMMUNITY_STR
, s
);
1555 afi
= family2afi(p
.family
);
1558 if (CHECK_FLAG(bgp
->rfapi_cfg
->flags
,
1559 BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP
)) {
1560 self_vn_addr
= &rfd
->vn_addr
;
1563 if (use_eth_resolution
) {
1564 uint32_t logical_net_id
= l2o
->logical_net_id
;
1565 struct ecommunity
*l2com
;
1568 * fix up p_original to contain L2 address
1570 rfapiL2o2Qprefix(l2o
, &p_original
);
1572 l2com
= bgp_rfapi_get_ecommunity_by_lni_label(
1573 bgp
, 1, logical_net_id
, l2o
->label
);
1575 uint8_t *v
= l2com
->val
;
1576 logical_net_id
= (v
[5] << 16) + (v
[6] << 8) + (v
[7]);
1579 * Ethernet/L2-based lookup
1581 * Always returns IT node corresponding to route
1584 if (RFAPI_RFP_DOWNLOAD_FULL
1585 == bgp
->rfapi_cfg
->rfp_cfg
.download_type
) {
1589 rn
= rfapiMonitorEthAdd(
1590 bgp
, rfd
, (eth_is_0
? &rfapi_ethaddr0
: &l2o
->macaddr
),
1594 struct rfapi_ip_prefix rprefix
;
1596 memset(&rprefix
, 0, sizeof(rprefix
));
1597 rprefix
.prefix
.addr_family
= target
->addr_family
;
1598 if (target
->addr_family
== AF_INET
) {
1599 rprefix
.length
= IPV4_MAX_BITLEN
;
1601 rprefix
.length
= IPV6_MAX_BITLEN
;
1604 pNHE
= rfapiEthRouteTable2NextHopList(
1605 logical_net_id
, &rprefix
,
1606 rfd
->response_lifetime
, self_vn_addr
,
1607 rfd
->rib
[afi
], &p_original
);
1617 rn
= rfapiMonitorAdd(bgp
, rfd
, &p
);
1620 * If target address is 0, this request is special: means to
1621 * return ALL routes in the table
1623 * Monitors for All-Routes queries get put on a special list,
1624 * not in the VPN tree
1626 if (RFAPI_0_PREFIX(&p
)) {
1628 vnc_zlog_debug_verbose("%s: 0-prefix", __func__
);
1631 * Generate nexthop list for caller
1633 pNHE
= rfapiRouteTable2NextHopList(
1634 rfd
->import_table
->imported_vpn
[afi
],
1635 rfd
->response_lifetime
, self_vn_addr
,
1636 rfd
->rib
[afi
], &p_original
);
1641 agg_lock_node(rn
); /* so we can unlock below */
1644 * returns locked node. Don't unlock yet because the
1646 * might free it before we're done with it. This
1648 * could occur when rfapiMonitorGetAttachNode() returns
1650 * newly-created default node.
1652 rn
= rfapiMonitorGetAttachNode(rfd
, &p
);
1658 agg_unlock_node(rn
);
1659 vnc_zlog_debug_verbose(
1660 "%s: VPN route not found, returning ENOENT", __func__
);
1664 if (VNC_DEBUG(RFAPI_QUERY
)) {
1665 rfapiShowImportTable(NULL
, "query",
1666 rfd
->import_table
->imported_vpn
[afi
], 1);
1669 if (use_eth_resolution
) {
1671 struct rfapi_ip_prefix rprefix
;
1673 memset(&rprefix
, 0, sizeof(rprefix
));
1674 rprefix
.prefix
.addr_family
= target
->addr_family
;
1675 if (target
->addr_family
== AF_INET
) {
1676 rprefix
.length
= IPV4_MAX_BITLEN
;
1678 rprefix
.length
= IPV6_MAX_BITLEN
;
1681 pNHE
= rfapiEthRouteNode2NextHopList(
1682 rn
, &rprefix
, rfd
->response_lifetime
, self_vn_addr
,
1683 rfd
->rib
[afi
], &p_original
);
1688 * Generate answer to query
1690 pNHE
= rfapiRouteNode2NextHopList(rn
, rfd
->response_lifetime
,
1691 self_vn_addr
, rfd
->rib
[afi
],
1695 agg_unlock_node(rn
);
1698 if (ppNextHopEntry
) {
1699 /* only count if caller gets it */
1700 ++bgp
->rfapi
->response_immediate_count
;
1704 vnc_zlog_debug_verbose("%s: NO NHEs, returning ENOENT",
1710 * count nexthops for statistics
1712 for (i_nhe
= pNHE
; i_nhe
; i_nhe
= i_nhe
->next
) {
1713 ++rfd
->stat_count_nh_reachable
;
1716 if (ppNextHopEntry
) {
1717 *ppNextHopEntry
= pNHE
;
1719 rfapi_free_next_hop_list(pNHE
);
1722 vnc_zlog_debug_verbose("%s: success", __func__
);
1727 * support on-the-fly reassignment of an already-open nve to a new
1728 * nve-group in the event that its original nve-group is
1729 * administratively deleted.
1731 static int rfapi_open_rfd(struct rfapi_descriptor
*rfd
, struct bgp
*bgp
)
1733 struct prefix pfx_vn
;
1734 struct prefix pfx_un
;
1735 struct rfapi_nve_group_cfg
*rfg
;
1737 struct rfapi_cfg
*hc
;
1744 hc
= bgp
->rfapi_cfg
;
1748 rc
= rfapiRaddr2Qprefix(&rfd
->vn_addr
, &pfx_vn
);
1751 rc
= rfapiRaddr2Qprefix(&rfd
->un_addr
, &pfx_un
);
1755 * Find the matching nve group config block
1757 rfg
= bgp_rfapi_cfg_match_group(hc
, &pfx_vn
, &pfx_un
);
1763 * check nve group config block for required values
1765 if (!rfg
->rt_export_list
|| !rfg
->rfapi_import_table
) {
1770 rc
= rfapi_open_inner(rfd
, bgp
, h
, rfg
);
1776 * re-advertise registered routes, this time as part of new NVE-group
1778 rfapiApReadvertiseAll(bgp
, rfd
);
1781 * re-attach callbacks to import table
1783 if (!(bgp
->rfapi_cfg
->flags
& BGP_VNC_CONFIG_CALLBACK_DISABLE
)) {
1784 rfapiMonitorAttachImportHd(rfd
);
1790 /*------------------------------------------
1793 * This function initializes a NVE record and associates it with
1794 * the specified VN and underlay network addresses
1797 * rfp_start_val value returned by rfp_start
1798 * vn NVE virtual network address
1800 * un NVE underlay network address
1802 * default_options Default options to use on registrations.
1803 * For now only tunnel type is supported.
1804 * May be overridden per-prefix in rfapi_register().
1805 * Caller owns (rfapi_open() does not free)
1807 * response_cb Pointer to next hop list update callback function or
1808 * NULL when no callbacks are desired.
1810 * userdata Passed to subsequent response_cb invocations.
1813 * response_lifetime The length of time that responses sent to this
1816 * pHandle pointer to location to store rfapi handle. The
1817 * handle must be passed on subsequent rfapi_ calls.
1822 * EEXIST NVE with this {vn,un} already open
1823 * ENOENT No matching nve group config
1824 * ENOMSG Matched nve group config was incomplete
1825 * ENXIO BGP or VNC not configured
1826 * EAFNOSUPPORT Matched nve group specifies auto-assignment of RD,
1827 * but underlay network address is not IPv4
1828 * EDEADLK Called from within a callback procedure
1829 *------------------------------------------*/
1830 int rfapi_open(void *rfp_start_val
, struct rfapi_ip_addr
*vn
,
1831 struct rfapi_ip_addr
*un
,
1832 struct rfapi_un_option
*default_options
,
1833 uint32_t *response_lifetime
,
1834 void *userdata
, /* callback cookie */
1835 rfapi_handle
*pHandle
)
1839 struct rfapi_descriptor
*rfd
;
1840 struct rfapi_cfg
*hc
;
1841 struct rfapi_nve_group_cfg
*rfg
;
1843 struct prefix pfx_vn
;
1844 struct prefix pfx_un
;
1847 rfapi_handle hh
= NULL
;
1848 int reusing_provisional
= 0;
1851 char buf
[2][INET_ADDRSTRLEN
];
1852 vnc_zlog_debug_verbose(
1853 "%s: VN=%s UN=%s", __func__
,
1854 rfapiRfapiIpAddr2Str(vn
, buf
[0], INET_ADDRSTRLEN
),
1855 rfapiRfapiIpAddr2Str(un
, buf
[1], INET_ADDRSTRLEN
));
1861 bgp
= rfapi_bgp_lookup_by_rfp(rfp_start_val
);
1869 hc
= bgp
->rfapi_cfg
;
1873 if (h
->flags
& RFAPI_INCALLBACK
)
1876 rc
= rfapiRaddr2Qprefix(vn
, &pfx_vn
);
1879 rc
= rfapiRaddr2Qprefix(un
, &pfx_un
);
1883 * already have a descriptor with VN and UN?
1885 if (!rfapi_find_handle(bgp
, vn
, un
, &hh
)) {
1887 * we might have set up a handle for static routes before
1888 * this NVE was opened. In that case, reuse the handle
1891 if (!CHECK_FLAG(rfd
->flags
, RFAPI_HD_FLAG_PROVISIONAL
)) {
1896 * reuse provisional descriptor
1899 reusing_provisional
= 1;
1903 * Find the matching nve group config block
1905 rfg
= bgp_rfapi_cfg_match_group(hc
, &pfx_vn
, &pfx_un
);
1907 ++h
->stat
.count_unknown_nves
;
1909 char buf
[2][INET_ADDRSTRLEN
];
1910 zlog_notice("%s: no matching group VN=%s UN=%s",
1912 rfapiRfapiIpAddr2Str(vn
, buf
[0],
1914 rfapiRfapiIpAddr2Str(un
, buf
[1],
1921 * check nve group config block for required values
1923 if (!rfg
->rt_export_list
|| !rfg
->rfapi_import_table
) {
1925 ++h
->stat
.count_unknown_nves
;
1930 * If group config specifies auto-rd assignment, check that
1931 * VN address is IPv4|v6 so we don't fail in rfapi_open_inner().
1932 * Check here so we don't need to unwind memory allocations, &c.
1934 if ((rfg
->rd
.family
== AF_UNIX
) && (vn
->addr_family
!= AF_INET
)
1935 && (vn
->addr_family
!= AF_INET6
)) {
1936 return EAFNOSUPPORT
;
1941 * reusing provisional rfd
1945 rfd
= XCALLOC(MTYPE_RFAPI_DESC
,
1946 sizeof(struct rfapi_descriptor
));
1950 if (default_options
) {
1951 struct rfapi_un_option
*p
;
1953 for (p
= default_options
; p
; p
= p
->next
) {
1954 if ((RFAPI_UN_OPTION_TYPE_PROVISIONAL
== p
->type
)) {
1955 rfd
->flags
|= RFAPI_HD_FLAG_PROVISIONAL
;
1957 if ((RFAPI_UN_OPTION_TYPE_TUNNELTYPE
== p
->type
)) {
1958 rfd
->default_tunneltype_option
= p
->v
.tunnel
;
1964 * Fill in caller fields
1968 rfd
->cookie
= userdata
;
1970 if (!reusing_provisional
) {
1971 rc
= rfapi_init_and_open(bgp
, rfd
, rfg
);
1973 * This can fail only if the VN address is IPv6 and the group
1974 * specified auto-assignment of RDs, which only works for v4,
1975 * and the check above should catch it.
1977 * Another failure possibility is that we were called
1978 * during an rfapi callback. Also checked above.
1983 if (response_lifetime
)
1984 *response_lifetime
= rfd
->response_lifetime
;
1990 * For use with debug functions
1992 static int rfapi_set_response_cb(struct rfapi_descriptor
*rfd
,
1993 rfapi_response_cb_t
*response_cb
)
1995 if (!is_valid_rfd(rfd
))
1997 rfd
->response_cb
= response_cb
;
2004 * Does almost all the work of rfapi_close, except:
2005 * 1. preserves the descriptor (doesn't free it)
2006 * 2. preserves the prefix query list (i.e., rfd->mon list)
2007 * 3. preserves the advertised prefix list (rfd->advertised)
2008 * 4. preserves the rib and rib_pending tables
2010 * The purpose of organizing it this way is to support on-the-fly
2011 * reassignment of an already-open nve to a new nve-group in the
2012 * event that its original nve-group is administratively deleted.
2014 static int rfapi_close_inner(struct rfapi_descriptor
*rfd
, struct bgp
*bgp
)
2017 struct prefix pfx_vn
;
2018 struct prefix_rd prd
; /* currently always 0 for VN->UN */
2020 if (!is_valid_rfd(rfd
))
2023 rc
= rfapiRaddr2Qprefix(&rfd
->vn_addr
, &pfx_vn
);
2024 assert(!rc
); /* should never have bad AF in stored vn address */
2027 * update exported routes to reflect disappearance of this NVE as
2030 vnc_direct_bgp_del_nve(bgp
, rfd
);
2031 vnc_zebra_del_nve(bgp
, rfd
);
2034 * unlink this HD's monitors from import table
2036 rfapiMonitorDetachImportHd(rfd
);
2039 * Unlink from Import Table
2040 * NB rfd->import_table will be NULL if we are closing a stale
2043 if (rfd
->import_table
)
2044 rfapiImportTableRefDelByIt(bgp
, rfd
->import_table
);
2045 rfd
->import_table
= NULL
;
2048 * Construct route distinguisher
2050 memset(&prd
, 0, sizeof(prd
));
2052 prd
.family
= AF_UNSPEC
;
2058 del_vnc_route(rfd
, rfd
->peer
, bgp
, SAFI_ENCAP
,
2059 &pfx_vn
, /* prefix being advertised */
2060 &prd
, /* route distinguisher to use (0 for ENCAP) */
2061 ZEBRA_ROUTE_BGP
, BGP_ROUTE_RFP
, NULL
, 0); /* no kill */
2064 * Construct route distinguisher for VPN routes
2067 prd
.family
= AF_UNSPEC
;
2071 * find all VPN routes associated with this rfd and delete them, too
2073 rfapiApWithdrawAll(bgp
, rfd
);
2076 * remove this nve descriptor from the list of nves
2077 * associated with the nve group
2080 listnode_delete(rfd
->rfg
->nves
, rfd
);
2081 rfd
->rfg
= NULL
; /* XXX mark as orphaned/stale */
2084 if (rfd
->rt_export_list
)
2085 ecommunity_free(&rfd
->rt_export_list
);
2086 rfd
->rt_export_list
= NULL
;
2089 * free peer structure (possibly delayed until its
2090 * refcount reaches zero)
2093 vnc_zlog_debug_verbose("%s: calling peer_delete(%p), #%d",
2094 __func__
, rfd
->peer
, rfd
->peer
->lock
);
2095 peer_delete(rfd
->peer
);
2102 int rfapi_close(void *handle
)
2104 struct rfapi_descriptor
*rfd
= (struct rfapi_descriptor
*)handle
;
2106 struct agg_node
*node
;
2110 vnc_zlog_debug_verbose("%s: rfd=%p", __func__
, rfd
);
2112 #ifdef RFAPI_WHO_IS_CALLING_ME
2113 #ifdef HAVE_GLIBC_BACKTRACE
2114 #define RFAPI_DEBUG_BACKTRACE_NENTRIES 5
2116 void *buf
[RFAPI_DEBUG_BACKTRACE_NENTRIES
];
2121 size
= backtrace(buf
, RFAPI_DEBUG_BACKTRACE_NENTRIES
);
2122 syms
= backtrace_symbols(buf
, size
);
2123 for (i
= 0; i
< size
&& i
< RFAPI_DEBUG_BACKTRACE_NENTRIES
;
2125 vnc_zlog_debug_verbose("backtrace[%2d]: %s", i
,
2141 if (!is_valid_rfd(rfd
))
2144 if (h
->flags
& RFAPI_INCALLBACK
) {
2146 * Queue these close requests for processing after callback
2149 if (!CHECK_FLAG(rfd
->flags
,
2150 RFAPI_HD_FLAG_CLOSING_ADMINISTRATIVELY
)) {
2151 work_queue_add(h
->deferred_close_q
, handle
);
2152 vnc_zlog_debug_verbose(
2153 "%s: added handle %p to deferred close queue",
2159 if (CHECK_FLAG(rfd
->flags
, RFAPI_HD_FLAG_CLOSING_ADMINISTRATIVELY
)) {
2161 vnc_zlog_debug_verbose("%s administrative close rfd=%p",
2164 if (h
->rfp_methods
.close_cb
) {
2165 vnc_zlog_debug_verbose(
2166 "%s calling close callback rfd=%p", __func__
,
2170 * call the callback fairly early so that it can still
2174 * NB RFAPI_INCALLBACK is tested above, so if we reach
2176 * we are not already in the context of a callback.
2178 h
->flags
|= RFAPI_INCALLBACK
;
2179 (*h
->rfp_methods
.close_cb
)(handle
, EIDRM
);
2180 h
->flags
&= ~RFAPI_INCALLBACK
;
2186 * Orphaned descriptors have already done this part, so do
2187 * only for non-orphaned descriptors.
2189 if ((rc
= rfapi_close_inner(rfd
, bgp
)))
2194 * Remove descriptor from UN index
2195 * (remove from chain at node)
2197 rc
= rfapi_find_node(bgp
, &rfd
->vn_addr
, &rfd
->un_addr
, &node
);
2199 struct rfapi_descriptor
*hh
;
2201 if (node
->info
== rfd
) {
2202 node
->info
= rfd
->next
;
2205 for (hh
= node
->info
; hh
; hh
= hh
->next
) {
2206 if (hh
->next
== rfd
) {
2207 hh
->next
= rfd
->next
;
2212 agg_unlock_node(node
);
2216 * remove from descriptor list
2218 listnode_delete(&h
->descriptors
, rfd
);
2221 * Delete monitor list items and free monitor structures
2223 (void)rfapiMonitorDelHd(rfd
);
2226 * release advertised prefix data
2228 rfapiApRelease(&rfd
->advertised
);
2231 * Release RFP callback RIB
2238 memset(rfd
, 0, sizeof(struct rfapi_descriptor
));
2239 XFREE(MTYPE_RFAPI_DESC
, rfd
);
2245 * Reopen a nve descriptor. If the descriptor's NVE-group
2246 * does not exist (e.g., if it has been administratively removed),
2247 * reassignment to a new NVE-group is attempted.
2249 * If NVE-group reassignment fails, the descriptor becomes "stale"
2250 * (rfd->rfg == NULL implies "stale:). The only permissible API operation
2251 * on a stale descriptor is rfapi_close(). Any other rfapi_* API operation
2252 * on the descriptor will return ESTALE.
2254 * Reopening a descriptor is a potentially expensive operation, because
2255 * it involves withdrawing any routes advertised by the NVE, withdrawing
2256 * the NVE's route queries, and then re-adding them all after a new
2257 * NVE-group is assigned. There are also possible route-export affects
2258 * caused by deleting and then adding the NVE: advertised prefixes
2259 * and nexthop lists for exported routes can turn over.
2261 int rfapi_reopen(struct rfapi_descriptor
*rfd
, struct bgp
*bgp
)
2266 if ((rc
= rfapi_close_inner(rfd
, bgp
))) {
2269 if ((rc
= rfapi_open_rfd(rfd
, bgp
))) {
2273 assert(h
!= NULL
&& !CHECK_FLAG(h
->flags
, RFAPI_INCALLBACK
));
2275 if (CHECK_FLAG(rfd
->flags
,
2276 RFAPI_HD_FLAG_CLOSING_ADMINISTRATIVELY
)
2277 && h
&& h
->rfp_methods
.close_cb
) {
2280 * NB RFAPI_INCALLBACK is tested above, so if we reach
2282 * we are not already in the context of a callback.
2284 h
->flags
|= RFAPI_INCALLBACK
;
2285 (*h
->rfp_methods
.close_cb
)((rfapi_handle
)rfd
, ESTALE
);
2286 h
->flags
&= ~RFAPI_INCALLBACK
;
2293 /***********************************************************************
2295 ***********************************************************************/
2297 * Announce reachability to this prefix via the NVE
2299 int rfapi_register(void *handle
, struct rfapi_ip_prefix
*prefix
,
2300 uint32_t lifetime
, /* host byte order */
2301 struct rfapi_un_option
*options_un
,
2302 struct rfapi_vn_option
*options_vn
,
2303 rfapi_register_action action
)
2305 struct rfapi_descriptor
*rfd
= (struct rfapi_descriptor
*)handle
;
2308 struct prefix
*pfx_ip
= NULL
;
2309 struct prefix_rd prd
;
2311 struct prefix pfx_mac_buf
;
2312 struct prefix
*pfx_mac
= NULL
;
2313 struct prefix pfx_vn_buf
;
2314 const char *action_str
= NULL
;
2315 uint32_t *label
= NULL
;
2316 struct rfapi_vn_option
*vo
;
2317 struct rfapi_l2address_option
*l2o
= NULL
;
2318 struct prefix_rd
*prd_override
= NULL
;
2321 case RFAPI_REGISTER_ADD
:
2324 case RFAPI_REGISTER_WITHDRAW
:
2325 action_str
= "withdraw";
2327 case RFAPI_REGISTER_KILL
:
2328 action_str
= "kill";
2336 * Inspect VN options
2338 for (vo
= options_vn
; vo
; vo
= vo
->next
) {
2339 if (RFAPI_VN_OPTION_TYPE_L2ADDR
== vo
->type
) {
2340 l2o
= &vo
->v
.l2addr
;
2342 if (RFAPI_VN_OPTION_TYPE_INTERNAL_RD
== vo
->type
) {
2343 prd_override
= &vo
->v
.internal_rd
;
2347 /*********************************************************************
2349 *********************************************************************/
2352 * set <p> based on <prefix>
2354 assert(!rfapiRprefix2Qprefix(prefix
, &p
));
2356 afi
= family2afi(prefix
->prefix
.addr_family
);
2359 vnc_zlog_debug_verbose(
2360 "%s(rfd=%p, pfx=%pFX, lifetime=%d, opts_un=%p, opts_vn=%p, action=%s)",
2361 __func__
, rfd
, &p
, lifetime
, options_un
, options_vn
,
2365 * These tests come after the prefix conversion so that we can
2366 * print the prefix in a debug message before failing
2371 vnc_zlog_debug_verbose("%s: no BGP instance: returning ENXIO",
2376 vnc_zlog_debug_verbose("%s: no RFAPI instance: returning ENXIO",
2381 if (RFAPI_REGISTER_ADD
== action
) {
2382 ++bgp
->rfapi
->stat
.count_registrations_failed
;
2384 vnc_zlog_debug_verbose(
2385 "%s: rfd=%p, no RF GRP instance: returning ESTALE",
2390 if (bgp
->rfapi
->flags
& RFAPI_INCALLBACK
) {
2391 if (RFAPI_REGISTER_ADD
== action
) {
2392 ++bgp
->rfapi
->stat
.count_registrations_failed
;
2394 vnc_zlog_debug_verbose("%s: in callback: returning EDEADLK",
2399 if (!is_valid_rfd(rfd
)) {
2400 if (RFAPI_REGISTER_ADD
== action
) {
2401 ++bgp
->rfapi
->stat
.count_registrations_failed
;
2403 vnc_zlog_debug_verbose("%s: invalid handle: returning EBADF",
2409 * Is there a MAC address in this registration?
2411 if (l2o
&& !RFAPI_0_ETHERADDR(&l2o
->macaddr
)) {
2412 rfapiL2o2Qprefix(l2o
, &pfx_mac_buf
);
2413 pfx_mac
= &pfx_mac_buf
;
2417 * Is there an IP prefix in this registration?
2419 if (!(RFAPI_0_PREFIX(&p
) && RFAPI_HOST_PREFIX(&p
))) {
2423 vnc_zlog_debug_verbose(
2424 "%s: missing mac addr that is required for host 0 pfx",
2426 if (RFAPI_REGISTER_ADD
== action
) {
2427 ++bgp
->rfapi
->stat
.count_registrations_failed
;
2431 if (rfapiRaddr2Qprefix(&rfd
->vn_addr
, &pfx_vn_buf
)) {
2432 vnc_zlog_debug_verbose(
2433 "%s: handle has bad vn_addr: returning EBADF",
2435 if (RFAPI_REGISTER_ADD
== action
) {
2436 ++bgp
->rfapi
->stat
.count_registrations_failed
;
2442 if (RFAPI_REGISTER_ADD
== action
) {
2443 ++bgp
->rfapi
->stat
.count_registrations
;
2447 * Figure out if this registration is missing an IP address
2451 * In RFAPI, we use prefixes in family AF_LINK to store
2452 * the MAC addresses. These prefixes are used for the
2453 * list of advertised prefixes and in the RFAPI import
2456 * In BGP proper, we use the prefix matching the NVE's
2457 * VN address with a host prefix-length (i.e., 32 or 128).
2460 if (l2o
&& l2o
->logical_net_id
&& RFAPI_0_PREFIX(&p
)
2461 && RFAPI_HOST_PREFIX(&p
)) {
2463 rfapiL2o2Qprefix(l2o
, &pfx_mac_buf
);
2464 pfx_mac
= &pfx_mac_buf
;
2468 * Construct route distinguisher
2471 prd
= *prd_override
;
2473 memset(&prd
, 0, sizeof(prd
));
2475 prd
.family
= AF_UNSPEC
;
2477 encode_rd_type(RD_TYPE_VNC_ETH
, prd
.val
);
2478 if (l2o
->local_nve_id
2479 || !(rfd
->rfg
->flags
& RFAPI_RFG_L2RD
)) {
2481 * If Local NVE ID is specified in message, use
2483 * (if no local default configured, also use it
2486 prd
.val
[1] = l2o
->local_nve_id
;
2488 if (rfd
->rfg
->l2rd
) {
2490 * locally-configured literal value
2492 prd
.val
[1] = rfd
->rfg
->l2rd
;
2495 * 0 means auto:vn, which means use LSB
2498 if (rfd
->vn_addr
.addr_family
2501 *(((char *)&rfd
->vn_addr
2507 *(((char *)&rfd
->vn_addr
2514 memcpy(prd
.val
+ 2, pfx_mac
->u
.prefix_eth
.octet
, 6);
2517 prd
.family
= AF_UNSPEC
;
2523 if (action
== RFAPI_REGISTER_WITHDRAW
2524 || action
== RFAPI_REGISTER_KILL
) {
2529 * withdraw previous advertisement
2532 rfd
, rfd
->peer
, bgp
, SAFI_MPLS_VPN
,
2534 : &pfx_vn_buf
, /* prefix being advertised */
2535 &prd
, /* route distinguisher (0 for ENCAP) */
2536 ZEBRA_ROUTE_BGP
, BGP_ROUTE_RFP
, NULL
,
2537 action
== RFAPI_REGISTER_KILL
);
2539 if (0 == rfapiApDelete(bgp
, rfd
, &p
, pfx_mac
, &prd
,
2542 rfapiTunnelRouteAnnounce(
2543 bgp
, rfd
, &rfd
->max_prefix_lifetime
);
2549 uint32_t local_pref
;
2550 struct ecommunity
*rtlist
= NULL
;
2551 struct ecommunity_val ecom_value
;
2553 if (!rfapiApCount(rfd
)) {
2555 * make sure we advertise tunnel route upon adding the
2561 if (rfapiApAdd(bgp
, rfd
, &p
, pfx_mac
, &prd
, lifetime
,
2562 prefix
->cost
, l2o
)) {
2566 vnc_zlog_debug_verbose("%s: adv_tunnel = %d", __func__
,
2569 vnc_zlog_debug_verbose("%s: announcing tunnel route",
2571 rfapiTunnelRouteAnnounce(bgp
, rfd
,
2572 &rfd
->max_prefix_lifetime
);
2575 vnc_zlog_debug_verbose("%s: calling add_vnc_route", __func__
);
2577 local_pref
= rfp_cost_to_localpref(prefix
->cost
);
2579 if (l2o
&& l2o
->label
)
2580 label
= &l2o
->label
;
2583 struct ecommunity
*l2com
= NULL
;
2586 l2com
= bgp_rfapi_get_ecommunity_by_lni_label(
2587 bgp
, 1, l2o
->logical_net_id
, *label
);
2590 rtlist
= ecommunity_dup(l2com
);
2593 * If mac address is set, add an RT based on the
2596 memset((char *)&ecom_value
, 0,
2597 sizeof(ecom_value
));
2598 ecom_value
.val
[1] = ECOMMUNITY_ROUTE_TARGET
;
2600 (l2o
->logical_net_id
>> 16) & 0xff;
2602 (l2o
->logical_net_id
>> 8) & 0xff;
2604 (l2o
->logical_net_id
>> 0) & 0xff;
2605 rtlist
= ecommunity_new();
2606 ecommunity_add_val(rtlist
, &ecom_value
,
2611 uint16_t val
= l2o
->tag_id
;
2612 memset((char *)&ecom_value
, 0,
2613 sizeof(ecom_value
));
2614 ecom_value
.val
[1] = ECOMMUNITY_ROUTE_TARGET
;
2615 if (as
> BGP_AS_MAX
) {
2617 ECOMMUNITY_ENCODE_AS4
;
2618 ecom_value
.val
[2] = (as
>> 24) & 0xff;
2619 ecom_value
.val
[3] = (as
>> 16) & 0xff;
2620 ecom_value
.val
[4] = (as
>> 8) & 0xff;
2621 ecom_value
.val
[5] = as
& 0xff;
2624 ECOMMUNITY_ENCODE_AS
;
2625 ecom_value
.val
[2] = (as
>> 8) & 0xff;
2626 ecom_value
.val
[3] = as
& 0xff;
2628 ecom_value
.val
[6] = (val
>> 8) & 0xff;
2629 ecom_value
.val
[7] = val
& 0xff;
2631 rtlist
= ecommunity_new();
2632 ecommunity_add_val(rtlist
, &ecom_value
,
2638 * advertise prefix via tunnel endpoint
2641 rfd
, /* rfapi descr, for export list & backref */
2642 bgp
, /* which bgp instance */
2643 SAFI_MPLS_VPN
, /* which SAFI */
2645 : &pfx_vn_buf
), /* prefix being advertised */
2646 &prd
, /* route distinguisher to use (0 for ENCAP) */
2647 &rfd
->vn_addr
, /* nexthop */
2649 &lifetime
, /* prefix lifetime -> Tunnel Encap attr */
2650 NULL
, options_un
, /* rfapi un options */
2651 options_vn
, /* rfapi vn options */
2652 (rtlist
? rtlist
: rfd
->rt_export_list
), NULL
, /* med */
2653 label
, /* label: default */
2654 ZEBRA_ROUTE_BGP
, BGP_ROUTE_RFP
, 0);
2657 ecommunity_free(&rtlist
); /* sets rtlist = NULL */
2660 vnc_zlog_debug_verbose("%s: success", __func__
);
2664 int rfapi_query(void *handle
, struct rfapi_ip_addr
*target
,
2665 struct rfapi_l2address_option
*l2o
, /* may be NULL */
2666 struct rfapi_next_hop_entry
**ppNextHopEntry
)
2668 struct rfapi_descriptor
*rfd
= (struct rfapi_descriptor
*)handle
;
2669 struct bgp
*bgp
= rfd
->bgp
;
2672 assert(ppNextHopEntry
);
2673 *ppNextHopEntry
= NULL
;
2675 if (bgp
&& bgp
->rfapi
) {
2676 bgp
->rfapi
->stat
.count_queries
++;
2680 if (bgp
&& bgp
->rfapi
)
2681 ++bgp
->rfapi
->stat
.count_queries_failed
;
2685 if ((rc
= rfapi_query_inner(handle
, target
, l2o
, ppNextHopEntry
))) {
2686 if (bgp
&& bgp
->rfapi
)
2687 ++bgp
->rfapi
->stat
.count_queries_failed
;
2692 int rfapi_query_done(rfapi_handle handle
, struct rfapi_ip_addr
*target
)
2696 struct rfapi_descriptor
*rfd
= (struct rfapi_descriptor
*)handle
;
2697 struct bgp
*bgp
= rfd
->bgp
;
2703 rc
= rfapiRaddr2Qprefix(target
, &p
);
2706 if (!is_valid_rfd(rfd
))
2710 if (!bgp
|| !bgp
->rfapi
)
2713 if (bgp
->rfapi
->flags
& RFAPI_INCALLBACK
)
2716 rfapiMonitorDel(bgp
, rfd
, &p
);
2721 int rfapi_query_done_all(rfapi_handle handle
, int *count
)
2723 struct rfapi_descriptor
*rfd
= (struct rfapi_descriptor
*)handle
;
2724 struct bgp
*bgp
= rfd
->bgp
;
2731 if (!is_valid_rfd(rfd
))
2735 if (!bgp
|| !bgp
->rfapi
)
2738 if (bgp
->rfapi
->flags
& RFAPI_INCALLBACK
)
2741 num
= rfapiMonitorDelHd(rfd
);
2749 void rfapi_free_next_hop_list(struct rfapi_next_hop_entry
*list
)
2751 struct rfapi_next_hop_entry
*nh
;
2752 struct rfapi_next_hop_entry
*next
;
2754 for (nh
= list
; nh
; nh
= next
) {
2756 rfapi_un_options_free(nh
->un_options
);
2757 nh
->un_options
= NULL
;
2758 rfapi_vn_options_free(nh
->vn_options
);
2759 nh
->vn_options
= NULL
;
2760 XFREE(MTYPE_RFAPI_NEXTHOP
, nh
);
2765 * NULL handle => return total count across all nves
2767 uint32_t rfapi_monitor_count(void *handle
)
2769 struct bgp
*bgp
= bgp_get_default();
2773 struct rfapi_descriptor
*rfd
=
2774 (struct rfapi_descriptor
*)handle
;
2775 count
= rfd
->monitor_count
;
2778 if (!bgp
|| !bgp
->rfapi
)
2781 count
= bgp
->rfapi
->monitor_count
;
2787 /***********************************************************************
2789 ***********************************************************************/
2791 DEFUN (debug_rfapi_show_nves
,
2792 debug_rfapi_show_nves_cmd
,
2793 "debug rfapi-dev show nves",
2797 "NVE Information\n")
2799 rfapiPrintMatchingDescriptors(vty
, NULL
, NULL
);
2804 debug_rfapi_show_nves_vn_un
,
2805 debug_rfapi_show_nves_vn_un_cmd
,
2806 "debug rfapi-dev show nves <vn|un> <A.B.C.D|X:X::X:X>", /* prefix also ok */
2811 "Specify virtual network\n"
2812 "Specify underlay network interface\n"
2818 if (!str2prefix(argv
[5]->arg
, &pfx
)) {
2819 vty_out(vty
, "Malformed address \"%s\"\n", argv
[5]->arg
);
2820 return CMD_WARNING_CONFIG_FAILED
;
2822 if (pfx
.family
!= AF_INET
&& pfx
.family
!= AF_INET6
) {
2823 vty_out(vty
, "Invalid address \"%s\"\n", argv
[5]->arg
);
2824 return CMD_WARNING_CONFIG_FAILED
;
2827 if (argv
[4]->arg
[0] == 'u') {
2828 rfapiPrintMatchingDescriptors(vty
, NULL
, &pfx
);
2830 rfapiPrintMatchingDescriptors(vty
, &pfx
, NULL
);
2836 * Note: this function does not flush vty output, so if it is called
2837 * with a stream pointing to a vty, the user will have to type something
2838 * before the callback output shows up
2840 static void test_nexthops_callback(
2841 // struct rfapi_ip_addr *target,
2842 struct rfapi_next_hop_entry
*next_hops
, void *userdata
)
2844 void *stream
= userdata
;
2846 int (*fp
)(void *, const char *, ...);
2849 const char *vty_newline
;
2851 if (rfapiStream2Vty(stream
, &fp
, &vty
, &out
, &vty_newline
) == 0)
2854 fp(out
, "Nexthops Callback, Target=(");
2855 // rfapiPrintRfapiIpAddr(stream, target);
2858 rfapiPrintNhl(stream
, next_hops
);
2862 rfapi_free_next_hop_list(next_hops
);
2865 DEFUN (debug_rfapi_open
,
2866 debug_rfapi_open_cmd
,
2867 "debug rfapi-dev open vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X>",
2871 "indicate vn addr follows\n"
2872 "virtual network interface IPv4 address\n"
2873 "virtual network interface IPv6 address\n"
2874 "indicate xt addr follows\n"
2875 "underlay network interface IPv4 address\n"
2876 "underlay network interface IPv6 address\n")
2878 struct rfapi_ip_addr vn
;
2879 struct rfapi_ip_addr un
;
2880 uint32_t lifetime
= 0;
2882 rfapi_handle handle
;
2887 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[4]->arg
, &vn
)))
2893 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[6]->arg
, &un
)))
2896 rc
= rfapi_open(rfapi_get_rfp_start_val_by_bgp(bgp_get_default()), &vn
,
2897 &un
, /*&uo */ NULL
, &lifetime
, NULL
, &handle
);
2899 vty_out(vty
, "rfapi_open: status %d, handle %p, lifetime %d\n", rc
,
2902 rc
= rfapi_set_response_cb(handle
, test_nexthops_callback
);
2904 vty_out(vty
, "rfapi_set_response_cb: status %d\n", rc
);
2910 DEFUN (debug_rfapi_close_vn_un
,
2911 debug_rfapi_close_vn_un_cmd
,
2912 "debug rfapi-dev close vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X>",
2916 "indicate vn addr follows\n"
2917 "virtual network interface IPv4 address\n"
2918 "virtual network interface IPv6 address\n"
2919 "indicate xt addr follows\n"
2920 "underlay network interface IPv4 address\n"
2921 "underlay network interface IPv6 address\n")
2923 struct rfapi_ip_addr vn
;
2924 struct rfapi_ip_addr un
;
2925 rfapi_handle handle
;
2931 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[4]->arg
, &vn
)))
2938 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[6]->arg
, &un
)))
2942 if (rfapi_find_handle_vty(vty
, &vn
, &un
, &handle
)) {
2943 vty_out(vty
, "can't locate handle matching vn=%s, un=%s\n",
2944 argv
[4]->arg
, argv
[6]->arg
);
2945 return CMD_WARNING_CONFIG_FAILED
;
2948 rc
= rfapi_close(handle
);
2950 vty_out(vty
, "rfapi_close(handle=%p): status %d\n", handle
, rc
);
2955 DEFUN (debug_rfapi_close_rfd
,
2956 debug_rfapi_close_rfd_cmd
,
2957 "debug rfapi-dev close rfd HANDLE",
2961 "indicate handle follows\n" "rfapi handle in hexadecimal\n")
2963 rfapi_handle handle
;
2965 char *endptr
= NULL
;
2967 handle
= (rfapi_handle
)(uintptr_t)(strtoull(argv
[4]->arg
, &endptr
, 16));
2969 if (*endptr
!= '\0' || (uintptr_t)handle
== UINTPTR_MAX
) {
2970 vty_out(vty
, "Invalid value: %s\n", argv
[4]->arg
);
2971 return CMD_WARNING_CONFIG_FAILED
;
2974 rc
= rfapi_close(handle
);
2976 vty_out(vty
, "rfapi_close(handle=%p): status %d\n", handle
, rc
);
2981 DEFUN (debug_rfapi_register_vn_un
,
2982 debug_rfapi_register_vn_un_cmd
,
2983 "debug rfapi-dev register vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> prefix <A.B.C.D/M|X:X::X:X/M> lifetime SECONDS [cost (0-255)]",
2987 "indicate vn addr follows\n"
2988 "virtual network IPv4 interface address\n"
2989 "virtual network IPv6 interface address\n"
2990 "indicate un addr follows\n"
2991 "underlay network IPv4 interface address\n"
2992 "underlay network IPv6 interface address\n"
2993 "indicate prefix follows\n"
2996 "indicate lifetime follows\n"
2998 "Cost (localpref = 255-cost)\n"
3001 struct rfapi_ip_addr vn
;
3002 struct rfapi_ip_addr un
;
3003 rfapi_handle handle
;
3006 struct rfapi_ip_prefix hpfx
;
3013 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[4]->arg
, &vn
)))
3020 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[6]->arg
, &un
)))
3024 if (rfapi_find_handle_vty(vty
, &vn
, &un
, &handle
)) {
3025 vty_out(vty
, "can't locate handle matching vn=%s, un=%s\n",
3026 argv
[4]->arg
, argv
[6]->arg
);
3027 return CMD_WARNING_CONFIG_FAILED
;
3031 * Get prefix to advertise
3033 if (!str2prefix(argv
[8]->arg
, &pfx
)) {
3034 vty_out(vty
, "Malformed prefix \"%s\"\n", argv
[8]->arg
);
3035 return CMD_WARNING_CONFIG_FAILED
;
3037 if (pfx
.family
!= AF_INET
&& pfx
.family
!= AF_INET6
) {
3038 vty_out(vty
, "Bad family for prefix \"%s\"\n", argv
[8]->arg
);
3039 return CMD_WARNING_CONFIG_FAILED
;
3041 rfapiQprefix2Rprefix(&pfx
, &hpfx
);
3043 if (strmatch(argv
[10]->text
, "infinite")) {
3044 lifetime
= RFAPI_INFINITE_LIFETIME
;
3046 lifetime
= strtoul(argv
[10]->arg
, NULL
, 10);
3050 cost
= (uint8_t) strtoul(argv
[12]->arg
, NULL
, 10);
3053 rc
= rfapi_register(handle
, &hpfx
, lifetime
, NULL
, NULL
,
3054 RFAPI_REGISTER_ADD
);
3056 vty_out(vty
, "rfapi_register failed with rc=%d (%s)\n", rc
,
3063 DEFUN (debug_rfapi_register_vn_un_l2o
,
3064 debug_rfapi_register_vn_un_l2o_cmd
,
3065 "debug rfapi-dev register vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> prefix <A.B.C.D/M|X:X::X:X/M> lifetime SECONDS macaddr X:X:X:X:X:X lni (0-16777215)",
3069 "indicate vn addr follows\n"
3070 "virtual network IPv4 interface address\n"
3071 "virtual network IPv6 interface address\n"
3072 "indicate un addr follows\n"
3073 "underlay network IPv4 interface address\n"
3074 "underlay network IPv6 interface address\n"
3075 "indicate prefix follows\n"
3078 "indicate lifetime follows\n"
3079 "Seconds of lifetime\n"
3080 "indicate MAC address follows\n"
3082 "indicate lni follows\n"
3083 "lni value range\n")
3085 struct rfapi_ip_addr vn
;
3086 struct rfapi_ip_addr un
;
3087 rfapi_handle handle
;
3090 struct rfapi_ip_prefix hpfx
;
3092 struct rfapi_vn_option optary
[10]; /* XXX must be big enough */
3093 struct rfapi_vn_option
*opt
= NULL
;
3099 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[4]->arg
, &vn
)))
3106 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[6]->arg
, &un
)))
3110 if (rfapi_find_handle_vty(vty
, &vn
, &un
, &handle
)) {
3111 vty_out(vty
, "can't locate handle matching vn=%s, un=%s\n",
3112 argv
[4]->arg
, argv
[6]->arg
);
3113 return CMD_WARNING_CONFIG_FAILED
;
3117 * Get prefix to advertise
3119 if (!str2prefix(argv
[8]->arg
, &pfx
)) {
3120 vty_out(vty
, "Malformed prefix \"%s\"\n", argv
[8]->arg
);
3121 return CMD_WARNING_CONFIG_FAILED
;
3123 if (pfx
.family
!= AF_INET
&& pfx
.family
!= AF_INET6
) {
3124 vty_out(vty
, "Bad family for prefix \"%s\"\n", argv
[8]->arg
);
3125 return CMD_WARNING_CONFIG_FAILED
;
3127 rfapiQprefix2Rprefix(&pfx
, &hpfx
);
3129 if (strmatch(argv
[10]->text
, "infinite")) {
3130 lifetime
= RFAPI_INFINITE_LIFETIME
;
3132 lifetime
= strtoul(argv
[10]->arg
, NULL
, 10);
3135 /* L2 option parsing START */
3136 memset(optary
, 0, sizeof(optary
));
3137 optary
[opt_next
].v
.l2addr
.logical_net_id
=
3138 strtoul(argv
[14]->arg
, NULL
, 10);
3139 if (rfapiStr2EthAddr(argv
[12]->arg
,
3140 &optary
[opt_next
].v
.l2addr
.macaddr
)) {
3141 vty_out(vty
, "Bad mac address \"%s\"\n", argv
[12]->arg
);
3142 return CMD_WARNING_CONFIG_FAILED
;
3144 optary
[opt_next
].type
= RFAPI_VN_OPTION_TYPE_L2ADDR
;
3147 /* L2 option parsing END */
3150 rc
= rfapi_register(handle
, &hpfx
, lifetime
, NULL
/* &uo */, opt
,
3151 RFAPI_REGISTER_ADD
);
3153 vty_out(vty
, "rfapi_register failed with rc=%d (%s)\n", rc
,
3161 DEFUN (debug_rfapi_unregister_vn_un
,
3162 debug_rfapi_unregister_vn_un_cmd
,
3163 "debug rfapi-dev unregister vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> prefix <A.B.C.D/M|X:X::X:X/M> [kill]",
3166 "rfapi_unregister\n"
3167 "indicate vn addr follows\n"
3168 "virtual network interface address\n"
3169 "virtual network interface address\n"
3170 "indicate xt addr follows\n"
3171 "underlay network interface address\n"
3172 "underlay network interface address\n"
3173 "prefix to remove\n"
3174 "prefix to remove\n"
3175 "prefix to remove\n"
3176 "Remove without holddown\n")
3178 struct rfapi_ip_addr vn
;
3179 struct rfapi_ip_addr un
;
3180 rfapi_handle handle
;
3182 struct rfapi_ip_prefix hpfx
;
3188 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[4]->arg
, &vn
)))
3194 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[6]->arg
, &un
)))
3198 if (rfapi_find_handle_vty(vty
, &vn
, &un
, &handle
)) {
3199 vty_out(vty
, "can't locate handle matching vn=%s, un=%s\n",
3200 argv
[4]->arg
, argv
[6]->arg
);
3201 return CMD_WARNING_CONFIG_FAILED
;
3205 * Get prefix to advertise
3207 if (!str2prefix(argv
[8]->arg
, &pfx
)) {
3208 vty_out(vty
, "Malformed prefix \"%s\"\n", argv
[8]->arg
);
3209 return CMD_WARNING_CONFIG_FAILED
;
3211 if (pfx
.family
!= AF_INET
&& pfx
.family
!= AF_INET6
) {
3212 vty_out(vty
, "Bad family for prefix \"%s\"\n", argv
[8]->arg
);
3213 return CMD_WARNING_CONFIG_FAILED
;
3215 rfapiQprefix2Rprefix(&pfx
, &hpfx
);
3217 rfapi_register(handle
, &hpfx
, 0, NULL
, NULL
,
3219 RFAPI_REGISTER_KILL
: RFAPI_REGISTER_WITHDRAW
));
3224 DEFUN (debug_rfapi_query_vn_un
,
3225 debug_rfapi_query_vn_un_cmd
,
3226 "debug rfapi-dev query vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> target <A.B.C.D|X:X::X:X>",
3230 "indicate vn addr follows\n"
3231 "virtual network interface IPv4 address\n"
3232 "virtual network interface IPv6 address\n"
3233 "indicate un addr follows\n"
3236 "indicate target follows\n"
3237 "target IPv4 address\n"
3238 "target IPv6 address\n")
3240 struct rfapi_ip_addr vn
;
3241 struct rfapi_ip_addr un
;
3242 struct rfapi_ip_addr target
;
3243 rfapi_handle handle
;
3245 struct rfapi_next_hop_entry
*pNextHopEntry
;
3250 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[4]->arg
, &vn
)))
3257 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[6]->arg
, &un
)))
3264 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[8]->arg
, &target
)))
3268 if (rfapi_find_handle_vty(vty
, &vn
, &un
, &handle
)) {
3269 vty_out(vty
, "can't locate handle matching vn=%s, un=%s\n",
3270 argv
[4]->arg
, argv
[6]->arg
);
3271 return CMD_WARNING_CONFIG_FAILED
;
3275 * options parameter not used? Set to NULL for now
3277 rc
= rfapi_query(handle
, &target
, NULL
, &pNextHopEntry
);
3280 vty_out(vty
, "rfapi_query failed with rc=%d (%s)\n", rc
,
3284 * print nexthop list
3286 test_nexthops_callback(/*&target, */ pNextHopEntry
,
3287 vty
); /* frees nh list! */
3294 DEFUN (debug_rfapi_query_vn_un_l2o
,
3295 debug_rfapi_query_vn_un_l2o_cmd
,
3296 "debug rfapi-dev query vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> lni LNI target X:X:X:X:X:X",
3300 "indicate vn addr follows\n"
3301 "virtual network interface IPv4 address\n"
3302 "virtual network interface IPv6 address\n"
3303 "indicate xt addr follows\n"
3304 "underlay network interface IPv4 address\n"
3305 "underlay network interface IPv6 address\n"
3306 "logical network ID follows\n"
3307 "logical network ID\n"
3308 "indicate target MAC addr follows\n"
3309 "target MAC addr\n")
3311 struct rfapi_ip_addr vn
;
3312 struct rfapi_ip_addr un
;
3318 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[4]->arg
, &vn
)))
3325 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[6]->arg
, &un
)))
3328 vty_out(vty
, "%% This command is broken.\n");
3329 return CMD_WARNING_CONFIG_FAILED
;
3333 DEFUN (debug_rfapi_query_done_vn_un
,
3334 debug_rfapi_query_vn_un_done_cmd
,
3335 "debug rfapi-dev query done vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> target <A.B.C.D|X:X::X:X>",
3338 "rfapi_query_done\n"
3339 "rfapi_query_done\n"
3340 "indicate vn addr follows\n"
3341 "virtual network interface IPv4 address\n"
3342 "virtual network interface IPv6 address\n"
3343 "indicate xt addr follows\n"
3344 "underlay network interface IPv4 address\n"
3345 "underlay network interface IPv6 address\n"
3346 "indicate target follows\n"
3347 "Target IPv4 address\n"
3348 "Target IPv6 address\n")
3350 struct rfapi_ip_addr vn
;
3351 struct rfapi_ip_addr un
;
3352 struct rfapi_ip_addr target
;
3353 rfapi_handle handle
;
3359 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[5]->arg
, &vn
)))
3366 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[7]->arg
, &un
)))
3373 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[9]->arg
, &target
)))
3377 if (rfapi_find_handle_vty(vty
, &vn
, &un
, &handle
)) {
3378 vty_out(vty
, "can't locate handle matching vn=%s, un=%s\n",
3379 argv
[5]->arg
, argv
[7]->arg
);
3380 return CMD_WARNING_CONFIG_FAILED
;
3384 * options parameter not used? Set to NULL for now
3386 rc
= rfapi_query_done(handle
, &target
);
3388 vty_out(vty
, "rfapi_query_done returned %d\n", rc
);
3393 DEFUN (debug_rfapi_show_import
,
3394 debug_rfapi_show_import_cmd
,
3395 "debug rfapi-dev show import",
3403 struct rfapi_import_table
*it
;
3408 * Show all import tables
3411 bgp
= bgp_get_default(); /* assume 1 instance for now */
3413 vty_out(vty
, "No BGP instance\n");
3414 return CMD_WARNING_CONFIG_FAILED
;
3419 vty_out(vty
, "No RFAPI instance\n");
3420 return CMD_WARNING_CONFIG_FAILED
;
3424 * Iterate over all import tables; do a filtered import
3425 * for the afi/safi combination
3429 for (it
= h
->imports
; it
; it
= it
->next
) {
3430 s
= ecommunity_ecom2str(it
->rt_import_list
,
3431 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3432 vty_out(vty
, "Import Table %p, RTs: %s\n", it
, s
);
3433 XFREE(MTYPE_ECOMMUNITY_STR
, s
);
3435 rfapiShowImportTable(vty
, "IP VPN", it
->imported_vpn
[AFI_IP
],
3437 rfapiShowImportTable(vty
, "IP ENCAP",
3438 it
->imported_encap
[AFI_IP
], 0);
3439 rfapiShowImportTable(vty
, "IP6 VPN", it
->imported_vpn
[AFI_IP6
],
3441 rfapiShowImportTable(vty
, "IP6 ENCAP",
3442 it
->imported_encap
[AFI_IP6
], 0);
3445 if (h
->import_mac
) {
3446 void *cursor
= NULL
;
3448 uintptr_t lni_as_ptr
;
3452 for (rc
= skiplist_next(h
->import_mac
, (void **)&lni_as_ptr
,
3453 (void **)&it
, &cursor
);
3455 rc
= skiplist_next(h
->import_mac
, (void **)&lni_as_ptr
,
3456 (void **)&it
, &cursor
)) {
3458 if (it
->imported_vpn
[AFI_L2VPN
]) {
3462 "\nLNI-based Ethernet Tables:\n");
3465 snprintf(buf
, sizeof(buf
), "L2VPN LNI=%u", lni
);
3466 rfapiShowImportTable(
3467 vty
, buf
, it
->imported_vpn
[AFI_L2VPN
],
3473 rfapiShowImportTable(vty
, "CE IT - IP VPN",
3474 h
->it_ce
->imported_vpn
[AFI_IP
], 1);
3479 DEFUN (debug_rfapi_show_import_vn_un
,
3480 debug_rfapi_show_import_vn_un_cmd
,
3481 "debug rfapi-dev show import vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X>",
3486 "indicate vn addr follows\n"
3487 "virtual network interface IPv4 address\n"
3488 "virtual network interface IPv6 address\n"
3489 "indicate xt addr follows\n"
3490 "underlay network interface IPv4 address\n"
3491 "underlay network interface IPv6 address\n")
3493 struct rfapi_ip_addr vn
;
3494 struct rfapi_ip_addr un
;
3495 rfapi_handle handle
;
3497 struct rfapi_descriptor
*rfd
;
3502 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[5]->arg
, &vn
)))
3509 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[7]->arg
, &un
)))
3513 if (rfapi_find_handle_vty(vty
, &vn
, &un
, &handle
)) {
3514 vty_out(vty
, "can't locate handle matching vn=%s, un=%s\n",
3515 argv
[5]->arg
, argv
[7]->arg
);
3516 return CMD_WARNING_CONFIG_FAILED
;
3519 rfd
= (struct rfapi_descriptor
*)handle
;
3521 rfapiShowImportTable(vty
, "IP VPN",
3522 rfd
->import_table
->imported_vpn
[AFI_IP
], 1);
3523 rfapiShowImportTable(vty
, "IP ENCAP",
3524 rfd
->import_table
->imported_encap
[AFI_IP
], 0);
3525 rfapiShowImportTable(vty
, "IP6 VPN",
3526 rfd
->import_table
->imported_vpn
[AFI_IP6
], 1);
3527 rfapiShowImportTable(vty
, "IP6 ENCAP",
3528 rfd
->import_table
->imported_encap
[AFI_IP6
], 0);
3533 DEFUN (debug_rfapi_response_omit_self
,
3534 debug_rfapi_response_omit_self_cmd
,
3535 "debug rfapi-dev response-omit-self <on|off>",
3538 "Omit self in RFP responses\n"
3539 "filter out self from responses\n" "leave self in responses\n")
3541 struct bgp
*bgp
= bgp_get_default();
3544 vty_out(vty
, "No BGP process is configured\n");
3545 return CMD_WARNING_CONFIG_FAILED
;
3547 if (!bgp
->rfapi_cfg
) {
3548 vty_out(vty
, "VNC not configured\n");
3549 return CMD_WARNING_CONFIG_FAILED
;
3552 if (strmatch(argv
[3]->text
, "on"))
3553 SET_FLAG(bgp
->rfapi_cfg
->flags
,
3554 BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP
);
3556 UNSET_FLAG(bgp
->rfapi_cfg
->flags
,
3557 BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP
);
3563 #ifdef RFAPI_DEBUG_SKIPLIST_CLI
3565 #include "lib/skiplist.h"
3566 DEFUN (skiplist_test_cli
,
3567 skiplist_test_cli_cmd
,
3569 "skiplist command\n"
3577 DEFUN (skiplist_debug_cli
,
3578 skiplist_debug_cli_cmd
,
3580 "skiplist command\n"
3583 skiplist_debug(vty
, NULL
);
3587 #endif /* RFAPI_DEBUG_SKIPLIST_CLI */
3589 void rfapi_init(void)
3591 bgp_rfapi_cfg_init();
3594 install_element(ENABLE_NODE
, &debug_rfapi_show_import_cmd
);
3595 install_element(ENABLE_NODE
, &debug_rfapi_show_import_vn_un_cmd
);
3597 install_element(ENABLE_NODE
, &debug_rfapi_open_cmd
);
3598 install_element(ENABLE_NODE
, &debug_rfapi_close_vn_un_cmd
);
3599 install_element(ENABLE_NODE
, &debug_rfapi_close_rfd_cmd
);
3600 install_element(ENABLE_NODE
, &debug_rfapi_register_vn_un_cmd
);
3601 install_element(ENABLE_NODE
, &debug_rfapi_unregister_vn_un_cmd
);
3602 install_element(ENABLE_NODE
, &debug_rfapi_query_vn_un_cmd
);
3603 install_element(ENABLE_NODE
, &debug_rfapi_query_vn_un_done_cmd
);
3604 install_element(ENABLE_NODE
, &debug_rfapi_query_vn_un_l2o_cmd
);
3606 install_element(ENABLE_NODE
, &debug_rfapi_response_omit_self_cmd
);
3608 /* Need the following show commands for gpz test scripts */
3609 install_element(ENABLE_NODE
, &debug_rfapi_show_nves_cmd
);
3610 install_element(ENABLE_NODE
, &debug_rfapi_show_nves_vn_un_cmd
);
3611 install_element(ENABLE_NODE
, &debug_rfapi_register_vn_un_l2o_cmd
);
3613 #ifdef RFAPI_DEBUG_SKIPLIST_CLI
3614 install_element(ENABLE_NODE
, &skiplist_test_cli_cmd
);
3615 install_element(ENABLE_NODE
, &skiplist_debug_cli_cmd
);
3622 static void rfapi_print_exported(struct bgp
*bgp
)
3624 struct bgp_dest
*destn
;
3625 struct bgp_dest
*dest
;
3626 struct bgp_path_info
*bpi
;
3631 for (destn
= bgp_table_top(bgp
->rib
[AFI_IP
][SAFI_MPLS_VPN
]); destn
;
3632 destn
= bgp_route_next(destn
)) {
3633 struct bgp_table
*table
;
3635 table
= bgp_dest_get_bgp_table_info(destn
);
3638 fprintf(stderr
, "%s: vpn destn=%p\n", __func__
, destn
);
3639 for (dest
= bgp_table_top(table
); dest
;
3640 dest
= bgp_route_next(dest
)) {
3641 bpi
= bgp_dest_get_bgp_path_info(dest
);
3645 fprintf(stderr
, "%s: dest=%p\n", __func__
, dest
);
3646 for (; bpi
; bpi
= bpi
->next
) {
3647 rfapiPrintBi((void *)2, bpi
); /* 2 => stderr */
3651 for (destn
= bgp_table_top(bgp
->rib
[AFI_IP
][SAFI_ENCAP
]); destn
;
3652 destn
= bgp_route_next(destn
)) {
3653 struct bgp_table
*table
;
3655 table
= bgp_dest_get_bgp_table_info(destn
);
3658 fprintf(stderr
, "%s: encap destn=%p\n", __func__
, destn
);
3659 for (dest
= bgp_table_top(table
); dest
;
3660 dest
= bgp_route_next(dest
)) {
3661 bpi
= bgp_dest_get_bgp_path_info(dest
);
3664 fprintf(stderr
, "%s: dest=%p\n", __func__
, dest
);
3665 for (; bpi
; bpi
= bpi
->next
) {
3666 rfapiPrintBi((void *)2, bpi
); /* 2 => stderr */
3671 #endif /* defined(DEBUG_RFAPI) */
3674 * Free all memory to prepare for clean exit as seen by valgrind memcheck
3676 void rfapi_delete(struct bgp
*bgp
)
3678 extern void rfp_clear_vnc_nve_all(void); /* can't fix correctly yet */
3681 * This clears queries and registered routes, and closes nves
3684 rfp_clear_vnc_nve_all();
3685 bgp_rfapi_cfg_destroy(bgp
, bgp
->rfapi_cfg
);
3686 bgp
->rfapi_cfg
= NULL
;
3687 bgp_rfapi_destroy(bgp
, bgp
->rfapi
);
3691 * show what's left in the BGP MPLSVPN RIB
3693 rfapi_print_exported(bgp
);
3697 int rfapi_set_autord_from_vn(struct prefix_rd
*rd
, struct rfapi_ip_addr
*vn
)
3699 vnc_zlog_debug_verbose("%s: auto-assigning RD", __func__
);
3700 if (vn
->addr_family
!= AF_INET
&& vn
->addr_family
!= AF_INET6
) {
3701 vnc_zlog_debug_verbose(
3702 "%s: can't auto-assign RD, VN addr family is not IPv4|v6",
3704 return EAFNOSUPPORT
;
3706 rd
->family
= AF_UNSPEC
;
3708 rd
->val
[1] = RD_TYPE_IP
;
3709 if (vn
->addr_family
== AF_INET
) {
3710 memcpy(rd
->val
+ 2, &vn
->addr
.v4
.s_addr
, 4);
3711 } else { /* is v6 */
3712 memcpy(rd
->val
+ 2, &vn
->addr
.v6
.s6_addr32
[3],
3713 4); /* low order 4 bytes */
3715 vnc_zlog_debug_verbose("%s: auto-RD is set to %pRDP", __func__
, rd
);
3719 /*------------------------------------------
3720 * rfapi_bgp_lookup_by_rfp
3722 * Find bgp instance pointer based on value returned by rfp_start
3725 * rfp_start_val value returned by rfp_startor
3726 * NULL (=get default instance)
3732 * bgp bgp instance pointer
3735 --------------------------------------------*/
3736 struct bgp
*rfapi_bgp_lookup_by_rfp(void *rfp_start_val
)
3738 struct bgp
*bgp
= NULL
;
3739 struct listnode
*node
, *nnode
;
3741 if (rfp_start_val
== NULL
)
3742 bgp
= bgp_get_default();
3744 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
3745 if (bgp
->rfapi
!= NULL
3746 && bgp
->rfapi
->rfp
== rfp_start_val
)
3751 /*------------------------------------------
3752 * rfapi_get_rfp_start_val_by_bgp
3754 * Find bgp instance pointer based on value returned by rfp_start
3757 * bgp bgp instance pointer
3766 --------------------------------------------*/
3767 void *rfapi_get_rfp_start_val_by_bgp(struct bgp
*bgp
)
3769 if (!bgp
|| !bgp
->rfapi
)
3771 return bgp
->rfapi
->rfp
;
3774 /***********************************************************************
3775 * RFP group specific configuration
3776 ***********************************************************************/
3777 static void *rfapi_rfp_get_or_init_group_config_default(struct rfapi_cfg
*rfc
,
3781 if (rfc
->default_rfp_cfg
== NULL
&& size
> 0) {
3782 rfc
->default_rfp_cfg
= XCALLOC(MTYPE_RFAPI_RFP_GROUP_CFG
, size
);
3783 vnc_zlog_debug_verbose("%s: allocated, size=%d", __func__
,
3786 return rfc
->default_rfp_cfg
;
3789 static void *rfapi_rfp_get_or_init_group_config_nve(struct rfapi_cfg
*rfc
,
3793 struct rfapi_nve_group_cfg
*rfg
=
3794 VTY_GET_CONTEXT_SUB(rfapi_nve_group_cfg
);
3796 /* make sure group is still in list */
3797 if (!rfg
|| !listnode_lookup(rfc
->nve_groups_sequential
, rfg
)) {
3798 /* Not in list anymore */
3799 vty_out(vty
, "Current NVE group no longer exists\n");
3803 if (rfg
->rfp_cfg
== NULL
&& size
> 0) {
3804 rfg
->rfp_cfg
= XCALLOC(MTYPE_RFAPI_RFP_GROUP_CFG
, size
);
3805 vnc_zlog_debug_verbose("%s: allocated, size=%d", __func__
,
3808 return rfg
->rfp_cfg
;
3811 static void *rfapi_rfp_get_or_init_group_config_l2(struct rfapi_cfg
*rfc
,
3815 struct rfapi_l2_group_cfg
*rfg
=
3816 VTY_GET_CONTEXT_SUB(rfapi_l2_group_cfg
);
3818 /* make sure group is still in list */
3819 if (!rfg
|| !listnode_lookup(rfc
->l2_groups
, rfg
)) {
3820 /* Not in list anymore */
3821 vty_out(vty
, "Current L2 group no longer exists\n");
3824 if (rfg
->rfp_cfg
== NULL
&& size
> 0) {
3825 rfg
->rfp_cfg
= XCALLOC(MTYPE_RFAPI_RFP_GROUP_CFG
, size
);
3826 vnc_zlog_debug_verbose("%s: allocated, size=%d", __func__
,
3829 return rfg
->rfp_cfg
;
3832 /*------------------------------------------
3833 * rfapi_rfp_init_group_config_ptr_vty
3835 * This is used to init or return a previously init'ed group specific
3836 * configuration pointer. Group is identified by vty context.
3837 * NOTE: size is ignored when a previously init'ed value is returned.
3838 * RFAPI frees rfp_cfg_group when group is deleted during reconfig,
3839 * bgp restart or shutdown.
3842 * rfp_start_val value returned by rfp_start
3844 * vty quagga vty context
3845 * size number of bytes to allocation
3851 * rfp_cfg_group NULL or Pointer to configuration structure
3852 --------------------------------------------*/
3853 void *rfapi_rfp_init_group_config_ptr_vty(void *rfp_start_val
,
3854 rfapi_rfp_cfg_group_type type
,
3855 struct vty
*vty
, uint32_t size
)
3860 if (rfp_start_val
== NULL
|| vty
== NULL
)
3863 bgp
= rfapi_bgp_lookup_by_rfp(rfp_start_val
);
3864 if (!bgp
|| !bgp
->rfapi_cfg
)
3868 case RFAPI_RFP_CFG_GROUP_DEFAULT
:
3869 ret
= rfapi_rfp_get_or_init_group_config_default(bgp
->rfapi_cfg
,
3872 case RFAPI_RFP_CFG_GROUP_NVE
:
3873 ret
= rfapi_rfp_get_or_init_group_config_nve(bgp
->rfapi_cfg
,
3876 case RFAPI_RFP_CFG_GROUP_L2
:
3877 ret
= rfapi_rfp_get_or_init_group_config_l2(bgp
->rfapi_cfg
, vty
,
3881 flog_err(EC_LIB_DEVELOPMENT
, "%s: Unknown group type=%d",
3883 /* should never happen */
3884 assert("Unknown type" == NULL
);
3890 /*------------------------------------------
3891 * rfapi_rfp_get_group_config_ptr_vty
3893 * This is used to get group specific configuration pointer.
3894 * Group is identified by type and vty context.
3895 * RFAPI frees rfp_cfg_group when group is deleted during reconfig,
3896 * bgp restart or shutdown.
3899 * rfp_start_val value returned by rfp_start
3901 * vty quagga vty context
3907 * rfp_cfg_group Pointer to configuration structure
3908 --------------------------------------------*/
3909 void *rfapi_rfp_get_group_config_ptr_vty(void *rfp_start_val
,
3910 rfapi_rfp_cfg_group_type type
,
3913 return rfapi_rfp_init_group_config_ptr_vty(rfp_start_val
, type
, vty
, 0);
3917 rfapi_rfp_get_group_config_name_nve(struct rfapi_cfg
*rfc
, const char *name
,
3919 rfp_group_config_search_cb_t
*search_cb
)
3921 struct rfapi_nve_group_cfg
*rfg
;
3922 struct listnode
*node
;
3924 for (ALL_LIST_ELEMENTS_RO(rfc
->nve_groups_sequential
, node
, rfg
)) {
3925 if (!strcmp(rfg
->name
, name
) && /* name match */
3926 (search_cb
== NULL
|| !search_cb(criteria
, rfg
->rfp_cfg
)))
3927 return rfg
->rfp_cfg
;
3933 rfapi_rfp_get_group_config_name_l2(struct rfapi_cfg
*rfc
, const char *name
,
3935 rfp_group_config_search_cb_t
*search_cb
)
3937 struct rfapi_l2_group_cfg
*rfg
;
3938 struct listnode
*node
;
3940 for (ALL_LIST_ELEMENTS_RO(rfc
->l2_groups
, node
, rfg
)) {
3941 if (!strcmp(rfg
->name
, name
) && /* name match */
3942 (search_cb
== NULL
|| !search_cb(criteria
, rfg
->rfp_cfg
)))
3943 return rfg
->rfp_cfg
;
3948 /*------------------------------------------
3949 * rfapi_rfp_get_group_config_ptr_name
3951 * This is used to get group specific configuration pointer.
3952 * Group is identified by type and name context.
3953 * RFAPI frees rfp_cfg_group when group is deleted during reconfig,
3954 * bgp restart or shutdown.
3957 * rfp_start_val value returned by rfp_start
3960 * criteria RFAPI caller provided search criteria
3961 * search_cb optional rfp_group_config_search_cb_t
3967 * rfp_cfg_group Pointer to configuration structure
3968 --------------------------------------------*/
3969 void *rfapi_rfp_get_group_config_ptr_name(
3970 void *rfp_start_val
, rfapi_rfp_cfg_group_type type
, const char *name
,
3971 void *criteria
, rfp_group_config_search_cb_t
*search_cb
)
3976 if (rfp_start_val
== NULL
|| name
== NULL
)
3979 bgp
= rfapi_bgp_lookup_by_rfp(rfp_start_val
);
3980 if (!bgp
|| !bgp
->rfapi_cfg
)
3984 case RFAPI_RFP_CFG_GROUP_DEFAULT
:
3985 ret
= bgp
->rfapi_cfg
->default_rfp_cfg
;
3987 case RFAPI_RFP_CFG_GROUP_NVE
:
3988 ret
= rfapi_rfp_get_group_config_name_nve(bgp
->rfapi_cfg
, name
,
3989 criteria
, search_cb
);
3991 case RFAPI_RFP_CFG_GROUP_L2
:
3992 ret
= rfapi_rfp_get_group_config_name_l2(bgp
->rfapi_cfg
, name
,
3993 criteria
, search_cb
);
3996 flog_err(EC_LIB_DEVELOPMENT
, "%s: Unknown group type=%d",
3998 /* should never happen */
3999 assert("Unknown type" == NULL
);
4005 /*------------------------------------------
4006 * rfapi_rfp_get_l2_group_config_ptr_lni
4008 * This is used to get group specific configuration pointer.
4009 * Group is identified by type and logical network identifier.
4010 * RFAPI frees rfp_cfg_group when group is deleted during reconfig,
4011 * bgp restart or shutdown.
4014 * rfp_start_val value returned by rfp_start
4016 * logical_net_id group logical network identifier
4017 * criteria RFAPI caller provided search criteria
4018 * search_cb optional rfp_group_config_search_cb_t
4024 * rfp_cfg_group Pointer to configuration structure
4025 --------------------------------------------*/
4027 rfapi_rfp_get_l2_group_config_ptr_lni(void *rfp_start_val
,
4028 uint32_t logical_net_id
, void *criteria
,
4029 rfp_group_config_search_cb_t
*search_cb
)
4032 struct rfapi_l2_group_cfg
*rfg
;
4033 struct listnode
*node
;
4035 if (rfp_start_val
== NULL
)
4038 bgp
= rfapi_bgp_lookup_by_rfp(rfp_start_val
);
4039 if (!bgp
|| !bgp
->rfapi_cfg
)
4042 for (ALL_LIST_ELEMENTS_RO(bgp
->rfapi_cfg
->l2_groups
, node
, rfg
)) {
4043 if (rfg
->logical_net_id
== logical_net_id
4044 && (search_cb
== NULL
4045 || !search_cb(criteria
, rfg
->rfp_cfg
))) {
4046 if (rfg
->rfp_cfg
== NULL
)
4047 vnc_zlog_debug_verbose(
4048 "%s: returning rfp group config for lni=0",
4050 return rfg
->rfp_cfg
;