3 * Copyright 2009-2016, LabN Consulting, L.L.C.
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
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
21 #include "lib/zebra.h"
22 #include "lib/prefix.h"
23 #include "lib/agg_table.h"
25 #include "lib/memory.h"
26 #include "lib/routemap.h"
28 #include "lib/linklist.h"
29 #include "lib/command.h"
30 #include "lib/stream.h"
31 #include "lib/ringbuf.h"
32 #include "lib/lib_errors.h"
34 #include "bgpd/bgpd.h"
35 #include "bgpd/bgp_ecommunity.h"
36 #include "bgpd/bgp_attr.h"
38 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
39 #include "bgpd/rfapi/rfapi.h"
40 #include "bgpd/rfapi/rfapi_backend.h"
42 #include "bgpd/bgp_route.h"
43 #include "bgpd/bgp_mplsvpn.h"
44 #include "bgpd/bgp_aspath.h"
45 #include "bgpd/bgp_advertise.h"
46 #include "bgpd/bgp_vnc_types.h"
47 #include "bgpd/bgp_zebra.h"
49 #include "bgpd/rfapi/rfapi_import.h"
50 #include "bgpd/rfapi/rfapi_private.h"
51 #include "bgpd/rfapi/rfapi_monitor.h"
52 #include "bgpd/rfapi/rfapi_vty.h"
53 #include "bgpd/rfapi/vnc_export_bgp.h"
54 #include "bgpd/rfapi/vnc_export_bgp_p.h"
55 #include "bgpd/rfapi/vnc_zebra.h"
56 #include "bgpd/rfapi/vnc_import_bgp.h"
57 #include "bgpd/rfapi/rfapi_rib.h"
58 #include "bgpd/rfapi/rfapi_ap.h"
59 #include "bgpd/rfapi/rfapi_encap_tlv.h"
60 #include "bgpd/rfapi/vnc_debug.h"
62 #ifdef HAVE_GLIBC_BACKTRACE
63 /* for backtrace and friends */
65 #endif /* HAVE_GLIBC_BACKTRACE */
67 struct ethaddr rfapi_ethaddr0
= {{0}};
69 #define DEBUG_RFAPI_STR "RF API debugging/testing command\n"
71 const char *rfapi_error_str(int code
)
77 return "BGP or VNC not configured";
81 return "Handle already open";
83 return "Incomplete configuration";
85 return "Invalid address family";
87 return "Called from within a callback procedure";
89 return "Invalid handle";
91 return "Invalid argument";
93 return "Stale descriptor";
95 return "Unknown error";
99 /*------------------------------------------
100 * rfapi_get_response_lifetime_default
102 * Returns the default lifetime for a response.
103 * rfp_start_val value returned by rfp_start or
104 * NULL (=use default instance)
111 * return value: The bgp instance default lifetime for a response.
112 --------------------------------------------*/
113 int rfapi_get_response_lifetime_default(void *rfp_start_val
)
115 struct bgp
*bgp
= rfapi_bgp_lookup_by_rfp(rfp_start_val
);
117 return bgp
->rfapi_cfg
->default_response_lifetime
;
118 return BGP_VNC_DEFAULT_RESPONSE_LIFETIME_DEFAULT
;
121 /*------------------------------------------
122 * rfapi_is_vnc_configured
124 * Returns if VNC is configured
127 * rfp_start_val value returned by rfp_start or
128 * NULL (=use default instance)
132 * return value: If VNC is configured for the bgpd instance
134 * ENXIO VNC not configured
135 --------------------------------------------*/
136 int rfapi_is_vnc_configured(void *rfp_start_val
)
138 struct bgp
*bgp
= rfapi_bgp_lookup_by_rfp(rfp_start_val
);
139 if (bgp_rfapi_is_vnc_configured(bgp
) == 0)
145 /*------------------------------------------
148 * Get the virtual network address used by an NVE based on it's RFD
151 * rfd: rfapi descriptor returned by rfapi_open or rfapi_create_generic
156 * vn NVE virtual network address
157 *------------------------------------------*/
158 struct rfapi_ip_addr
*rfapi_get_vn_addr(void *rfd
)
160 struct rfapi_descriptor
*rrfd
= (struct rfapi_descriptor
*)rfd
;
161 return &rrfd
->vn_addr
;
164 /*------------------------------------------
167 * Get the underlay network address used by an NVE based on it's RFD
170 * rfd: rfapi descriptor returned by rfapi_open or rfapi_create_generic
175 * un NVE underlay network address
176 *------------------------------------------*/
177 struct rfapi_ip_addr
*rfapi_get_un_addr(void *rfd
)
179 struct rfapi_descriptor
*rrfd
= (struct rfapi_descriptor
*)rfd
;
180 return &rrfd
->un_addr
;
183 int rfapi_ip_addr_cmp(struct rfapi_ip_addr
*a1
, struct rfapi_ip_addr
*a2
)
185 if (a1
->addr_family
!= a2
->addr_family
)
186 return a1
->addr_family
- a2
->addr_family
;
188 if (a1
->addr_family
== AF_INET
) {
189 return IPV4_ADDR_CMP(&a1
->addr
.v4
, &a2
->addr
.v4
);
192 if (a1
->addr_family
== AF_INET6
) {
193 return IPV6_ADDR_CMP(&a1
->addr
.v6
, &a2
->addr
.v6
);
201 static int rfapi_find_node(struct bgp
*bgp
, struct rfapi_ip_addr
*vn_addr
,
202 struct rfapi_ip_addr
*un_addr
,
203 struct agg_node
**node
)
220 afi
= family2afi(un_addr
->addr_family
);
225 if ((rc
= rfapiRaddr2Qprefix(un_addr
, &p
)))
228 rn
= agg_node_lookup(h
->un
[afi
], &p
);
241 int rfapi_find_rfd(struct bgp
*bgp
, struct rfapi_ip_addr
*vn_addr
,
242 struct rfapi_ip_addr
*un_addr
, struct rfapi_descriptor
**rfd
)
247 rc
= rfapi_find_node(bgp
, vn_addr
, un_addr
, &rn
);
252 for (*rfd
= (struct rfapi_descriptor
*)(rn
->info
); *rfd
;
253 *rfd
= (*rfd
)->next
) {
254 if (!rfapi_ip_addr_cmp(&(*rfd
)->vn_addr
, vn_addr
))
264 /*------------------------------------------
268 * un underlay network address
269 * vn virtual network address
272 * pHandle pointer to location to store handle
276 * ENOENT no matching handle
277 * ENXIO BGP or VNC not configured
278 *------------------------------------------*/
279 static int rfapi_find_handle(struct bgp
*bgp
, struct rfapi_ip_addr
*vn_addr
,
280 struct rfapi_ip_addr
*un_addr
,
281 rfapi_handle
*handle
)
283 struct rfapi_descriptor
**rfd
;
285 rfd
= (struct rfapi_descriptor
**)handle
;
287 return rfapi_find_rfd(bgp
, vn_addr
, un_addr
, rfd
);
290 static int rfapi_find_handle_vty(struct vty
*vty
, struct rfapi_ip_addr
*vn_addr
,
291 struct rfapi_ip_addr
*un_addr
,
292 rfapi_handle
*handle
)
295 struct rfapi_descriptor
**rfd
;
297 bgp
= bgp_get_default(); /* assume 1 instance for now */
299 rfd
= (struct rfapi_descriptor
**)handle
;
301 return rfapi_find_rfd(bgp
, vn_addr
, un_addr
, rfd
);
304 static int is_valid_rfd(struct rfapi_descriptor
*rfd
)
308 if (!rfd
|| rfd
->bgp
== NULL
)
313 RFAPI_HD_FLAG_IS_VRF
)) /* assume VRF/internal are valid */
316 if (rfapi_find_handle(rfd
->bgp
, &rfd
->vn_addr
, &rfd
->un_addr
, &hh
))
326 * check status of descriptor
328 int rfapi_check(void *handle
)
330 struct rfapi_descriptor
*rfd
= (struct rfapi_descriptor
*)handle
;
334 if (!rfd
|| rfd
->bgp
== NULL
)
339 RFAPI_HD_FLAG_IS_VRF
)) /* assume VRF/internal are valid */
342 if ((rc
= rfapi_find_handle(rfd
->bgp
, &rfd
->vn_addr
, &rfd
->un_addr
,
356 void del_vnc_route(struct rfapi_descriptor
*rfd
,
357 struct peer
*peer
, /* rfd->peer for RFP regs */
358 struct bgp
*bgp
, safi_t safi
, struct prefix
*p
,
359 struct prefix_rd
*prd
, uint8_t type
, uint8_t sub_type
,
360 struct rfapi_nexthop
*lnh
, int kill
)
362 afi_t afi
; /* of the VN address */
364 struct bgp_path_info
*bpi
;
365 char buf
[PREFIX_STRLEN
];
366 char buf2
[RD_ADDRSTRLEN
];
367 struct prefix_rd prd0
;
369 prefix2str(p
, buf
, sizeof(buf
));
371 afi
= family2afi(p
->family
);
372 assert(afi
== AFI_IP
|| afi
== AFI_IP6
);
374 if (safi
== SAFI_ENCAP
) {
375 memset(&prd0
, 0, sizeof(prd0
));
376 prd0
.family
= AF_UNSPEC
;
380 bn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
382 vnc_zlog_debug_verbose(
383 "%s: peer=%p, prefix=%s, prd=%s afi=%d, safi=%d bn=%p, bn->info=%p",
384 __func__
, peer
, buf
, prefix_rd2str(prd
, buf2
, sizeof(buf2
)),
385 afi
, safi
, bn
, (bn
? bgp_node_get_bgp_path_info(bn
) : NULL
));
387 for (bpi
= (bn
? bgp_node_get_bgp_path_info(bn
) : NULL
); bpi
;
390 vnc_zlog_debug_verbose(
391 "%s: trying bpi=%p, bpi->peer=%p, bpi->type=%d, bpi->sub_type=%d, bpi->extra->vnc.export.rfapi_handle=%p, local_pref=%" PRIu64
,
392 __func__
, bpi
, bpi
->peer
, bpi
->type
, bpi
->sub_type
,
393 (bpi
->extra
? bpi
->extra
->vnc
.export
.rfapi_handle
395 CHECK_FLAG(bpi
->attr
->flag
,
396 ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)
397 ? bpi
->attr
->local_pref
: 0));
399 if (bpi
->peer
== peer
&& bpi
->type
== type
400 && bpi
->sub_type
== sub_type
&& bpi
->extra
401 && bpi
->extra
->vnc
.export
.rfapi_handle
== (void *)rfd
) {
403 vnc_zlog_debug_verbose("%s: matched it", __func__
);
411 * lnh set means to JUST delete the local nexthop from this
412 * route. Leave the route itself in place.
413 * TBD add return code reporting of success/failure
415 if (!bpi
|| !bpi
->extra
416 || !bpi
->extra
->vnc
.export
.local_nexthops
) {
420 vnc_zlog_debug_verbose(
421 "%s: lnh list already empty at prefix %s",
429 struct listnode
*node
;
430 struct rfapi_nexthop
*pLnh
= NULL
;
432 for (ALL_LIST_ELEMENTS_RO(bpi
->extra
->vnc
.export
.local_nexthops
,
435 if (prefix_same(&pLnh
->addr
, &lnh
->addr
)) {
441 listnode_delete(bpi
->extra
->vnc
.export
.local_nexthops
,
444 /* silly rabbit, listnode_delete doesn't invoke
445 * list->del on data */
446 rfapi_nexthop_free(pLnh
);
448 vnc_zlog_debug_verbose("%s: desired lnh not found %s",
455 * loop back to import tables
456 * Do this before removing from BGP RIB because rfapiProcessWithdraw
459 rfapiProcessWithdraw(peer
, rfd
, p
, prd
, NULL
, afi
, safi
, type
, kill
);
462 prefix2str(p
, buf
, sizeof(buf
));
463 vnc_zlog_debug_verbose(
464 "%s: Found route (safi=%d) to delete at prefix %s",
465 __func__
, safi
, buf
);
467 if (safi
== SAFI_MPLS_VPN
) {
468 struct bgp_node
*prn
= NULL
;
469 struct bgp_table
*table
= NULL
;
471 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
472 (struct prefix
*)prd
);
473 table
= bgp_node_get_bgp_table_info(prn
);
475 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
476 bgp
, prd
, table
, p
, bpi
);
477 bgp_unlock_node(prn
);
481 * Delete local_nexthops list
483 if (bpi
->extra
&& bpi
->extra
->vnc
.export
.local_nexthops
)
484 list_delete(&bpi
->extra
->vnc
.export
.local_nexthops
);
486 bgp_aggregate_decrement(bgp
, p
, bpi
, afi
, safi
);
487 bgp_path_info_delete(bn
, bpi
);
488 bgp_process(bgp
, bn
, afi
, safi
);
490 vnc_zlog_debug_verbose(
491 "%s: Couldn't find route (safi=%d) at prefix %s",
492 __func__
, safi
, buf
);
498 struct rfapi_nexthop
*rfapi_nexthop_new(struct rfapi_nexthop
*copyme
)
500 struct rfapi_nexthop
*new =
501 XCALLOC(MTYPE_RFAPI_NEXTHOP
, sizeof(struct rfapi_nexthop
));
507 void rfapi_nexthop_free(void *p
)
509 struct rfapi_nexthop
*goner
= p
;
510 XFREE(MTYPE_RFAPI_NEXTHOP
, goner
);
513 struct rfapi_vn_option
*rfapi_vn_options_dup(struct rfapi_vn_option
*existing
)
515 struct rfapi_vn_option
*p
;
516 struct rfapi_vn_option
*head
= NULL
;
517 struct rfapi_vn_option
*tail
= NULL
;
519 for (p
= existing
; p
; p
= p
->next
) {
520 struct rfapi_vn_option
*new;
522 new = XCALLOC(MTYPE_RFAPI_VN_OPTION
,
523 sizeof(struct rfapi_vn_option
));
536 void rfapi_un_options_free(struct rfapi_un_option
*p
)
538 struct rfapi_un_option
*next
;
542 XFREE(MTYPE_RFAPI_UN_OPTION
, p
);
547 void rfapi_vn_options_free(struct rfapi_vn_option
*p
)
549 struct rfapi_vn_option
*next
;
553 XFREE(MTYPE_RFAPI_VN_OPTION
, p
);
558 /* Based on bgp_redistribute_add() */
559 void add_vnc_route(struct rfapi_descriptor
*rfd
, /* cookie, VPN UN addr, peer */
560 struct bgp
*bgp
, int safi
, struct prefix
*p
,
561 struct prefix_rd
*prd
, struct rfapi_ip_addr
*nexthop
,
562 uint32_t *local_pref
,
563 uint32_t *lifetime
, /* NULL => dont send lifetime */
564 struct bgp_tea_options
*rfp_options
,
565 struct rfapi_un_option
*options_un
,
566 struct rfapi_vn_option
*options_vn
,
567 struct ecommunity
*rt_export_list
, /* Copied, not consumed */
568 uint32_t *med
, /* NULL => don't set med */
569 uint32_t *label
, /* low order 3 bytes */
570 uint8_t type
, uint8_t sub_type
, /* RFP, NORMAL or REDIST */
573 afi_t afi
; /* of the VN address */
574 struct bgp_path_info
*new;
575 struct bgp_path_info
*bpi
;
578 struct attr attr
= {0};
579 struct attr
*new_attr
;
582 struct bgp_attr_encap_subtlv
*encaptlv
;
583 char buf
[PREFIX_STRLEN
];
584 char buf2
[RD_ADDRSTRLEN
];
586 struct prefix pfx_buf
;
589 struct rfapi_nexthop
*lnh
= NULL
; /* local nexthop */
590 struct rfapi_vn_option
*vo
;
591 struct rfapi_l2address_option
*l2o
= NULL
;
592 struct rfapi_ip_addr
*un_addr
= &rfd
->un_addr
;
594 bgp_encap_types TunnelType
= BGP_ENCAP_TYPE_RESERVED
;
595 struct bgp_redist
*red
;
597 if (safi
== SAFI_ENCAP
598 && !(bgp
->rfapi_cfg
->flags
& BGP_VNC_CONFIG_ADV_UN_METHOD_ENCAP
)) {
601 * Encap mode not enabled. UN addresses will be communicated
602 * via VNC Tunnel subtlv instead.
604 vnc_zlog_debug_verbose(
605 "%s: encap mode not enabled, not adding SAFI_ENCAP route",
611 if ((safi
== SAFI_MPLS_VPN
) && (flags
& RFAPI_AHR_SET_PFX_TO_NEXTHOP
))
614 if (rfapiRaddr2Qprefix (nexthop
, &pfx_buf
))
616 vnc_zlog_debug_verbose
617 ("%s: can't set pfx to vn addr, not adding SAFI_MPLS_VPN route",
624 for (vo
= options_vn
; vo
; vo
= vo
->next
) {
625 if (RFAPI_VN_OPTION_TYPE_L2ADDR
== vo
->type
) {
627 if (RFAPI_0_ETHERADDR(&l2o
->macaddr
))
628 l2o
= NULL
; /* not MAC resolution */
630 if (RFAPI_VN_OPTION_TYPE_LOCAL_NEXTHOP
== vo
->type
) {
631 lnh
= &vo
->v
.local_nexthop
;
638 label_val
= MPLS_LABEL_IMPLICIT_NULL
;
640 prefix_rd2str(prd
, buf2
, sizeof(buf2
));
642 afi
= family2afi(p
->family
);
643 assert(afi
== AFI_IP
|| afi
== AFI_IP6
);
645 vnc_zlog_debug_verbose("%s: afi=%s, safi=%s", __func__
, afi2str(afi
),
648 /* Make default attribute. Produces already-interned attr.aspath */
649 /* Cripes, the memory management of attributes is byzantine */
651 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
656 * extra: dynamically allocated, owned by attr
657 * aspath: points to interned hash from aspath hash table
662 * Route-specific un_options get added to the VPN SAFI
663 * advertisement tunnel encap attribute. (the per-NVE
664 * "default" un_options are put into the 1-per-NVE ENCAP
665 * SAFI advertisement). The VPN SAFI also gets the
666 * default un_options if there are no route-specific options.
669 struct rfapi_un_option
*uo
;
671 for (uo
= options_un
; uo
; uo
= uo
->next
) {
672 if (RFAPI_UN_OPTION_TYPE_TUNNELTYPE
== uo
->type
) {
673 TunnelType
= rfapi_tunneltype_option_to_tlv(
674 bgp
, un_addr
, &uo
->v
.tunnel
, &attr
,
681 * These are the NVE-specific "default" un_options which are
682 * put into the 1-per-NVE ENCAP advertisement.
684 if (rfd
->default_tunneltype_option
.type
) {
685 TunnelType
= rfapi_tunneltype_option_to_tlv(
686 bgp
, un_addr
, &rfd
->default_tunneltype_option
,
688 } else /* create default for local addse */
689 if (type
== ZEBRA_ROUTE_BGP
690 && sub_type
== BGP_ROUTE_RFP
)
691 TunnelType
= rfapi_tunneltype_option_to_tlv(
692 bgp
, un_addr
, NULL
, &attr
, l2o
!= NULL
);
695 if (TunnelType
== BGP_ENCAP_TYPE_MPLS
) {
696 if (safi
== SAFI_ENCAP
) {
697 /* Encap SAFI not used with MPLS */
698 vnc_zlog_debug_verbose(
699 "%s: mpls tunnel type, encap safi omitted",
701 aspath_unintern(&attr
.aspath
); /* Unintern original. */
707 attr
.local_pref
= *local_pref
;
708 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
713 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
716 /* override default weight assigned by bgp_attr_default_set() */
717 attr
.weight
= rfd
->peer
? rfd
->peer
->weight
[afi
][safi
] : 0;
720 * NB: ticket 81: do not reset attr.aspath here because it would
721 * cause iBGP peers to drop route
725 * Set originator ID for routes imported from BGP directly.
726 * These routes could be synthetic, and therefore could
727 * reuse the peer pointers of the routes they are derived
728 * from. Setting the originator ID to "us" prevents the
729 * wrong originator ID from being sent when this route is
730 * sent from a route reflector.
732 if (type
== ZEBRA_ROUTE_BGP_DIRECT
733 || type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
) {
734 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
);
735 attr
.originator_id
= bgp
->router_id
;
739 /* Set up vnc attribute (sub-tlv for Prefix Lifetime) */
740 if (lifetime
&& *lifetime
!= RFAPI_INFINITE_LIFETIME
) {
743 encaptlv
= XCALLOC(MTYPE_ENCAP_TLV
,
744 sizeof(struct bgp_attr_encap_subtlv
) + 4);
747 BGP_VNC_SUBTLV_TYPE_LIFETIME
; /* prefix lifetime */
748 encaptlv
->length
= 4;
749 lt
= htonl(*lifetime
);
750 memcpy(encaptlv
->value
, <
, 4);
751 attr
.vnc_subtlvs
= encaptlv
;
752 vnc_zlog_debug_verbose(
753 "%s: set Encap Attr Prefix Lifetime to %d", __func__
,
757 /* add rfp options to vnc attr */
760 if (flags
& RFAPI_AHR_RFPOPT_IS_VNCTLV
) {
763 * this flag means we're passing a pointer to an
764 * existing encap tlv chain which we should copy.
765 * It's a hack to avoid adding yet another argument
768 encaptlv
= encap_tlv_dup(
769 (struct bgp_attr_encap_subtlv
*)rfp_options
);
770 if (attr
.vnc_subtlvs
) {
771 attr
.vnc_subtlvs
->next
= encaptlv
;
773 attr
.vnc_subtlvs
= encaptlv
;
777 struct bgp_tea_options
*hop
;
778 /* XXX max of one tlv present so far from above code */
779 struct bgp_attr_encap_subtlv
*tail
= attr
.vnc_subtlvs
;
781 for (hop
= rfp_options
; hop
; hop
= hop
->next
) {
788 sizeof(struct bgp_attr_encap_subtlv
) + 2
792 BGP_VNC_SUBTLV_TYPE_RFPOPTION
; /* RFP
795 encaptlv
->length
= 2 + hop
->length
;
796 *((uint8_t *)(encaptlv
->value
) + 0) = hop
->type
;
797 *((uint8_t *)(encaptlv
->value
) + 1) =
799 memcpy(((uint8_t *)encaptlv
->value
) + 2,
800 hop
->value
, hop
->length
);
803 * add to end of subtlv chain
806 tail
->next
= encaptlv
;
808 attr
.vnc_subtlvs
= encaptlv
;
818 * extra: dynamically allocated, owned by attr
819 * vnc_subtlvs: dynamic chain, length 1
820 * aspath: points to interned hash from aspath hash table
824 attr
.ecommunity
= ecommunity_new();
825 assert(attr
.ecommunity
);
827 if (TunnelType
!= BGP_ENCAP_TYPE_MPLS
828 && TunnelType
!= BGP_ENCAP_TYPE_RESERVED
) {
830 * Add BGP Encapsulation Extended Community. Format described in
831 * section 4.5 of RFC 5512.
832 * Always include when not MPLS type, to disambiguate this case.
834 struct ecommunity_val beec
;
836 memset(&beec
, 0, sizeof(beec
));
837 beec
.val
[0] = ECOMMUNITY_ENCODE_OPAQUE
;
838 beec
.val
[1] = ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP
;
839 beec
.val
[6] = ((TunnelType
) >> 8) & 0xff;
840 beec
.val
[7] = (TunnelType
)&0xff;
841 ecommunity_add_val(attr
.ecommunity
, &beec
);
845 * Add extended community attributes to match rt export list
847 if (rt_export_list
) {
849 ecommunity_merge(attr
.ecommunity
, rt_export_list
);
852 if (attr
.ecommunity
->size
) {
853 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
855 ecommunity_free(&attr
.ecommunity
);
856 attr
.ecommunity
= NULL
;
858 vnc_zlog_debug_verbose("%s: attr.ecommunity=%p", __func__
,
865 * extra: dynamically allocated, owned by attr
866 * vnc_subtlvs: dynamic chain, length 1
867 * ecommunity: dynamic 2-part
868 * aspath: points to interned hash from aspath hash table
871 /* stuff nexthop in attr_extra; which field depends on IPv4 or IPv6 */
872 switch (nexthop
->addr_family
) {
875 * set this field to prevent bgp_route.c code from setting
876 * mp_nexthop_global_in to self
878 attr
.nexthop
.s_addr
= nexthop
->addr
.v4
.s_addr
;
880 attr
.mp_nexthop_global_in
= nexthop
->addr
.v4
;
881 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
;
885 attr
.mp_nexthop_global
= nexthop
->addr
.v6
;
886 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
894 prefix2str(p
, buf
, sizeof(buf
));
900 * extra: dynamically allocated, owned by attr
901 * vnc_subtlvs: dynamic chain, length 1
902 * ecommunity: dynamic 2-part
903 * aspath: points to interned hash from aspath hash table
906 red
= bgp_redist_lookup(bgp
, afi
, type
, 0);
908 if (red
&& red
->redist_metric_flag
) {
909 attr
.med
= red
->redist_metric
;
910 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
913 bn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
916 * bgp_attr_intern creates a new reference to a cached
917 * attribute, but leaves the following bits of trash:
919 * - old attr->extra (free via bgp_attr_extra_free(attr))
921 * Note that it frees the original attr->extra->ecommunity
922 * but leaves the new attribute pointing to the ORIGINAL
923 * vnc options (which therefore we needn't free from the
926 new_attr
= bgp_attr_intern(&attr
);
928 aspath_unintern(&attr
.aspath
); /* Unintern original. */
934 * extra: dynamically allocated, owned by attr
935 * vnc_subtlvs: dynamic chain, length 1
936 * ecommunity: POINTS TO INTERNED ecom, THIS REF NOT COUNTED
938 * new_attr: an attr that is part of the hash table, distinct
939 * from attr which is static.
940 * extra: dynamically allocated, owned by new_attr (in hash table)
941 * vnc_subtlvs: POINTS TO SAME dynamic chain AS attr
942 * ecommunity: POINTS TO interned/refcounted dynamic 2-part AS attr
943 * aspath: POINTS TO interned/refcounted hashed block
945 for (bpi
= bgp_node_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
) {
946 /* probably only need to check
947 * bpi->extra->vnc.export.rfapi_handle */
948 if (bpi
->peer
== rfd
->peer
&& bpi
->type
== type
949 && bpi
->sub_type
== sub_type
&& bpi
->extra
950 && bpi
->extra
->vnc
.export
.rfapi_handle
== (void *)rfd
) {
959 * Adding new local_nexthop, which does not by itself change
960 * what is advertised via BGP
963 if (!bpi
->extra
->vnc
.export
.local_nexthops
) {
964 /* TBD make arrangements to free when needed */
965 bpi
->extra
->vnc
.export
.local_nexthops
=
967 bpi
->extra
->vnc
.export
.local_nexthops
->del
=
974 struct listnode
*node
;
975 struct rfapi_nexthop
*pLnh
= NULL
;
977 for (ALL_LIST_ELEMENTS_RO(
978 bpi
->extra
->vnc
.export
.local_nexthops
,
981 if (prefix_same(&pLnh
->addr
, &lnh
->addr
)) {
987 * Not present, add new one
990 pLnh
= rfapi_nexthop_new(lnh
);
992 bpi
->extra
->vnc
.export
.local_nexthops
,
997 if (attrhash_cmp(bpi
->attr
, new_attr
)
998 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
999 bgp_attr_unintern(&new_attr
);
1000 bgp_unlock_node(bn
);
1003 "%s: Found route (safi=%d) at prefix %s, no change",
1004 __func__
, safi
, buf
);
1008 /* The attribute is changed. */
1009 bgp_path_info_set_flag(bn
, bpi
, BGP_PATH_ATTR_CHANGED
);
1011 if (safi
== SAFI_MPLS_VPN
) {
1012 struct bgp_node
*prn
= NULL
;
1013 struct bgp_table
*table
= NULL
;
1015 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
1016 (struct prefix
*)prd
);
1017 table
= bgp_node_get_bgp_table_info(prn
);
1019 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
1020 bgp
, prd
, table
, p
, bpi
);
1021 bgp_unlock_node(prn
);
1024 /* Rewrite BGP route information. */
1025 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
1026 bgp_path_info_restore(bn
, bpi
);
1028 bgp_aggregate_decrement(bgp
, p
, bpi
, afi
, safi
);
1029 bgp_attr_unintern(&bpi
->attr
);
1030 bpi
->attr
= new_attr
;
1031 bpi
->uptime
= bgp_clock();
1034 if (safi
== SAFI_MPLS_VPN
) {
1035 struct bgp_node
*prn
= NULL
;
1036 struct bgp_table
*table
= NULL
;
1038 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
1039 (struct prefix
*)prd
);
1040 table
= bgp_node_get_bgp_table_info(prn
);
1042 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
1043 bgp
, prd
, table
, p
, bpi
);
1044 bgp_unlock_node(prn
);
1047 /* Process change. */
1048 bgp_aggregate_increment(bgp
, p
, bpi
, afi
, safi
);
1049 bgp_process(bgp
, bn
, afi
, safi
);
1050 bgp_unlock_node(bn
);
1053 "%s: Found route (safi=%d) at prefix %s, changed attr",
1054 __func__
, safi
, buf
);
1060 new = info_make(type
, sub_type
, 0, rfd
->peer
, new_attr
, NULL
);
1061 SET_FLAG(new->flags
, BGP_PATH_VALID
);
1063 /* save backref to rfapi handle */
1064 assert(bgp_path_info_extra_get(new));
1065 new->extra
->vnc
.export
.rfapi_handle
= (void *)rfd
;
1066 encode_label(label_val
, &new->extra
->label
[0]);
1070 if (VNC_DEBUG(VERBOSE
)) {
1071 vnc_zlog_debug_verbose("%s: printing BPI", __func__
);
1072 rfapiPrintBi(NULL
, new);
1075 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
1076 bgp_path_info_add(bn
, new);
1078 if (safi
== SAFI_MPLS_VPN
) {
1079 struct bgp_node
*prn
= NULL
;
1080 struct bgp_table
*table
= NULL
;
1082 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
1083 table
= bgp_node_get_bgp_table_info(prn
);
1085 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
1086 bgp
, prd
, table
, p
, new);
1087 bgp_unlock_node(prn
);
1088 encode_label(label_val
, &bn
->local_label
);
1091 bgp_unlock_node(bn
);
1092 bgp_process(bgp
, bn
, afi
, safi
);
1095 "%s: Added route (safi=%s) at prefix %s (bn=%p, prd=%s)",
1096 __func__
, safi2str(safi
), buf
, bn
, buf2
);
1099 /* Loop back to import tables */
1100 rfapiProcessUpdate(rfd
->peer
, rfd
, p
, prd
, new_attr
, afi
, safi
, type
,
1101 sub_type
, &label_val
);
1102 vnc_zlog_debug_verbose("%s: looped back import route (safi=%d)",
1106 uint32_t rfp_cost_to_localpref(uint8_t cost
)
1111 static void rfapiTunnelRouteAnnounce(struct bgp
*bgp
,
1112 struct rfapi_descriptor
*rfd
,
1113 uint32_t *pLifetime
)
1115 struct prefix_rd prd
;
1116 struct prefix pfx_vn
;
1118 uint32_t local_pref
= rfp_cost_to_localpref(0);
1120 rc
= rfapiRaddr2Qprefix(&(rfd
->vn_addr
), &pfx_vn
);
1124 * Construct route distinguisher = 0
1126 memset(&prd
, 0, sizeof(prd
));
1127 prd
.family
= AF_UNSPEC
;
1130 add_vnc_route(rfd
, /* rfapi descr, for export list & backref */
1131 bgp
, /* which bgp instance */
1132 SAFI_ENCAP
, /* which SAFI */
1133 &pfx_vn
, /* prefix to advertise */
1134 &prd
, /* route distinguisher to use */
1135 &rfd
->un_addr
, /* nexthop */
1137 pLifetime
, /* max lifetime of child VPN routes */
1138 NULL
, /* no rfp options for ENCAP safi */
1139 NULL
, /* rfp un options */
1140 NULL
, /* rfp vn options */
1141 rfd
->rt_export_list
, NULL
, /* med */
1142 NULL
, /* label: default */
1143 ZEBRA_ROUTE_BGP
, BGP_ROUTE_RFP
, 0);
1147 /***********************************************************************
1148 * RFP processing behavior configuration
1149 ***********************************************************************/
1151 /*------------------------------------------
1152 * rfapi_rfp_set_configuration
1154 * This is used to change rfapi's processing behavior based on
1158 * rfp_start_val value returned by rfp_start
1159 * rfapi_rfp_cfg Pointer to configuration structure
1166 * ENXIO Unabled to locate configured BGP/VNC
1167 --------------------------------------------*/
1168 int rfapi_rfp_set_configuration(void *rfp_start_val
, struct rfapi_rfp_cfg
*new)
1170 struct rfapi_rfp_cfg
*rcfg
;
1173 bgp
= rfapi_bgp_lookup_by_rfp(rfp_start_val
);
1175 if (!new || !bgp
|| !bgp
->rfapi_cfg
)
1178 rcfg
= &bgp
->rfapi_cfg
->rfp_cfg
;
1179 rcfg
->download_type
= new->download_type
;
1180 rcfg
->ftd_advertisement_interval
= new->ftd_advertisement_interval
;
1181 rcfg
->holddown_factor
= new->holddown_factor
;
1183 if (rcfg
->use_updated_response
!= new->use_updated_response
) {
1184 rcfg
->use_updated_response
= new->use_updated_response
;
1185 if (rcfg
->use_updated_response
)
1186 rfapiMonitorCallbacksOn(bgp
);
1188 rfapiMonitorCallbacksOff(bgp
);
1190 if (rcfg
->use_removes
!= new->use_removes
) {
1191 rcfg
->use_removes
= new->use_removes
;
1192 if (rcfg
->use_removes
)
1193 rfapiMonitorResponseRemovalOn(bgp
);
1195 rfapiMonitorResponseRemovalOff(bgp
);
1200 /*------------------------------------------
1201 * rfapi_rfp_set_cb_methods
1203 * Change registered callback functions for asynchronous notifications
1204 * from RFAPI to the RFP client.
1207 * rfp_start_val value returned by rfp_start
1208 * methods Pointer to struct rfapi_rfp_cb_methods containing
1209 * pointers to callback methods as described above
1213 * ENXIO BGP or VNC not configured
1214 *------------------------------------------*/
1215 int rfapi_rfp_set_cb_methods(void *rfp_start_val
,
1216 struct rfapi_rfp_cb_methods
*methods
)
1221 bgp
= rfapi_bgp_lookup_by_rfp(rfp_start_val
);
1229 h
->rfp_methods
= *methods
;
1234 /***********************************************************************
1236 ***********************************************************************/
1238 * Caller must supply an already-allocated rfd with the "caller"
1239 * fields already set (vn_addr, un_addr, callback, cookie)
1240 * The advertised_prefixes[] array elements should be NULL to
1241 * have this function set them to newly-allocated radix trees.
1243 static int rfapi_open_inner(struct rfapi_descriptor
*rfd
, struct bgp
*bgp
,
1244 struct rfapi
*h
, struct rfapi_nve_group_cfg
*rfg
)
1248 if (h
->flags
& RFAPI_INCALLBACK
)
1252 * Fill in configured fields
1256 * If group's RD is specified as "auto", then fill in based
1257 * on NVE's VN address
1261 if (rfd
->rd
.family
== AF_UNIX
) {
1262 ret
= rfapi_set_autord_from_vn(&rfd
->rd
, &rfd
->vn_addr
);
1266 rfd
->rt_export_list
= (rfg
->rt_export_list
)
1267 ? ecommunity_dup(rfg
->rt_export_list
)
1269 rfd
->response_lifetime
= rfg
->response_lifetime
;
1273 * Fill in BGP peer structure
1275 rfd
->peer
= peer_new(bgp
);
1276 rfd
->peer
->status
= Established
; /* keep bgp core happy */
1277 bgp_sync_delete(rfd
->peer
); /* don't need these */
1280 * since this peer is not on the I/O thread, this lock is not strictly
1281 * necessary, but serves as a reminder to those who may meddle...
1283 frr_with_mutex(&rfd
->peer
->io_mtx
) {
1284 // we don't need any I/O related facilities
1285 if (rfd
->peer
->ibuf
)
1286 stream_fifo_free(rfd
->peer
->ibuf
);
1287 if (rfd
->peer
->obuf
)
1288 stream_fifo_free(rfd
->peer
->obuf
);
1290 if (rfd
->peer
->ibuf_work
)
1291 ringbuf_del(rfd
->peer
->ibuf_work
);
1292 if (rfd
->peer
->obuf_work
)
1293 stream_free(rfd
->peer
->obuf_work
);
1295 rfd
->peer
->ibuf
= NULL
;
1296 rfd
->peer
->obuf
= NULL
;
1297 rfd
->peer
->obuf_work
= NULL
;
1298 rfd
->peer
->ibuf_work
= NULL
;
1301 { /* base code assumes have valid host pointer */
1305 if (rfd
->vn_addr
.addr_family
== AF_INET
) {
1306 inet_ntop(AF_INET
, &rfd
->vn_addr
.addr
.v4
, buf
, BUFSIZ
);
1307 } else if (rfd
->vn_addr
.addr_family
== AF_INET6
) {
1308 inet_ntop(AF_INET6
, &rfd
->vn_addr
.addr
.v6
, buf
, BUFSIZ
);
1310 rfd
->peer
->host
= XSTRDUP(MTYPE_BGP_PEER_HOST
, buf
);
1312 /* Mark peer as belonging to HD */
1313 SET_FLAG(rfd
->peer
->flags
, PEER_FLAG_IS_RFAPI_HD
);
1316 * Set min prefix lifetime to max value so it will get set
1317 * upon first rfapi_register()
1319 rfd
->min_prefix_lifetime
= UINT32_MAX
;
1322 * Allocate response tables if needed
1324 #define RFD_RTINIT_AFI(rh, ary, afi) \
1327 ary[afi] = agg_table_init(); \
1328 agg_set_table_info(ary[afi], rh); \
1332 #define RFD_RTINIT(rh, ary) \
1334 RFD_RTINIT_AFI(rh, ary, AFI_IP); \
1335 RFD_RTINIT_AFI(rh, ary, AFI_IP6); \
1336 RFD_RTINIT_AFI(rh, ary, AFI_L2VPN); \
1339 RFD_RTINIT(rfd
, rfd
->rib
);
1340 RFD_RTINIT(rfd
, rfd
->rib_pending
);
1341 RFD_RTINIT(rfd
, rfd
->rsp_times
);
1344 * Link to Import Table
1346 rfd
->import_table
= rfg
->rfapi_import_table
;
1347 rfd
->import_table
->refcount
+= 1;
1349 rfapiApInit(&rfd
->advertised
);
1352 * add this NVE descriptor to the list of NVEs in the NVE group
1355 rfg
->nves
= list_new();
1357 listnode_add(rfg
->nves
, rfd
);
1359 vnc_direct_bgp_add_nve(bgp
, rfd
);
1360 vnc_zebra_add_nve(bgp
, rfd
);
1365 /* moved from rfapi_register */
1366 int rfapi_init_and_open(struct bgp
*bgp
, struct rfapi_descriptor
*rfd
,
1367 struct rfapi_nve_group_cfg
*rfg
)
1369 struct rfapi
*h
= bgp
->rfapi
;
1370 char buf_vn
[BUFSIZ
];
1371 char buf_un
[BUFSIZ
];
1372 afi_t afi_vn
, afi_un
;
1373 struct prefix pfx_un
;
1374 struct agg_node
*rn
;
1377 rfapi_time(&rfd
->open_time
);
1379 if (rfg
->type
== RFAPI_GROUP_CFG_VRF
)
1380 SET_FLAG(rfd
->flags
, RFAPI_HD_FLAG_IS_VRF
);
1382 rfapiRfapiIpAddr2Str(&rfd
->vn_addr
, buf_vn
, BUFSIZ
);
1383 rfapiRfapiIpAddr2Str(&rfd
->un_addr
, buf_un
, BUFSIZ
);
1385 vnc_zlog_debug_verbose("%s: new RFD with VN=%s UN=%s cookie=%p",
1386 __func__
, buf_vn
, buf_un
, rfd
->cookie
);
1388 if (rfg
->type
!= RFAPI_GROUP_CFG_VRF
) /* unclear if needed for VRF */
1390 listnode_add(&h
->descriptors
, rfd
);
1391 if (h
->descriptors
.count
> h
->stat
.max_descriptors
) {
1392 h
->stat
.max_descriptors
= h
->descriptors
.count
;
1396 * attach to UN radix tree
1398 afi_vn
= family2afi(rfd
->vn_addr
.addr_family
);
1399 afi_un
= family2afi(rfd
->un_addr
.addr_family
);
1400 assert(afi_vn
&& afi_un
);
1401 assert(!rfapiRaddr2Qprefix(&rfd
->un_addr
, &pfx_un
));
1403 rn
= agg_node_get(h
->un
[afi_un
], &pfx_un
);
1405 rfd
->next
= rn
->info
;
1409 return rfapi_open_inner(rfd
, bgp
, h
, rfg
);
1412 struct rfapi_vn_option
*rfapiVnOptionsDup(struct rfapi_vn_option
*orig
)
1414 struct rfapi_vn_option
*head
= NULL
;
1415 struct rfapi_vn_option
*tail
= NULL
;
1416 struct rfapi_vn_option
*vo
= NULL
;
1418 for (vo
= orig
; vo
; vo
= vo
->next
) {
1419 struct rfapi_vn_option
*new;
1421 new = XCALLOC(MTYPE_RFAPI_VN_OPTION
,
1422 sizeof(struct rfapi_vn_option
));
1423 memcpy(new, vo
, sizeof(struct rfapi_vn_option
));
1435 struct rfapi_un_option
*rfapiUnOptionsDup(struct rfapi_un_option
*orig
)
1437 struct rfapi_un_option
*head
= NULL
;
1438 struct rfapi_un_option
*tail
= NULL
;
1439 struct rfapi_un_option
*uo
= NULL
;
1441 for (uo
= orig
; uo
; uo
= uo
->next
) {
1442 struct rfapi_un_option
*new;
1444 new = XCALLOC(MTYPE_RFAPI_UN_OPTION
,
1445 sizeof(struct rfapi_un_option
));
1446 memcpy(new, uo
, sizeof(struct rfapi_un_option
));
1458 struct bgp_tea_options
*rfapiOptionsDup(struct bgp_tea_options
*orig
)
1460 struct bgp_tea_options
*head
= NULL
;
1461 struct bgp_tea_options
*tail
= NULL
;
1462 struct bgp_tea_options
*hop
= NULL
;
1464 for (hop
= orig
; hop
; hop
= hop
->next
) {
1465 struct bgp_tea_options
*new;
1467 new = XCALLOC(MTYPE_BGP_TEA_OPTIONS
,
1468 sizeof(struct bgp_tea_options
));
1469 memcpy(new, hop
, sizeof(struct bgp_tea_options
));
1472 new->value
= XCALLOC(MTYPE_BGP_TEA_OPTIONS_VALUE
,
1474 memcpy(new->value
, hop
->value
, hop
->length
);
1485 void rfapiFreeBgpTeaOptionChain(struct bgp_tea_options
*p
)
1487 struct bgp_tea_options
*next
;
1493 XFREE(MTYPE_BGP_TEA_OPTIONS_VALUE
, p
->value
);
1496 XFREE(MTYPE_BGP_TEA_OPTIONS
, p
);
1502 void rfapiAdbFree(struct rfapi_adb
*adb
)
1504 XFREE(MTYPE_RFAPI_ADB
, adb
);
1508 rfapi_query_inner(void *handle
, struct rfapi_ip_addr
*target
,
1509 struct rfapi_l2address_option
*l2o
, /* may be NULL */
1510 struct rfapi_next_hop_entry
**ppNextHopEntry
)
1514 struct prefix p_original
;
1515 struct agg_node
*rn
;
1516 struct rfapi_descriptor
*rfd
= (struct rfapi_descriptor
*)handle
;
1517 struct bgp
*bgp
= rfd
->bgp
;
1518 struct rfapi_next_hop_entry
*pNHE
= NULL
;
1519 struct rfapi_ip_addr
*self_vn_addr
= NULL
;
1521 int use_eth_resolution
= 0;
1522 struct rfapi_next_hop_entry
*i_nhe
;
1526 vnc_zlog_debug_verbose("%s: No BGP instance, returning ENXIO",
1531 vnc_zlog_debug_verbose("%s: No RFAPI instance, returning ENXIO",
1535 if (bgp
->rfapi
->flags
& RFAPI_INCALLBACK
) {
1536 vnc_zlog_debug_verbose(
1537 "%s: Called during calback, returning EDEADLK",
1542 if (!is_valid_rfd(rfd
)) {
1543 vnc_zlog_debug_verbose("%s: invalid handle, returning EBADF",
1548 rfd
->rsp_counter
++; /* dedup: identify this generation */
1549 rfd
->rsp_time
= rfapi_time(NULL
); /* response content dedup */
1550 rfd
->ftd_last_allowed_time
=
1552 - bgp
->rfapi_cfg
->rfp_cfg
.ftd_advertisement_interval
;
1555 if (!memcmp(l2o
->macaddr
.octet
, rfapi_ethaddr0
.octet
,
1559 /* per t/c Paul/Lou 151022 */
1560 if (!eth_is_0
|| l2o
->logical_net_id
) {
1561 use_eth_resolution
= 1;
1566 *ppNextHopEntry
= NULL
;
1569 * Save original target in prefix form. In case of L2-based queries,
1570 * p_original will be modified to reflect the L2 target
1572 assert(!rfapiRaddr2Qprefix(target
, &p_original
));
1574 if (bgp
->rfapi_cfg
->rfp_cfg
.download_type
== RFAPI_RFP_DOWNLOAD_FULL
) {
1575 /* convert query to 0/0 when full-table download is enabled */
1576 memset((char *)&p
, 0, sizeof(p
));
1577 p
.family
= target
->addr_family
;
1583 char buf
[PREFIX_STRLEN
];
1586 prefix2str(&p
, buf
, sizeof(buf
));
1587 vnc_zlog_debug_verbose("%s(rfd=%p, target=%s, ppNextHop=%p)",
1588 __func__
, rfd
, buf
, ppNextHopEntry
);
1590 s
= ecommunity_ecom2str(rfd
->import_table
->rt_import_list
,
1591 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1592 vnc_zlog_debug_verbose(
1593 "%s rfd->import_table=%p, rfd->import_table->rt_import_list: %s",
1594 __func__
, rfd
->import_table
, s
);
1595 XFREE(MTYPE_ECOMMUNITY_STR
, s
);
1598 afi
= family2afi(p
.family
);
1601 if (CHECK_FLAG(bgp
->rfapi_cfg
->flags
,
1602 BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP
)) {
1603 self_vn_addr
= &rfd
->vn_addr
;
1606 if (use_eth_resolution
) {
1607 uint32_t logical_net_id
= l2o
->logical_net_id
;
1608 struct ecommunity
*l2com
;
1611 * fix up p_original to contain L2 address
1613 rfapiL2o2Qprefix(l2o
, &p_original
);
1615 l2com
= bgp_rfapi_get_ecommunity_by_lni_label(
1616 bgp
, 1, logical_net_id
, l2o
->label
);
1618 uint8_t *v
= l2com
->val
;
1619 logical_net_id
= (v
[5] << 16) + (v
[6] << 8) + (v
[7]);
1622 * Ethernet/L2-based lookup
1624 * Always returns IT node corresponding to route
1627 if (RFAPI_RFP_DOWNLOAD_FULL
1628 == bgp
->rfapi_cfg
->rfp_cfg
.download_type
) {
1632 rn
= rfapiMonitorEthAdd(
1633 bgp
, rfd
, (eth_is_0
? &rfapi_ethaddr0
: &l2o
->macaddr
),
1637 struct rfapi_ip_prefix rprefix
;
1639 memset(&rprefix
, 0, sizeof(rprefix
));
1640 rprefix
.prefix
.addr_family
= target
->addr_family
;
1641 if (target
->addr_family
== AF_INET
) {
1642 rprefix
.length
= 32;
1644 rprefix
.length
= 128;
1647 pNHE
= rfapiEthRouteTable2NextHopList(
1648 logical_net_id
, &rprefix
,
1649 rfd
->response_lifetime
, self_vn_addr
,
1650 rfd
->rib
[afi
], &p_original
);
1660 rn
= rfapiMonitorAdd(bgp
, rfd
, &p
);
1663 * If target address is 0, this request is special: means to
1664 * return ALL routes in the table
1666 * Monitors for All-Routes queries get put on a special list,
1667 * not in the VPN tree
1669 if (RFAPI_0_PREFIX(&p
)) {
1671 vnc_zlog_debug_verbose("%s: 0-prefix", __func__
);
1674 * Generate nexthop list for caller
1676 pNHE
= rfapiRouteTable2NextHopList(
1677 rfd
->import_table
->imported_vpn
[afi
],
1678 rfd
->response_lifetime
, self_vn_addr
,
1679 rfd
->rib
[afi
], &p_original
);
1684 agg_lock_node(rn
); /* so we can unlock below */
1687 * returns locked node. Don't unlock yet because the
1689 * might free it before we're done with it. This
1691 * could occur when rfapiMonitorGetAttachNode() returns
1693 * newly-created default node.
1695 rn
= rfapiMonitorGetAttachNode(rfd
, &p
);
1701 agg_unlock_node(rn
);
1702 vnc_zlog_debug_verbose(
1703 "%s: VPN route not found, returning ENOENT", __func__
);
1707 if (VNC_DEBUG(RFAPI_QUERY
)) {
1708 rfapiShowImportTable(NULL
, "query",
1709 rfd
->import_table
->imported_vpn
[afi
], 1);
1712 if (use_eth_resolution
) {
1714 struct rfapi_ip_prefix rprefix
;
1716 memset(&rprefix
, 0, sizeof(rprefix
));
1717 rprefix
.prefix
.addr_family
= target
->addr_family
;
1718 if (target
->addr_family
== AF_INET
) {
1719 rprefix
.length
= 32;
1721 rprefix
.length
= 128;
1724 pNHE
= rfapiEthRouteNode2NextHopList(
1725 rn
, &rprefix
, rfd
->response_lifetime
, self_vn_addr
,
1726 rfd
->rib
[afi
], &p_original
);
1731 * Generate answer to query
1733 pNHE
= rfapiRouteNode2NextHopList(rn
, rfd
->response_lifetime
,
1734 self_vn_addr
, rfd
->rib
[afi
],
1738 agg_unlock_node(rn
);
1741 if (ppNextHopEntry
) {
1742 /* only count if caller gets it */
1743 ++bgp
->rfapi
->response_immediate_count
;
1747 vnc_zlog_debug_verbose("%s: NO NHEs, returning ENOENT",
1753 * count nexthops for statistics
1755 for (i_nhe
= pNHE
; i_nhe
; i_nhe
= i_nhe
->next
) {
1756 ++rfd
->stat_count_nh_reachable
;
1759 if (ppNextHopEntry
) {
1760 *ppNextHopEntry
= pNHE
;
1762 rfapi_free_next_hop_list(pNHE
);
1765 vnc_zlog_debug_verbose("%s: success", __func__
);
1770 * support on-the-fly reassignment of an already-open nve to a new
1771 * nve-group in the event that its original nve-group is
1772 * administratively deleted.
1774 static int rfapi_open_rfd(struct rfapi_descriptor
*rfd
, struct bgp
*bgp
)
1776 struct prefix pfx_vn
;
1777 struct prefix pfx_un
;
1778 struct rfapi_nve_group_cfg
*rfg
;
1780 struct rfapi_cfg
*hc
;
1787 hc
= bgp
->rfapi_cfg
;
1791 rc
= rfapiRaddr2Qprefix(&rfd
->vn_addr
, &pfx_vn
);
1794 rc
= rfapiRaddr2Qprefix(&rfd
->un_addr
, &pfx_un
);
1798 * Find the matching nve group config block
1800 rfg
= bgp_rfapi_cfg_match_group(hc
, &pfx_vn
, &pfx_un
);
1806 * check nve group config block for required values
1808 if (!rfg
->rt_export_list
|| !rfg
->rfapi_import_table
) {
1813 rc
= rfapi_open_inner(rfd
, bgp
, h
, rfg
);
1819 * re-advertise registered routes, this time as part of new NVE-group
1821 rfapiApReadvertiseAll(bgp
, rfd
);
1824 * re-attach callbacks to import table
1826 if (!(bgp
->rfapi_cfg
->flags
& BGP_VNC_CONFIG_CALLBACK_DISABLE
)) {
1827 rfapiMonitorAttachImportHd(rfd
);
1833 /*------------------------------------------
1836 * This function initializes a NVE record and associates it with
1837 * the specified VN and underlay network addresses
1840 * rfp_start_val value returned by rfp_start
1841 * vn NVE virtual network address
1843 * un NVE underlay network address
1845 * default_options Default options to use on registrations.
1846 * For now only tunnel type is supported.
1847 * May be overridden per-prefix in rfapi_register().
1848 * Caller owns (rfapi_open() does not free)
1850 * response_cb Pointer to next hop list update callback function or
1851 * NULL when no callbacks are desired.
1853 * userdata Passed to subsequent response_cb invocations.
1856 * response_lifetime The length of time that responses sent to this
1859 * pHandle pointer to location to store rfapi handle. The
1860 * handle must be passed on subsequent rfapi_ calls.
1865 * EEXIST NVE with this {vn,un} already open
1866 * ENOENT No matching nve group config
1867 * ENOMSG Matched nve group config was incomplete
1868 * ENXIO BGP or VNC not configured
1869 * EAFNOSUPPORT Matched nve group specifies auto-assignment of RD,
1870 * but underlay network address is not IPv4
1871 * EDEADLK Called from within a callback procedure
1872 *------------------------------------------*/
1873 int rfapi_open(void *rfp_start_val
, struct rfapi_ip_addr
*vn
,
1874 struct rfapi_ip_addr
*un
,
1875 struct rfapi_un_option
*default_options
,
1876 uint32_t *response_lifetime
,
1877 void *userdata
, /* callback cookie */
1878 rfapi_handle
*pHandle
)
1882 struct rfapi_descriptor
*rfd
;
1883 struct rfapi_cfg
*hc
;
1884 struct rfapi_nve_group_cfg
*rfg
;
1886 struct prefix pfx_vn
;
1887 struct prefix pfx_un
;
1890 rfapi_handle hh
= NULL
;
1891 int reusing_provisional
= 0;
1894 char buf
[2][INET_ADDRSTRLEN
];
1895 vnc_zlog_debug_verbose(
1896 "%s: VN=%s UN=%s", __func__
,
1897 rfapiRfapiIpAddr2Str(vn
, buf
[0], INET_ADDRSTRLEN
),
1898 rfapiRfapiIpAddr2Str(un
, buf
[1], INET_ADDRSTRLEN
));
1904 bgp
= rfapi_bgp_lookup_by_rfp(rfp_start_val
);
1912 hc
= bgp
->rfapi_cfg
;
1916 if (h
->flags
& RFAPI_INCALLBACK
)
1919 rc
= rfapiRaddr2Qprefix(vn
, &pfx_vn
);
1922 rc
= rfapiRaddr2Qprefix(un
, &pfx_un
);
1926 * already have a descriptor with VN and UN?
1928 if (!rfapi_find_handle(bgp
, vn
, un
, &hh
)) {
1930 * we might have set up a handle for static routes before
1931 * this NVE was opened. In that case, reuse the handle
1934 if (!CHECK_FLAG(rfd
->flags
, RFAPI_HD_FLAG_PROVISIONAL
)) {
1939 * reuse provisional descriptor
1942 reusing_provisional
= 1;
1946 * Find the matching nve group config block
1948 rfg
= bgp_rfapi_cfg_match_group(hc
, &pfx_vn
, &pfx_un
);
1950 ++h
->stat
.count_unknown_nves
;
1952 char buf
[2][INET_ADDRSTRLEN
];
1953 zlog_notice("%s: no matching group VN=%s UN=%s",
1955 rfapiRfapiIpAddr2Str(vn
, buf
[0],
1957 rfapiRfapiIpAddr2Str(un
, buf
[1],
1964 * check nve group config block for required values
1966 if (!rfg
->rt_export_list
|| !rfg
->rfapi_import_table
) {
1968 ++h
->stat
.count_unknown_nves
;
1973 * If group config specifies auto-rd assignment, check that
1974 * VN address is IPv4|v6 so we don't fail in rfapi_open_inner().
1975 * Check here so we don't need to unwind memory allocations, &c.
1977 if ((rfg
->rd
.family
== AF_UNIX
) && (vn
->addr_family
!= AF_INET
)
1978 && (vn
->addr_family
!= AF_INET6
)) {
1979 return EAFNOSUPPORT
;
1984 * reusing provisional rfd
1988 rfd
= XCALLOC(MTYPE_RFAPI_DESC
,
1989 sizeof(struct rfapi_descriptor
));
1994 if (default_options
) {
1995 struct rfapi_un_option
*p
;
1997 for (p
= default_options
; p
; p
= p
->next
) {
1998 if ((RFAPI_UN_OPTION_TYPE_PROVISIONAL
== p
->type
)) {
1999 rfd
->flags
|= RFAPI_HD_FLAG_PROVISIONAL
;
2001 if ((RFAPI_UN_OPTION_TYPE_TUNNELTYPE
== p
->type
)) {
2002 rfd
->default_tunneltype_option
= p
->v
.tunnel
;
2008 * Fill in caller fields
2012 rfd
->cookie
= userdata
;
2014 if (!reusing_provisional
) {
2015 rc
= rfapi_init_and_open(bgp
, rfd
, rfg
);
2017 * This can fail only if the VN address is IPv6 and the group
2018 * specified auto-assignment of RDs, which only works for v4,
2019 * and the check above should catch it.
2021 * Another failure possibility is that we were called
2022 * during an rfapi callback. Also checked above.
2027 if (response_lifetime
)
2028 *response_lifetime
= rfd
->response_lifetime
;
2034 * For use with debug functions
2036 static int rfapi_set_response_cb(struct rfapi_descriptor
*rfd
,
2037 rfapi_response_cb_t
*response_cb
)
2039 if (!is_valid_rfd(rfd
))
2041 rfd
->response_cb
= response_cb
;
2048 * Does almost all the work of rfapi_close, except:
2049 * 1. preserves the descriptor (doesn't free it)
2050 * 2. preserves the prefix query list (i.e., rfd->mon list)
2051 * 3. preserves the advertised prefix list (rfd->advertised)
2052 * 4. preserves the rib and rib_pending tables
2054 * The purpose of organizing it this way is to support on-the-fly
2055 * reassignment of an already-open nve to a new nve-group in the
2056 * event that its original nve-group is administratively deleted.
2058 static int rfapi_close_inner(struct rfapi_descriptor
*rfd
, struct bgp
*bgp
)
2061 struct prefix pfx_vn
;
2062 struct prefix_rd prd
; /* currently always 0 for VN->UN */
2064 if (!is_valid_rfd(rfd
))
2067 rc
= rfapiRaddr2Qprefix(&rfd
->vn_addr
, &pfx_vn
);
2068 assert(!rc
); /* should never have bad AF in stored vn address */
2071 * update exported routes to reflect disappearance of this NVE as
2074 vnc_direct_bgp_del_nve(bgp
, rfd
);
2075 vnc_zebra_del_nve(bgp
, rfd
);
2078 * unlink this HD's monitors from import table
2080 rfapiMonitorDetachImportHd(rfd
);
2083 * Unlink from Import Table
2084 * NB rfd->import_table will be NULL if we are closing a stale
2087 if (rfd
->import_table
)
2088 rfapiImportTableRefDelByIt(bgp
, rfd
->import_table
);
2089 rfd
->import_table
= NULL
;
2092 * Construct route distinguisher
2094 memset(&prd
, 0, sizeof(prd
));
2096 prd
.family
= AF_UNSPEC
;
2102 del_vnc_route(rfd
, rfd
->peer
, bgp
, SAFI_ENCAP
,
2103 &pfx_vn
, /* prefix being advertised */
2104 &prd
, /* route distinguisher to use (0 for ENCAP) */
2105 ZEBRA_ROUTE_BGP
, BGP_ROUTE_RFP
, NULL
, 0); /* no kill */
2108 * Construct route distinguisher for VPN routes
2111 prd
.family
= AF_UNSPEC
;
2115 * find all VPN routes associated with this rfd and delete them, too
2117 rfapiApWithdrawAll(bgp
, rfd
);
2120 * remove this nve descriptor from the list of nves
2121 * associated with the nve group
2124 listnode_delete(rfd
->rfg
->nves
, rfd
);
2125 rfd
->rfg
= NULL
; /* XXX mark as orphaned/stale */
2128 if (rfd
->rt_export_list
)
2129 ecommunity_free(&rfd
->rt_export_list
);
2130 rfd
->rt_export_list
= NULL
;
2133 * free peer structure (possibly delayed until its
2134 * refcount reaches zero)
2137 vnc_zlog_debug_verbose("%s: calling peer_delete(%p), #%d",
2138 __func__
, rfd
->peer
, rfd
->peer
->lock
);
2139 peer_delete(rfd
->peer
);
2146 int rfapi_close(void *handle
)
2148 struct rfapi_descriptor
*rfd
= (struct rfapi_descriptor
*)handle
;
2150 struct agg_node
*node
;
2154 vnc_zlog_debug_verbose("%s: rfd=%p", __func__
, rfd
);
2156 #if RFAPI_WHO_IS_CALLING_ME
2157 #ifdef HAVE_GLIBC_BACKTRACE
2158 #define RFAPI_DEBUG_BACKTRACE_NENTRIES 5
2160 void *buf
[RFAPI_DEBUG_BACKTRACE_NENTRIES
];
2165 size
= backtrace(buf
, RFAPI_DEBUG_BACKTRACE_NENTRIES
);
2166 syms
= backtrace_symbols(buf
, size
);
2167 for (i
= 0; i
< size
&& i
< RFAPI_DEBUG_BACKTRACE_NENTRIES
;
2169 vnc_zlog_debug_verbose("backtrace[%2d]: %s", i
,
2185 if (!is_valid_rfd(rfd
))
2188 if (h
->flags
& RFAPI_INCALLBACK
) {
2190 * Queue these close requests for processing after callback
2193 if (!CHECK_FLAG(rfd
->flags
,
2194 RFAPI_HD_FLAG_CLOSING_ADMINISTRATIVELY
)) {
2195 work_queue_add(h
->deferred_close_q
, handle
);
2196 vnc_zlog_debug_verbose(
2197 "%s: added handle %p to deferred close queue",
2203 if (CHECK_FLAG(rfd
->flags
, RFAPI_HD_FLAG_CLOSING_ADMINISTRATIVELY
)) {
2205 vnc_zlog_debug_verbose("%s administrative close rfd=%p",
2208 if (h
&& h
->rfp_methods
.close_cb
) {
2209 vnc_zlog_debug_verbose(
2210 "%s calling close callback rfd=%p", __func__
,
2214 * call the callback fairly early so that it can still
2218 * NB RFAPI_INCALLBACK is tested above, so if we reach
2220 * we are not already in the context of a callback.
2222 h
->flags
|= RFAPI_INCALLBACK
;
2223 (*h
->rfp_methods
.close_cb
)(handle
, EIDRM
);
2224 h
->flags
&= ~RFAPI_INCALLBACK
;
2230 * Orphaned descriptors have already done this part, so do
2231 * only for non-orphaned descriptors.
2233 if ((rc
= rfapi_close_inner(rfd
, bgp
)))
2238 * Remove descriptor from UN index
2239 * (remove from chain at node)
2241 rc
= rfapi_find_node(bgp
, &rfd
->vn_addr
, &rfd
->un_addr
, &node
);
2243 struct rfapi_descriptor
*hh
;
2245 if (node
->info
== rfd
) {
2246 node
->info
= rfd
->next
;
2249 for (hh
= node
->info
; hh
; hh
= hh
->next
) {
2250 if (hh
->next
== rfd
) {
2251 hh
->next
= rfd
->next
;
2256 agg_unlock_node(node
);
2260 * remove from descriptor list
2262 listnode_delete(&h
->descriptors
, rfd
);
2265 * Delete monitor list items and free monitor structures
2267 (void)rfapiMonitorDelHd(rfd
);
2270 * release advertised prefix data
2272 rfapiApRelease(&rfd
->advertised
);
2275 * Release RFP callback RIB
2282 memset(rfd
, 0, sizeof(struct rfapi_descriptor
));
2283 XFREE(MTYPE_RFAPI_DESC
, rfd
);
2289 * Reopen a nve descriptor. If the descriptor's NVE-group
2290 * does not exist (e.g., if it has been administratively removed),
2291 * reassignment to a new NVE-group is attempted.
2293 * If NVE-group reassignment fails, the descriptor becomes "stale"
2294 * (rfd->rfg == NULL implies "stale:). The only permissible API operation
2295 * on a stale descriptor is rfapi_close(). Any other rfapi_* API operation
2296 * on the descriptor will return ESTALE.
2298 * Reopening a descriptor is a potentially expensive operation, because
2299 * it involves withdrawing any routes advertised by the NVE, withdrawing
2300 * the NVE's route queries, and then re-adding them all after a new
2301 * NVE-group is assigned. There are also possible route-export affects
2302 * caused by deleting and then adding the NVE: advertised prefixes
2303 * and nexthop lists for exported routes can turn over.
2305 int rfapi_reopen(struct rfapi_descriptor
*rfd
, struct bgp
*bgp
)
2310 if ((rc
= rfapi_close_inner(rfd
, bgp
))) {
2313 if ((rc
= rfapi_open_rfd(rfd
, bgp
))) {
2317 assert(h
!= NULL
&& !CHECK_FLAG(h
->flags
, RFAPI_INCALLBACK
));
2319 if (CHECK_FLAG(rfd
->flags
,
2320 RFAPI_HD_FLAG_CLOSING_ADMINISTRATIVELY
)
2321 && h
&& h
->rfp_methods
.close_cb
) {
2324 * NB RFAPI_INCALLBACK is tested above, so if we reach
2326 * we are not already in the context of a callback.
2328 h
->flags
|= RFAPI_INCALLBACK
;
2329 (*h
->rfp_methods
.close_cb
)((rfapi_handle
)rfd
, ESTALE
);
2330 h
->flags
&= ~RFAPI_INCALLBACK
;
2337 /***********************************************************************
2339 ***********************************************************************/
2341 * Announce reachability to this prefix via the NVE
2343 int rfapi_register(void *handle
, struct rfapi_ip_prefix
*prefix
,
2344 uint32_t lifetime
, /* host byte order */
2345 struct rfapi_un_option
*options_un
,
2346 struct rfapi_vn_option
*options_vn
,
2347 rfapi_register_action action
)
2349 struct rfapi_descriptor
*rfd
= (struct rfapi_descriptor
*)handle
;
2352 struct prefix
*pfx_ip
= NULL
;
2353 struct prefix_rd prd
;
2355 struct prefix pfx_mac_buf
;
2356 struct prefix
*pfx_mac
= NULL
;
2357 struct prefix pfx_vn_buf
;
2358 const char *action_str
= NULL
;
2359 uint32_t *label
= NULL
;
2360 struct rfapi_vn_option
*vo
;
2361 struct rfapi_l2address_option
*l2o
= NULL
;
2362 struct prefix_rd
*prd_override
= NULL
;
2365 case RFAPI_REGISTER_ADD
:
2368 case RFAPI_REGISTER_WITHDRAW
:
2369 action_str
= "withdraw";
2371 case RFAPI_REGISTER_KILL
:
2372 action_str
= "kill";
2380 * Inspect VN options
2382 for (vo
= options_vn
; vo
; vo
= vo
->next
) {
2383 if (RFAPI_VN_OPTION_TYPE_L2ADDR
== vo
->type
) {
2384 l2o
= &vo
->v
.l2addr
;
2386 if (RFAPI_VN_OPTION_TYPE_INTERNAL_RD
== vo
->type
) {
2387 prd_override
= &vo
->v
.internal_rd
;
2391 /*********************************************************************
2393 *********************************************************************/
2396 * set <p> based on <prefix>
2398 assert(!rfapiRprefix2Qprefix(prefix
, &p
));
2400 afi
= family2afi(prefix
->prefix
.addr_family
);
2405 char buf
[PREFIX_STRLEN
];
2407 prefix2str(&p
, buf
, sizeof(buf
));
2408 vnc_zlog_debug_verbose(
2409 "%s(rfd=%p, pfx=%s, lifetime=%d, opts_un=%p, opts_vn=%p, action=%s)",
2410 __func__
, rfd
, buf
, lifetime
, options_un
, options_vn
,
2415 * These tests come after the prefix conversion so that we can
2416 * print the prefix in a debug message before failing
2421 vnc_zlog_debug_verbose("%s: no BGP instance: returning ENXIO",
2426 vnc_zlog_debug_verbose("%s: no RFAPI instance: returning ENXIO",
2431 if (RFAPI_REGISTER_ADD
== action
) {
2432 ++bgp
->rfapi
->stat
.count_registrations_failed
;
2434 vnc_zlog_debug_verbose(
2435 "%s: rfd=%p, no RF GRP instance: returning ESTALE",
2440 if (bgp
->rfapi
->flags
& RFAPI_INCALLBACK
) {
2441 if (RFAPI_REGISTER_ADD
== action
) {
2442 ++bgp
->rfapi
->stat
.count_registrations_failed
;
2444 vnc_zlog_debug_verbose("%s: in callback: returning EDEADLK",
2449 if (!is_valid_rfd(rfd
)) {
2450 if (RFAPI_REGISTER_ADD
== action
) {
2451 ++bgp
->rfapi
->stat
.count_registrations_failed
;
2453 vnc_zlog_debug_verbose("%s: invalid handle: returning EBADF",
2459 * Is there a MAC address in this registration?
2461 if (l2o
&& !RFAPI_0_ETHERADDR(&l2o
->macaddr
)) {
2462 rfapiL2o2Qprefix(l2o
, &pfx_mac_buf
);
2463 pfx_mac
= &pfx_mac_buf
;
2467 * Is there an IP prefix in this registration?
2469 if (!(RFAPI_0_PREFIX(&p
) && RFAPI_HOST_PREFIX(&p
))) {
2473 vnc_zlog_debug_verbose(
2474 "%s: missing mac addr that is required for host 0 pfx",
2476 if (RFAPI_REGISTER_ADD
== action
) {
2477 ++bgp
->rfapi
->stat
.count_registrations_failed
;
2481 if (rfapiRaddr2Qprefix(&rfd
->vn_addr
, &pfx_vn_buf
)) {
2482 vnc_zlog_debug_verbose(
2483 "%s: handle has bad vn_addr: returning EBADF",
2485 if (RFAPI_REGISTER_ADD
== action
) {
2486 ++bgp
->rfapi
->stat
.count_registrations_failed
;
2492 if (RFAPI_REGISTER_ADD
== action
) {
2493 ++bgp
->rfapi
->stat
.count_registrations
;
2497 * Figure out if this registration is missing an IP address
2501 * In RFAPI, we use prefixes in family AF_LINK to store
2502 * the MAC addresses. These prefixes are used for the
2503 * list of advertised prefixes and in the RFAPI import
2506 * In BGP proper, we use the prefix matching the NVE's
2507 * VN address with a host prefix-length (i.e., 32 or 128).
2510 if (l2o
&& l2o
->logical_net_id
&& RFAPI_0_PREFIX(&p
)
2511 && RFAPI_HOST_PREFIX(&p
)) {
2513 rfapiL2o2Qprefix(l2o
, &pfx_mac_buf
);
2514 pfx_mac
= &pfx_mac_buf
;
2518 * Construct route distinguisher
2521 prd
= *prd_override
;
2523 memset(&prd
, 0, sizeof(prd
));
2525 prd
.family
= AF_UNSPEC
;
2527 encode_rd_type(RD_TYPE_VNC_ETH
, prd
.val
);
2528 if (l2o
->local_nve_id
2529 || !(rfd
->rfg
->flags
& RFAPI_RFG_L2RD
)) {
2531 * If Local NVE ID is specified in message, use
2533 * (if no local default configured, also use it
2536 prd
.val
[1] = l2o
->local_nve_id
;
2538 if (rfd
->rfg
->l2rd
) {
2540 * locally-configured literal value
2542 prd
.val
[1] = rfd
->rfg
->l2rd
;
2545 * 0 means auto:vn, which means use LSB
2548 if (rfd
->vn_addr
.addr_family
2551 *(((char *)&rfd
->vn_addr
2557 *(((char *)&rfd
->vn_addr
2564 memcpy(prd
.val
+ 2, pfx_mac
->u
.prefix_eth
.octet
, 6);
2567 prd
.family
= AF_UNSPEC
;
2573 if (action
== RFAPI_REGISTER_WITHDRAW
2574 || action
== RFAPI_REGISTER_KILL
) {
2579 * withdraw previous advertisement
2582 rfd
, rfd
->peer
, bgp
, SAFI_MPLS_VPN
,
2584 : &pfx_vn_buf
, /* prefix being advertised */
2585 &prd
, /* route distinguisher (0 for ENCAP) */
2586 ZEBRA_ROUTE_BGP
, BGP_ROUTE_RFP
, NULL
,
2587 action
== RFAPI_REGISTER_KILL
);
2589 if (0 == rfapiApDelete(bgp
, rfd
, &p
, pfx_mac
, &prd
,
2592 rfapiTunnelRouteAnnounce(
2593 bgp
, rfd
, &rfd
->max_prefix_lifetime
);
2599 uint32_t local_pref
;
2600 struct ecommunity
*rtlist
= NULL
;
2601 struct ecommunity_val ecom_value
;
2603 if (!rfapiApCount(rfd
)) {
2605 * make sure we advertise tunnel route upon adding the
2611 if (rfapiApAdd(bgp
, rfd
, &p
, pfx_mac
, &prd
, lifetime
,
2612 prefix
->cost
, l2o
)) {
2616 vnc_zlog_debug_verbose("%s: adv_tunnel = %d", __func__
,
2619 vnc_zlog_debug_verbose("%s: announcing tunnel route",
2621 rfapiTunnelRouteAnnounce(bgp
, rfd
,
2622 &rfd
->max_prefix_lifetime
);
2625 vnc_zlog_debug_verbose("%s: calling add_vnc_route", __func__
);
2627 local_pref
= rfp_cost_to_localpref(prefix
->cost
);
2629 if (l2o
&& l2o
->label
)
2630 label
= &l2o
->label
;
2633 struct ecommunity
*l2com
= NULL
;
2636 l2com
= bgp_rfapi_get_ecommunity_by_lni_label(
2637 bgp
, 1, l2o
->logical_net_id
, *label
);
2640 rtlist
= ecommunity_dup(l2com
);
2643 * If mac address is set, add an RT based on the
2646 memset((char *)&ecom_value
, 0,
2647 sizeof(ecom_value
));
2648 ecom_value
.val
[1] = ECOMMUNITY_ROUTE_TARGET
;
2650 (l2o
->logical_net_id
>> 16) & 0xff;
2652 (l2o
->logical_net_id
>> 8) & 0xff;
2654 (l2o
->logical_net_id
>> 0) & 0xff;
2655 rtlist
= ecommunity_new();
2656 ecommunity_add_val(rtlist
, &ecom_value
);
2660 uint16_t val
= l2o
->tag_id
;
2661 memset((char *)&ecom_value
, 0,
2662 sizeof(ecom_value
));
2663 ecom_value
.val
[1] = ECOMMUNITY_ROUTE_TARGET
;
2664 if (as
> BGP_AS_MAX
) {
2666 ECOMMUNITY_ENCODE_AS4
;
2667 ecom_value
.val
[2] = (as
>> 24) & 0xff;
2668 ecom_value
.val
[3] = (as
>> 16) & 0xff;
2669 ecom_value
.val
[4] = (as
>> 8) & 0xff;
2670 ecom_value
.val
[5] = as
& 0xff;
2673 ECOMMUNITY_ENCODE_AS
;
2674 ecom_value
.val
[2] = (as
>> 8) & 0xff;
2675 ecom_value
.val
[3] = as
& 0xff;
2677 ecom_value
.val
[6] = (val
>> 8) & 0xff;
2678 ecom_value
.val
[7] = val
& 0xff;
2680 rtlist
= ecommunity_new();
2681 ecommunity_add_val(rtlist
, &ecom_value
);
2686 * advertise prefix via tunnel endpoint
2689 rfd
, /* rfapi descr, for export list & backref */
2690 bgp
, /* which bgp instance */
2691 SAFI_MPLS_VPN
, /* which SAFI */
2693 : &pfx_vn_buf
), /* prefix being advertised */
2694 &prd
, /* route distinguisher to use (0 for ENCAP) */
2695 &rfd
->vn_addr
, /* nexthop */
2697 &lifetime
, /* prefix lifetime -> Tunnel Encap attr */
2698 NULL
, options_un
, /* rfapi un options */
2699 options_vn
, /* rfapi vn options */
2700 (rtlist
? rtlist
: rfd
->rt_export_list
), NULL
, /* med */
2701 label
, /* label: default */
2702 ZEBRA_ROUTE_BGP
, BGP_ROUTE_RFP
, 0);
2705 ecommunity_free(&rtlist
); /* sets rtlist = NULL */
2708 vnc_zlog_debug_verbose("%s: success", __func__
);
2712 int rfapi_query(void *handle
, struct rfapi_ip_addr
*target
,
2713 struct rfapi_l2address_option
*l2o
, /* may be NULL */
2714 struct rfapi_next_hop_entry
**ppNextHopEntry
)
2716 struct rfapi_descriptor
*rfd
= (struct rfapi_descriptor
*)handle
;
2717 struct bgp
*bgp
= rfd
->bgp
;
2720 assert(ppNextHopEntry
);
2721 *ppNextHopEntry
= NULL
;
2723 if (bgp
&& bgp
->rfapi
) {
2724 bgp
->rfapi
->stat
.count_queries
++;
2728 if (bgp
&& bgp
->rfapi
)
2729 ++bgp
->rfapi
->stat
.count_queries_failed
;
2733 if ((rc
= rfapi_query_inner(handle
, target
, l2o
, ppNextHopEntry
))) {
2734 if (bgp
&& bgp
->rfapi
)
2735 ++bgp
->rfapi
->stat
.count_queries_failed
;
2740 int rfapi_query_done(rfapi_handle handle
, struct rfapi_ip_addr
*target
)
2744 struct rfapi_descriptor
*rfd
= (struct rfapi_descriptor
*)handle
;
2745 struct bgp
*bgp
= rfd
->bgp
;
2751 rc
= rfapiRaddr2Qprefix(target
, &p
);
2754 if (!is_valid_rfd(rfd
))
2758 if (!bgp
|| !bgp
->rfapi
)
2761 if (bgp
->rfapi
->flags
& RFAPI_INCALLBACK
)
2764 rfapiMonitorDel(bgp
, rfd
, &p
);
2769 int rfapi_query_done_all(rfapi_handle handle
, int *count
)
2771 struct rfapi_descriptor
*rfd
= (struct rfapi_descriptor
*)handle
;
2772 struct bgp
*bgp
= rfd
->bgp
;
2779 if (!is_valid_rfd(rfd
))
2783 if (!bgp
|| !bgp
->rfapi
)
2786 if (bgp
->rfapi
->flags
& RFAPI_INCALLBACK
)
2789 num
= rfapiMonitorDelHd(rfd
);
2797 void rfapi_free_next_hop_list(struct rfapi_next_hop_entry
*list
)
2799 struct rfapi_next_hop_entry
*nh
;
2800 struct rfapi_next_hop_entry
*next
;
2802 for (nh
= list
; nh
; nh
= next
) {
2804 rfapi_un_options_free(nh
->un_options
);
2805 nh
->un_options
= NULL
;
2806 rfapi_vn_options_free(nh
->vn_options
);
2807 nh
->vn_options
= NULL
;
2808 XFREE(MTYPE_RFAPI_NEXTHOP
, nh
);
2813 * NULL handle => return total count across all nves
2815 uint32_t rfapi_monitor_count(void *handle
)
2817 struct bgp
*bgp
= bgp_get_default();
2821 struct rfapi_descriptor
*rfd
=
2822 (struct rfapi_descriptor
*)handle
;
2823 count
= rfd
->monitor_count
;
2826 if (!bgp
|| !bgp
->rfapi
)
2829 count
= bgp
->rfapi
->monitor_count
;
2835 /***********************************************************************
2837 ***********************************************************************/
2839 DEFUN (debug_rfapi_show_nves
,
2840 debug_rfapi_show_nves_cmd
,
2841 "debug rfapi-dev show nves",
2845 "NVE Information\n")
2847 rfapiPrintMatchingDescriptors(vty
, NULL
, NULL
);
2852 debug_rfapi_show_nves_vn_un
,
2853 debug_rfapi_show_nves_vn_un_cmd
,
2854 "debug rfapi-dev show nves <vn|un> <A.B.C.D|X:X::X:X>", /* prefix also ok */
2859 "Specify virtual network\n"
2860 "Specify underlay network interface\n"
2866 if (!str2prefix(argv
[5]->arg
, &pfx
)) {
2867 vty_out(vty
, "Malformed address \"%s\"\n", argv
[5]->arg
);
2868 return CMD_WARNING_CONFIG_FAILED
;
2870 if (pfx
.family
!= AF_INET
&& pfx
.family
!= AF_INET6
) {
2871 vty_out(vty
, "Invalid address \"%s\"\n", argv
[5]->arg
);
2872 return CMD_WARNING_CONFIG_FAILED
;
2875 if (argv
[4]->arg
[0] == 'u') {
2876 rfapiPrintMatchingDescriptors(vty
, NULL
, &pfx
);
2878 rfapiPrintMatchingDescriptors(vty
, &pfx
, NULL
);
2884 * Note: this function does not flush vty output, so if it is called
2885 * with a stream pointing to a vty, the user will have to type something
2886 * before the callback output shows up
2888 static void test_nexthops_callback(
2889 // struct rfapi_ip_addr *target,
2890 struct rfapi_next_hop_entry
*next_hops
, void *userdata
)
2892 void *stream
= userdata
;
2894 int (*fp
)(void *, const char *, ...);
2897 const char *vty_newline
;
2899 if (rfapiStream2Vty(stream
, &fp
, &vty
, &out
, &vty_newline
) == 0)
2902 fp(out
, "Nexthops Callback, Target=(");
2903 // rfapiPrintRfapiIpAddr(stream, target);
2906 rfapiPrintNhl(stream
, next_hops
);
2910 rfapi_free_next_hop_list(next_hops
);
2913 DEFUN (debug_rfapi_open
,
2914 debug_rfapi_open_cmd
,
2915 "debug rfapi-dev open vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X>",
2919 "indicate vn addr follows\n"
2920 "virtual network interface IPv4 address\n"
2921 "virtual network interface IPv6 address\n"
2922 "indicate xt addr follows\n"
2923 "underlay network interface IPv4 address\n"
2924 "underlay network interface IPv6 address\n")
2926 struct rfapi_ip_addr vn
;
2927 struct rfapi_ip_addr un
;
2928 uint32_t lifetime
= 0;
2930 rfapi_handle handle
;
2935 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[4]->arg
, &vn
)))
2941 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[6]->arg
, &un
)))
2944 rc
= rfapi_open(rfapi_get_rfp_start_val_by_bgp(bgp_get_default()), &vn
,
2945 &un
, /*&uo */ NULL
, &lifetime
, NULL
, &handle
);
2947 vty_out(vty
, "rfapi_open: status %d, handle %p, lifetime %d\n", rc
,
2950 rc
= rfapi_set_response_cb(handle
, test_nexthops_callback
);
2952 vty_out(vty
, "rfapi_set_response_cb: status %d\n", rc
);
2958 DEFUN (debug_rfapi_close_vn_un
,
2959 debug_rfapi_close_vn_un_cmd
,
2960 "debug rfapi-dev close vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X>",
2964 "indicate vn addr follows\n"
2965 "virtual network interface IPv4 address\n"
2966 "virtual network interface IPv6 address\n"
2967 "indicate xt addr follows\n"
2968 "underlay network interface IPv4 address\n"
2969 "underlay network interface IPv6 address\n")
2971 struct rfapi_ip_addr vn
;
2972 struct rfapi_ip_addr un
;
2973 rfapi_handle handle
;
2979 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[4]->arg
, &vn
)))
2986 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[6]->arg
, &un
)))
2990 if (rfapi_find_handle_vty(vty
, &vn
, &un
, &handle
)) {
2991 vty_out(vty
, "can't locate handle matching vn=%s, un=%s\n",
2992 argv
[4]->arg
, argv
[6]->arg
);
2993 return CMD_WARNING_CONFIG_FAILED
;
2996 rc
= rfapi_close(handle
);
2998 vty_out(vty
, "rfapi_close(handle=%p): status %d\n", handle
, rc
);
3003 DEFUN (debug_rfapi_close_rfd
,
3004 debug_rfapi_close_rfd_cmd
,
3005 "debug rfapi-dev close rfd HANDLE",
3009 "indicate handle follows\n" "rfapi handle in hexadecimal\n")
3011 rfapi_handle handle
;
3013 char *endptr
= NULL
;
3015 handle
= (rfapi_handle
)(uintptr_t)(strtoull(argv
[4]->arg
, &endptr
, 16));
3017 if (*endptr
!= '\0' || (uintptr_t)handle
== UINTPTR_MAX
) {
3018 vty_out(vty
, "Invalid value: %s\n", argv
[4]->arg
);
3019 return CMD_WARNING_CONFIG_FAILED
;
3022 rc
= rfapi_close(handle
);
3024 vty_out(vty
, "rfapi_close(handle=%p): status %d\n", handle
, rc
);
3029 DEFUN (debug_rfapi_register_vn_un
,
3030 debug_rfapi_register_vn_un_cmd
,
3031 "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)]",
3035 "indicate vn addr follows\n"
3036 "virtual network IPv4 interface address\n"
3037 "virtual network IPv6 interface address\n"
3038 "indicate un addr follows\n"
3039 "underlay network IPv4 interface address\n"
3040 "underlay network IPv6 interface address\n"
3041 "indicate prefix follows\n"
3044 "indicate lifetime follows\n"
3046 "Cost (localpref = 255-cost)\n"
3049 struct rfapi_ip_addr vn
;
3050 struct rfapi_ip_addr un
;
3051 rfapi_handle handle
;
3054 struct rfapi_ip_prefix hpfx
;
3061 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[4]->arg
, &vn
)))
3068 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[6]->arg
, &un
)))
3072 if (rfapi_find_handle_vty(vty
, &vn
, &un
, &handle
)) {
3073 vty_out(vty
, "can't locate handle matching vn=%s, un=%s\n",
3074 argv
[4]->arg
, argv
[6]->arg
);
3075 return CMD_WARNING_CONFIG_FAILED
;
3079 * Get prefix to advertise
3081 if (!str2prefix(argv
[8]->arg
, &pfx
)) {
3082 vty_out(vty
, "Malformed prefix \"%s\"\n", argv
[8]->arg
);
3083 return CMD_WARNING_CONFIG_FAILED
;
3085 if (pfx
.family
!= AF_INET
&& pfx
.family
!= AF_INET6
) {
3086 vty_out(vty
, "Bad family for prefix \"%s\"\n", argv
[8]->arg
);
3087 return CMD_WARNING_CONFIG_FAILED
;
3089 rfapiQprefix2Rprefix(&pfx
, &hpfx
);
3091 if (strmatch(argv
[10]->text
, "infinite")) {
3092 lifetime
= RFAPI_INFINITE_LIFETIME
;
3094 lifetime
= strtoul(argv
[10]->arg
, NULL
, 10);
3098 cost
= (uint8_t) strtoul(argv
[12]->arg
, NULL
, 10);
3101 rc
= rfapi_register(handle
, &hpfx
, lifetime
, NULL
, NULL
,
3102 RFAPI_REGISTER_ADD
);
3104 vty_out(vty
, "rfapi_register failed with rc=%d (%s)\n", rc
,
3111 DEFUN (debug_rfapi_register_vn_un_l2o
,
3112 debug_rfapi_register_vn_un_l2o_cmd
,
3113 "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 YY:YY:YY:YY:YY:YY lni (0-16777215)",
3117 "indicate vn addr follows\n"
3118 "virtual network IPv4 interface address\n"
3119 "virtual network IPv6 interface address\n"
3120 "indicate un addr follows\n"
3121 "underlay network IPv4 interface address\n"
3122 "underlay network IPv6 interface address\n"
3123 "indicate prefix follows\n"
3126 "indicate lifetime follows\n"
3127 "Seconds of lifetime\n"
3128 "indicate MAC address follows\n"
3130 "indicate lni follows\n"
3131 "lni value range\n")
3133 struct rfapi_ip_addr vn
;
3134 struct rfapi_ip_addr un
;
3135 rfapi_handle handle
;
3138 struct rfapi_ip_prefix hpfx
;
3140 struct rfapi_vn_option optary
[10]; /* XXX must be big enough */
3141 struct rfapi_vn_option
*opt
= NULL
;
3147 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[4]->arg
, &vn
)))
3154 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[6]->arg
, &un
)))
3158 if (rfapi_find_handle_vty(vty
, &vn
, &un
, &handle
)) {
3159 vty_out(vty
, "can't locate handle matching vn=%s, un=%s\n",
3160 argv
[4]->arg
, argv
[6]->arg
);
3161 return CMD_WARNING_CONFIG_FAILED
;
3165 * Get prefix to advertise
3167 if (!str2prefix(argv
[8]->arg
, &pfx
)) {
3168 vty_out(vty
, "Malformed prefix \"%s\"\n", argv
[8]->arg
);
3169 return CMD_WARNING_CONFIG_FAILED
;
3171 if (pfx
.family
!= AF_INET
&& pfx
.family
!= AF_INET6
) {
3172 vty_out(vty
, "Bad family for prefix \"%s\"\n", argv
[8]->arg
);
3173 return CMD_WARNING_CONFIG_FAILED
;
3175 rfapiQprefix2Rprefix(&pfx
, &hpfx
);
3177 if (strmatch(argv
[10]->text
, "infinite")) {
3178 lifetime
= RFAPI_INFINITE_LIFETIME
;
3180 lifetime
= strtoul(argv
[10]->arg
, NULL
, 10);
3183 /* L2 option parsing START */
3184 memset(optary
, 0, sizeof(optary
));
3185 optary
[opt_next
].v
.l2addr
.logical_net_id
=
3186 strtoul(argv
[14]->arg
, NULL
, 10);
3187 if (rfapiStr2EthAddr(argv
[12]->arg
,
3188 &optary
[opt_next
].v
.l2addr
.macaddr
)) {
3189 vty_out(vty
, "Bad mac address \"%s\"\n", argv
[12]->arg
);
3190 return CMD_WARNING_CONFIG_FAILED
;
3192 optary
[opt_next
].type
= RFAPI_VN_OPTION_TYPE_L2ADDR
;
3195 /* L2 option parsing END */
3198 rc
= rfapi_register(handle
, &hpfx
, lifetime
, NULL
/* &uo */, opt
,
3199 RFAPI_REGISTER_ADD
);
3201 vty_out(vty
, "rfapi_register failed with rc=%d (%s)\n", rc
,
3209 DEFUN (debug_rfapi_unregister_vn_un
,
3210 debug_rfapi_unregister_vn_un_cmd
,
3211 "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]",
3215 "indicate vn addr follows\n"
3216 "virtual network interface address\n"
3217 "indicate xt addr follows\n"
3218 "underlay network interface address\n"
3219 "prefix to remove\n"
3220 "Remove without holddown")
3222 struct rfapi_ip_addr vn
;
3223 struct rfapi_ip_addr un
;
3224 rfapi_handle handle
;
3226 struct rfapi_ip_prefix hpfx
;
3232 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[4]->arg
, &vn
)))
3239 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[6]->arg
, &un
)))
3243 if (rfapi_find_handle_vty(vty
, &vn
, &un
, &handle
)) {
3244 vty_out(vty
, "can't locate handle matching vn=%s, un=%s\n",
3245 argv
[4]->arg
, argv
[6]->arg
);
3246 return CMD_WARNING_CONFIG_FAILED
;
3250 * Get prefix to advertise
3252 if (!str2prefix(argv
[8]->arg
, &pfx
)) {
3253 vty_out(vty
, "Malformed prefix \"%s\"\n", argv
[8]->arg
);
3254 return CMD_WARNING_CONFIG_FAILED
;
3256 if (pfx
.family
!= AF_INET
&& pfx
.family
!= AF_INET6
) {
3257 vty_out(vty
, "Bad family for prefix \"%s\"\n", argv
[8]->arg
);
3258 return CMD_WARNING_CONFIG_FAILED
;
3260 rfapiQprefix2Rprefix(&pfx
, &hpfx
);
3262 rfapi_register(handle
, &hpfx
, 0, NULL
, NULL
,
3264 RFAPI_REGISTER_KILL
: RFAPI_REGISTER_WITHDRAW
));
3269 DEFUN (debug_rfapi_query_vn_un
,
3270 debug_rfapi_query_vn_un_cmd
,
3271 "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>",
3275 "indicate vn addr follows\n"
3276 "virtual network interface IPv4 address\n"
3277 "virtual network interface IPv6 address\n"
3278 "indicate un addr follows\n"
3281 "indicate target follows\n"
3282 "target IPv4 address\n"
3283 "target IPv6 address\n")
3285 struct rfapi_ip_addr vn
;
3286 struct rfapi_ip_addr un
;
3287 struct rfapi_ip_addr target
;
3288 rfapi_handle handle
;
3290 struct rfapi_next_hop_entry
*pNextHopEntry
;
3295 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[4]->arg
, &vn
)))
3302 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[6]->arg
, &un
)))
3309 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[8]->arg
, &target
)))
3313 if (rfapi_find_handle_vty(vty
, &vn
, &un
, &handle
)) {
3314 vty_out(vty
, "can't locate handle matching vn=%s, un=%s\n",
3315 argv
[4]->arg
, argv
[6]->arg
);
3316 return CMD_WARNING_CONFIG_FAILED
;
3320 * options parameter not used? Set to NULL for now
3322 rc
= rfapi_query(handle
, &target
, NULL
, &pNextHopEntry
);
3325 vty_out(vty
, "rfapi_query failed with rc=%d (%s)\n", rc
,
3329 * print nexthop list
3331 test_nexthops_callback(/*&target, */ pNextHopEntry
,
3332 vty
); /* frees nh list! */
3339 DEFUN (debug_rfapi_query_vn_un_l2o
,
3340 debug_rfapi_query_vn_un_l2o_cmd
,
3341 "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 YY:YY:YY:YY:YY:YY",
3345 "indicate vn addr follows\n"
3346 "virtual network interface IPv4 address\n"
3347 "virtual network interface IPv6 address\n"
3348 "indicate xt addr follows\n"
3349 "underlay network interface IPv4 address\n"
3350 "underlay network interface IPv6 address\n"
3351 "logical network ID follows\n"
3352 "logical network ID\n"
3353 "indicate target MAC addr follows\n"
3354 "target MAC addr\n")
3356 struct rfapi_ip_addr vn
;
3357 struct rfapi_ip_addr un
;
3363 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[4]->arg
, &vn
)))
3370 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[6]->arg
, &un
)))
3373 vty_out(vty
, "%% This command is broken.\n");
3374 return CMD_WARNING_CONFIG_FAILED
;
3378 DEFUN (debug_rfapi_query_done_vn_un
,
3379 debug_rfapi_query_vn_un_done_cmd
,
3380 "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>",
3383 "rfapi_query_done\n"
3384 "rfapi_query_done\n"
3385 "indicate vn addr follows\n"
3386 "virtual network interface IPv4 address\n"
3387 "virtual network interface IPv6 address\n"
3388 "indicate xt addr follows\n"
3389 "underlay network interface IPv4 address\n"
3390 "underlay network interface IPv6 address\n"
3391 "indicate target follows\n"
3392 "Target IPv4 address\n"
3393 "Target IPv6 address\n")
3395 struct rfapi_ip_addr vn
;
3396 struct rfapi_ip_addr un
;
3397 struct rfapi_ip_addr target
;
3398 rfapi_handle handle
;
3404 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[5]->arg
, &vn
)))
3411 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[7]->arg
, &un
)))
3418 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[9]->arg
, &target
)))
3422 if (rfapi_find_handle_vty(vty
, &vn
, &un
, &handle
)) {
3423 vty_out(vty
, "can't locate handle matching vn=%s, un=%s\n",
3424 argv
[5]->arg
, argv
[7]->arg
);
3425 return CMD_WARNING_CONFIG_FAILED
;
3429 * options parameter not used? Set to NULL for now
3431 rc
= rfapi_query_done(handle
, &target
);
3433 vty_out(vty
, "rfapi_query_done returned %d\n", rc
);
3438 DEFUN (debug_rfapi_show_import
,
3439 debug_rfapi_show_import_cmd
,
3440 "debug rfapi-dev show import",
3448 struct rfapi_import_table
*it
;
3453 * Show all import tables
3456 bgp
= bgp_get_default(); /* assume 1 instance for now */
3458 vty_out(vty
, "No BGP instance\n");
3459 return CMD_WARNING_CONFIG_FAILED
;
3464 vty_out(vty
, "No RFAPI instance\n");
3465 return CMD_WARNING_CONFIG_FAILED
;
3469 * Iterate over all import tables; do a filtered import
3470 * for the afi/safi combination
3474 for (it
= h
->imports
; it
; it
= it
->next
) {
3475 s
= ecommunity_ecom2str(it
->rt_import_list
,
3476 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3477 vty_out(vty
, "Import Table %p, RTs: %s\n", it
, s
);
3478 XFREE(MTYPE_ECOMMUNITY_STR
, s
);
3480 rfapiShowImportTable(vty
, "IP VPN", it
->imported_vpn
[AFI_IP
],
3482 rfapiShowImportTable(vty
, "IP ENCAP",
3483 it
->imported_encap
[AFI_IP
], 0);
3484 rfapiShowImportTable(vty
, "IP6 VPN", it
->imported_vpn
[AFI_IP6
],
3486 rfapiShowImportTable(vty
, "IP6 ENCAP",
3487 it
->imported_encap
[AFI_IP6
], 0);
3490 if (h
->import_mac
) {
3491 void *cursor
= NULL
;
3493 uintptr_t lni_as_ptr
;
3497 for (rc
= skiplist_next(h
->import_mac
, (void **)&lni_as_ptr
,
3498 (void **)&it
, &cursor
);
3500 rc
= skiplist_next(h
->import_mac
, (void **)&lni_as_ptr
,
3501 (void **)&it
, &cursor
)) {
3503 if (it
->imported_vpn
[AFI_L2VPN
]) {
3507 "\nLNI-based Ethernet Tables:\n");
3510 snprintf(buf
, BUFSIZ
, "L2VPN LNI=%u", lni
);
3511 rfapiShowImportTable(
3512 vty
, buf
, it
->imported_vpn
[AFI_L2VPN
],
3518 rfapiShowImportTable(vty
, "CE IT - IP VPN",
3519 h
->it_ce
->imported_vpn
[AFI_IP
], 1);
3524 DEFUN (debug_rfapi_show_import_vn_un
,
3525 debug_rfapi_show_import_vn_un_cmd
,
3526 "debug rfapi-dev show import vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X>",
3531 "indicate vn addr follows\n"
3532 "virtual network interface IPv4 address\n"
3533 "virtual network interface IPv6 address\n"
3534 "indicate xt addr follows\n"
3535 "underlay network interface IPv4 address\n"
3536 "underlay network interface IPv6 address\n")
3538 struct rfapi_ip_addr vn
;
3539 struct rfapi_ip_addr un
;
3540 rfapi_handle handle
;
3542 struct rfapi_descriptor
*rfd
;
3547 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[5]->arg
, &vn
)))
3554 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[7]->arg
, &un
)))
3558 if (rfapi_find_handle_vty(vty
, &vn
, &un
, &handle
)) {
3559 vty_out(vty
, "can't locate handle matching vn=%s, un=%s\n",
3560 argv
[5]->arg
, argv
[7]->arg
);
3561 return CMD_WARNING_CONFIG_FAILED
;
3564 rfd
= (struct rfapi_descriptor
*)handle
;
3566 rfapiShowImportTable(vty
, "IP VPN",
3567 rfd
->import_table
->imported_vpn
[AFI_IP
], 1);
3568 rfapiShowImportTable(vty
, "IP ENCAP",
3569 rfd
->import_table
->imported_encap
[AFI_IP
], 0);
3570 rfapiShowImportTable(vty
, "IP6 VPN",
3571 rfd
->import_table
->imported_vpn
[AFI_IP6
], 1);
3572 rfapiShowImportTable(vty
, "IP6 ENCAP",
3573 rfd
->import_table
->imported_encap
[AFI_IP6
], 0);
3578 DEFUN (debug_rfapi_response_omit_self
,
3579 debug_rfapi_response_omit_self_cmd
,
3580 "debug rfapi-dev response-omit-self <on|off>",
3583 "Omit self in RFP responses\n"
3584 "filter out self from responses\n" "leave self in responses\n")
3586 struct bgp
*bgp
= bgp_get_default();
3589 vty_out(vty
, "No BGP process is configured\n");
3590 return CMD_WARNING_CONFIG_FAILED
;
3592 if (!bgp
->rfapi_cfg
) {
3593 vty_out(vty
, "VNC not configured\n");
3594 return CMD_WARNING_CONFIG_FAILED
;
3597 if (strmatch(argv
[3]->text
, "on"))
3598 SET_FLAG(bgp
->rfapi_cfg
->flags
,
3599 BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP
);
3601 UNSET_FLAG(bgp
->rfapi_cfg
->flags
,
3602 BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP
);
3608 #ifdef RFAPI_DEBUG_SKIPLIST_CLI
3610 #include "lib/skiplist.h"
3611 DEFUN (skiplist_test_cli
,
3612 skiplist_test_cli_cmd
,
3614 "skiplist command\n"
3622 DEFUN (skiplist_debug_cli
,
3623 skiplist_debug_cli_cmd
,
3625 "skiplist command\n"
3628 skiplist_debug(vty
, NULL
);
3632 #endif /* RFAPI_DEBUG_SKIPLIST_CLI */
3634 void rfapi_init(void)
3636 bgp_rfapi_cfg_init();
3639 install_element(ENABLE_NODE
, &debug_rfapi_show_import_cmd
);
3640 install_element(ENABLE_NODE
, &debug_rfapi_show_import_vn_un_cmd
);
3642 install_element(ENABLE_NODE
, &debug_rfapi_open_cmd
);
3643 install_element(ENABLE_NODE
, &debug_rfapi_close_vn_un_cmd
);
3644 install_element(ENABLE_NODE
, &debug_rfapi_close_rfd_cmd
);
3645 install_element(ENABLE_NODE
, &debug_rfapi_register_vn_un_cmd
);
3646 install_element(ENABLE_NODE
, &debug_rfapi_unregister_vn_un_cmd
);
3647 install_element(ENABLE_NODE
, &debug_rfapi_query_vn_un_cmd
);
3648 install_element(ENABLE_NODE
, &debug_rfapi_query_vn_un_done_cmd
);
3649 install_element(ENABLE_NODE
, &debug_rfapi_query_vn_un_l2o_cmd
);
3651 install_element(ENABLE_NODE
, &debug_rfapi_response_omit_self_cmd
);
3653 /* Need the following show commands for gpz test scripts */
3654 install_element(ENABLE_NODE
, &debug_rfapi_show_nves_cmd
);
3655 install_element(ENABLE_NODE
, &debug_rfapi_show_nves_vn_un_cmd
);
3656 install_element(ENABLE_NODE
, &debug_rfapi_register_vn_un_l2o_cmd
);
3658 #ifdef RFAPI_DEBUG_SKIPLIST_CLI
3659 install_element(ENABLE_NODE
, &skiplist_test_cli_cmd
);
3660 install_element(ENABLE_NODE
, &skiplist_debug_cli_cmd
);
3667 static void rfapi_print_exported(struct bgp
*bgp
)
3669 struct bgp_node
*rdn
;
3670 struct bgp_node
*rn
;
3671 struct bgp_path_info
*bpi
;
3676 for (rdn
= bgp_table_top(bgp
->rib
[AFI_IP
][SAFI_MPLS_VPN
]); rdn
;
3677 rdn
= bgp_route_next(rdn
)) {
3678 struct bgp_table
*table
;
3680 table
= bgp_node_get_bgp_table_info(rdn
);
3683 fprintf(stderr
, "%s: vpn rdn=%p\n", __func__
, rdn
);
3684 for (rn
= bgp_table_top(table
); rn
;
3685 rn
= bgp_route_next(rn
)) {
3686 bpi
= bgp_node_get_bgp_path_info(rn
);
3690 fprintf(stderr
, "%s: rn=%p\n", __func__
, rn
);
3691 for (; bpi
; bpi
= bpi
->next
) {
3692 rfapiPrintBi((void *)2, bpi
); /* 2 => stderr */
3696 for (rdn
= bgp_table_top(bgp
->rib
[AFI_IP
][SAFI_ENCAP
]); rdn
;
3697 rdn
= bgp_route_next(rdn
)) {
3698 struct bgp_table
*table
;
3700 table
= bgp_node_get_bgp_table_info(rdn
);
3703 fprintf(stderr
, "%s: encap rdn=%p\n", __func__
, rdn
);
3704 for (rn
= bgp_table_top(table
)); rn
;
3705 rn
= bgp_route_next(rn
)) {
3706 bpi
= bgp_node_get_bgp_path_info(rn
);
3709 fprintf(stderr
, "%s: rn=%p\n", __func__
, rn
);
3710 for (; bpi
; bpi
= bpi
->next
) {
3711 rfapiPrintBi((void *)2, bpi
); /* 2 => stderr */
3716 #endif /* defined(DEBUG_RFAPI) */
3719 * Free all memory to prepare for clean exit as seen by valgrind memcheck
3721 void rfapi_delete(struct bgp
*bgp
)
3723 extern void rfp_clear_vnc_nve_all(void); /* can't fix correctly yet */
3726 * This clears queries and registered routes, and closes nves
3729 rfp_clear_vnc_nve_all();
3730 bgp_rfapi_cfg_destroy(bgp
, bgp
->rfapi_cfg
);
3731 bgp
->rfapi_cfg
= NULL
;
3732 bgp_rfapi_destroy(bgp
, bgp
->rfapi
);
3736 * show what's left in the BGP MPLSVPN RIB
3738 rfapi_print_exported(bgp
);
3742 int rfapi_set_autord_from_vn(struct prefix_rd
*rd
, struct rfapi_ip_addr
*vn
)
3744 vnc_zlog_debug_verbose("%s: auto-assigning RD", __func__
);
3745 if (vn
->addr_family
!= AF_INET
&& vn
->addr_family
!= AF_INET6
) {
3746 vnc_zlog_debug_verbose(
3747 "%s: can't auto-assign RD, VN addr family is not IPv4"
3750 return EAFNOSUPPORT
;
3752 rd
->family
= AF_UNSPEC
;
3754 rd
->val
[1] = RD_TYPE_IP
;
3755 if (vn
->addr_family
== AF_INET
) {
3756 memcpy(rd
->val
+ 2, &vn
->addr
.v4
.s_addr
, 4);
3757 } else { /* is v6 */
3758 memcpy(rd
->val
+ 2, &vn
->addr
.v6
.s6_addr32
[3],
3759 4); /* low order 4 bytes */
3762 char buf
[RD_ADDRSTRLEN
];
3764 vnc_zlog_debug_verbose("%s: auto-RD is set to %s", __func__
,
3765 prefix_rd2str(rd
, buf
, sizeof(buf
)));
3770 /*------------------------------------------
3771 * rfapi_bgp_lookup_by_rfp
3773 * Find bgp instance pointer based on value returned by rfp_start
3776 * rfp_start_val value returned by rfp_startor
3777 * NULL (=get default instance)
3783 * bgp bgp instance pointer
3786 --------------------------------------------*/
3787 struct bgp
*rfapi_bgp_lookup_by_rfp(void *rfp_start_val
)
3789 struct bgp
*bgp
= NULL
;
3790 struct listnode
*node
, *nnode
;
3792 if (rfp_start_val
== NULL
)
3793 bgp
= bgp_get_default();
3795 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
3796 if (bgp
->rfapi
!= NULL
3797 && bgp
->rfapi
->rfp
== rfp_start_val
)
3802 /*------------------------------------------
3803 * rfapi_get_rfp_start_val_by_bgp
3805 * Find bgp instance pointer based on value returned by rfp_start
3808 * bgp bgp instance pointer
3817 --------------------------------------------*/
3818 void *rfapi_get_rfp_start_val_by_bgp(struct bgp
*bgp
)
3820 if (!bgp
|| !bgp
->rfapi
)
3822 return bgp
->rfapi
->rfp
;
3825 /***********************************************************************
3826 * RFP group specific configuration
3827 ***********************************************************************/
3828 static void *rfapi_rfp_get_or_init_group_config_default(struct rfapi_cfg
*rfc
,
3832 if (rfc
->default_rfp_cfg
== NULL
&& size
> 0) {
3833 rfc
->default_rfp_cfg
= XCALLOC(MTYPE_RFAPI_RFP_GROUP_CFG
, size
);
3834 vnc_zlog_debug_verbose("%s: allocated, size=%d", __func__
,
3837 return rfc
->default_rfp_cfg
;
3840 static void *rfapi_rfp_get_or_init_group_config_nve(struct rfapi_cfg
*rfc
,
3844 struct rfapi_nve_group_cfg
*rfg
=
3845 VTY_GET_CONTEXT_SUB(rfapi_nve_group_cfg
);
3847 /* make sure group is still in list */
3848 if (!rfg
|| !listnode_lookup(rfc
->nve_groups_sequential
, rfg
)) {
3849 /* Not in list anymore */
3850 vty_out(vty
, "Current NVE group no longer exists\n");
3854 if (rfg
->rfp_cfg
== NULL
&& size
> 0) {
3855 rfg
->rfp_cfg
= XCALLOC(MTYPE_RFAPI_RFP_GROUP_CFG
, size
);
3856 vnc_zlog_debug_verbose("%s: allocated, size=%d", __func__
,
3859 return rfg
->rfp_cfg
;
3862 static void *rfapi_rfp_get_or_init_group_config_l2(struct rfapi_cfg
*rfc
,
3866 struct rfapi_l2_group_cfg
*rfg
=
3867 VTY_GET_CONTEXT_SUB(rfapi_l2_group_cfg
);
3869 /* make sure group is still in list */
3870 if (!rfg
|| !listnode_lookup(rfc
->l2_groups
, rfg
)) {
3871 /* Not in list anymore */
3872 vty_out(vty
, "Current L2 group no longer exists\n");
3875 if (rfg
->rfp_cfg
== NULL
&& size
> 0) {
3876 rfg
->rfp_cfg
= XCALLOC(MTYPE_RFAPI_RFP_GROUP_CFG
, size
);
3877 vnc_zlog_debug_verbose("%s: allocated, size=%d", __func__
,
3880 return rfg
->rfp_cfg
;
3883 /*------------------------------------------
3884 * rfapi_rfp_init_group_config_ptr_vty
3886 * This is used to init or return a previously init'ed group specific
3887 * configuration pointer. Group is identified by vty context.
3888 * NOTE: size is ignored when a previously init'ed value is returned.
3889 * RFAPI frees rfp_cfg_group when group is deleted during reconfig,
3890 * bgp restart or shutdown.
3893 * rfp_start_val value returned by rfp_start
3895 * vty quagga vty context
3896 * size number of bytes to allocation
3902 * rfp_cfg_group NULL or Pointer to configuration structure
3903 --------------------------------------------*/
3904 void *rfapi_rfp_init_group_config_ptr_vty(void *rfp_start_val
,
3905 rfapi_rfp_cfg_group_type type
,
3906 struct vty
*vty
, uint32_t size
)
3911 if (rfp_start_val
== NULL
|| vty
== NULL
)
3914 bgp
= rfapi_bgp_lookup_by_rfp(rfp_start_val
);
3915 if (!bgp
|| !bgp
->rfapi_cfg
)
3919 case RFAPI_RFP_CFG_GROUP_DEFAULT
:
3920 ret
= rfapi_rfp_get_or_init_group_config_default(bgp
->rfapi_cfg
,
3923 case RFAPI_RFP_CFG_GROUP_NVE
:
3924 ret
= rfapi_rfp_get_or_init_group_config_nve(bgp
->rfapi_cfg
,
3927 case RFAPI_RFP_CFG_GROUP_L2
:
3928 ret
= rfapi_rfp_get_or_init_group_config_l2(bgp
->rfapi_cfg
, vty
,
3932 flog_err(EC_LIB_DEVELOPMENT
, "%s: Unknown group type=%d",
3934 /* should never happen */
3935 assert("Unknown type" == NULL
);
3941 /*------------------------------------------
3942 * rfapi_rfp_get_group_config_ptr_vty
3944 * This is used to get group specific configuration pointer.
3945 * Group is identified by type and vty context.
3946 * RFAPI frees rfp_cfg_group when group is deleted during reconfig,
3947 * bgp restart or shutdown.
3950 * rfp_start_val value returned by rfp_start
3952 * vty quagga vty context
3958 * rfp_cfg_group Pointer to configuration structure
3959 --------------------------------------------*/
3960 void *rfapi_rfp_get_group_config_ptr_vty(void *rfp_start_val
,
3961 rfapi_rfp_cfg_group_type type
,
3964 return rfapi_rfp_init_group_config_ptr_vty(rfp_start_val
, type
, vty
, 0);
3968 rfapi_rfp_get_group_config_name_nve(struct rfapi_cfg
*rfc
, const char *name
,
3970 rfp_group_config_search_cb_t
*search_cb
)
3972 struct rfapi_nve_group_cfg
*rfg
;
3973 struct listnode
*node
;
3975 for (ALL_LIST_ELEMENTS_RO(rfc
->nve_groups_sequential
, node
, rfg
)) {
3976 if (!strcmp(rfg
->name
, name
) && /* name match */
3977 (search_cb
== NULL
|| !search_cb(criteria
, rfg
->rfp_cfg
)))
3978 return rfg
->rfp_cfg
;
3984 rfapi_rfp_get_group_config_name_l2(struct rfapi_cfg
*rfc
, const char *name
,
3986 rfp_group_config_search_cb_t
*search_cb
)
3988 struct rfapi_l2_group_cfg
*rfg
;
3989 struct listnode
*node
;
3991 for (ALL_LIST_ELEMENTS_RO(rfc
->l2_groups
, node
, rfg
)) {
3992 if (!strcmp(rfg
->name
, name
) && /* name match */
3993 (search_cb
== NULL
|| !search_cb(criteria
, rfg
->rfp_cfg
)))
3994 return rfg
->rfp_cfg
;
3999 /*------------------------------------------
4000 * rfapi_rfp_get_group_config_ptr_name
4002 * This is used to get group specific configuration pointer.
4003 * Group is identified by type and name context.
4004 * RFAPI frees rfp_cfg_group when group is deleted during reconfig,
4005 * bgp restart or shutdown.
4008 * rfp_start_val value returned by rfp_start
4011 * criteria RFAPI caller provided serach criteria
4012 * search_cb optional rfp_group_config_search_cb_t
4018 * rfp_cfg_group Pointer to configuration structure
4019 --------------------------------------------*/
4020 void *rfapi_rfp_get_group_config_ptr_name(
4021 void *rfp_start_val
, rfapi_rfp_cfg_group_type type
, const char *name
,
4022 void *criteria
, rfp_group_config_search_cb_t
*search_cb
)
4027 if (rfp_start_val
== NULL
|| name
== NULL
)
4030 bgp
= rfapi_bgp_lookup_by_rfp(rfp_start_val
);
4031 if (!bgp
|| !bgp
->rfapi_cfg
)
4035 case RFAPI_RFP_CFG_GROUP_DEFAULT
:
4036 ret
= bgp
->rfapi_cfg
->default_rfp_cfg
;
4038 case RFAPI_RFP_CFG_GROUP_NVE
:
4039 ret
= rfapi_rfp_get_group_config_name_nve(bgp
->rfapi_cfg
, name
,
4040 criteria
, search_cb
);
4042 case RFAPI_RFP_CFG_GROUP_L2
:
4043 ret
= rfapi_rfp_get_group_config_name_l2(bgp
->rfapi_cfg
, name
,
4044 criteria
, search_cb
);
4047 flog_err(EC_LIB_DEVELOPMENT
, "%s: Unknown group type=%d",
4049 /* should never happen */
4050 assert("Unknown type" == NULL
);
4056 /*------------------------------------------
4057 * rfapi_rfp_get_l2_group_config_ptr_lni
4059 * This is used to get group specific configuration pointer.
4060 * Group is identified by type and logical network identifier.
4061 * RFAPI frees rfp_cfg_group when group is deleted during reconfig,
4062 * bgp restart or shutdown.
4065 * rfp_start_val value returned by rfp_start
4067 * logical_net_id group logical network identifier
4068 * criteria RFAPI caller provided serach criteria
4069 * search_cb optional rfp_group_config_search_cb_t
4075 * rfp_cfg_group Pointer to configuration structure
4076 --------------------------------------------*/
4078 rfapi_rfp_get_l2_group_config_ptr_lni(void *rfp_start_val
,
4079 uint32_t logical_net_id
, void *criteria
,
4080 rfp_group_config_search_cb_t
*search_cb
)
4083 struct rfapi_l2_group_cfg
*rfg
;
4084 struct listnode
*node
;
4086 if (rfp_start_val
== NULL
)
4089 bgp
= rfapi_bgp_lookup_by_rfp(rfp_start_val
);
4090 if (!bgp
|| !bgp
->rfapi_cfg
)
4093 for (ALL_LIST_ELEMENTS_RO(bgp
->rfapi_cfg
->l2_groups
, node
, rfg
)) {
4094 if (rfg
->logical_net_id
== logical_net_id
4095 && (search_cb
== NULL
4096 || !search_cb(criteria
, rfg
->rfp_cfg
))) {
4097 if (rfg
->rfp_cfg
== NULL
)
4098 vnc_zlog_debug_verbose(
4099 "%s: returning rfp group config for lni=0",
4101 return rfg
->rfp_cfg
;