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
24 #include "lib/zebra.h"
25 #include "lib/prefix.h"
26 #include "lib/table.h"
28 #include "lib/memory.h"
29 #include "lib/routemap.h"
31 #include "lib/linklist.h"
32 #include "lib/command.h"
33 #include "lib/stream.h"
35 #include "bgpd/bgpd.h"
36 #include "bgpd/bgp_ecommunity.h"
37 #include "bgpd/bgp_attr.h"
39 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
40 #include "bgpd/rfapi/rfapi.h"
41 #include "bgpd/rfapi/rfapi_backend.h"
43 #include "bgpd/bgp_route.h"
44 #include "bgpd/bgp_mplsvpn.h"
45 #include "bgpd/bgp_aspath.h"
46 #include "bgpd/bgp_advertise.h"
47 #include "bgpd/bgp_vnc_types.h"
48 #include "bgpd/bgp_zebra.h"
50 #include "bgpd/rfapi/rfapi_import.h"
51 #include "bgpd/rfapi/rfapi_private.h"
52 #include "bgpd/rfapi/rfapi_monitor.h"
53 #include "bgpd/rfapi/rfapi_vty.h"
54 #include "bgpd/rfapi/vnc_export_bgp.h"
55 #include "bgpd/rfapi/vnc_export_bgp_p.h"
56 #include "bgpd/rfapi/vnc_zebra.h"
57 #include "bgpd/rfapi/vnc_import_bgp.h"
58 #include "bgpd/rfapi/rfapi_rib.h"
59 #include "bgpd/rfapi/rfapi_ap.h"
60 #include "bgpd/rfapi/rfapi_encap_tlv.h"
61 #include "bgpd/rfapi/vnc_debug.h"
63 #ifdef HAVE_GLIBC_BACKTRACE
64 /* for backtrace and friends */
66 #endif /* HAVE_GLIBC_BACKTRACE */
68 struct ethaddr rfapi_ethaddr0
= {{0}};
70 #define DEBUG_RFAPI_STR "RF API debugging/testing command\n"
72 const char *rfapi_error_str(int code
)
78 return "BGP or VNC not configured";
82 return "Handle already open";
84 return "Incomplete configuration";
86 return "Invalid address family";
88 return "Called from within a callback procedure";
90 return "Invalid handle";
92 return "Invalid argument";
94 return "Stale descriptor";
96 return "Unknown error";
100 /*------------------------------------------
101 * rfapi_get_response_lifetime_default
103 * Returns the default lifetime for a response.
104 * rfp_start_val value returned by rfp_start or
105 * NULL (=use default instance)
112 * return value: The bgp instance default lifetime for a response.
113 --------------------------------------------*/
114 int rfapi_get_response_lifetime_default(void *rfp_start_val
)
116 struct bgp
*bgp
= rfapi_bgp_lookup_by_rfp(rfp_start_val
);
118 return bgp
->rfapi_cfg
->default_response_lifetime
;
119 return BGP_VNC_DEFAULT_RESPONSE_LIFETIME_DEFAULT
;
122 /*------------------------------------------
123 * rfapi_is_vnc_configured
125 * Returns if VNC (BGP VPN messaging /VPN & encap SAFIs) are configured
128 * rfp_start_val value returned by rfp_start or
129 * NULL (=use default instance)
133 * return value: If VNC is configured for the bgpd instance
135 * ENXIO VNC not configured
136 --------------------------------------------*/
137 int rfapi_is_vnc_configured(void *rfp_start_val
)
139 struct bgp
*bgp
= rfapi_bgp_lookup_by_rfp(rfp_start_val
);
140 return bgp_rfapi_is_vnc_configured(bgp
);
144 /*------------------------------------------
147 * Get the virtual network address used by an NVE based on it's RFD
150 * rfd: rfapi descriptor returned by rfapi_open or rfapi_create_generic
155 * vn NVE virtual network address
156 *------------------------------------------*/
157 struct rfapi_ip_addr
*rfapi_get_vn_addr(void *rfd
)
159 struct rfapi_descriptor
*rrfd
= (struct rfapi_descriptor
*)rfd
;
160 return &rrfd
->vn_addr
;
163 /*------------------------------------------
166 * Get the underlay network address used by an NVE based on it's RFD
169 * rfd: rfapi descriptor returned by rfapi_open or rfapi_create_generic
174 * un NVE underlay network address
175 *------------------------------------------*/
176 struct rfapi_ip_addr
*rfapi_get_un_addr(void *rfd
)
178 struct rfapi_descriptor
*rrfd
= (struct rfapi_descriptor
*)rfd
;
179 return &rrfd
->un_addr
;
182 int rfapi_ip_addr_cmp(struct rfapi_ip_addr
*a1
, struct rfapi_ip_addr
*a2
)
184 if (a1
->addr_family
!= a2
->addr_family
)
185 return a1
->addr_family
- a2
->addr_family
;
187 if (a1
->addr_family
== AF_INET
) {
188 return IPV4_ADDR_CMP(&a1
->addr
.v4
, &a2
->addr
.v4
);
191 if (a1
->addr_family
== AF_INET6
) {
192 return IPV6_ADDR_CMP(&a1
->addr
.v6
, &a2
->addr
.v6
);
200 static int rfapi_find_node(struct bgp
*bgp
, struct rfapi_ip_addr
*vn_addr
,
201 struct rfapi_ip_addr
*un_addr
,
202 struct route_node
**node
)
206 struct route_node
*rn
;
219 afi
= family2afi(un_addr
->addr_family
);
224 if ((rc
= rfapiRaddr2Qprefix(un_addr
, &p
)))
227 rn
= route_node_lookup(&h
->un
[afi
], &p
);
232 route_unlock_node(rn
);
240 int rfapi_find_rfd(struct bgp
*bgp
, struct rfapi_ip_addr
*vn_addr
,
241 struct rfapi_ip_addr
*un_addr
, struct rfapi_descriptor
**rfd
)
243 struct route_node
*rn
;
246 rc
= rfapi_find_node(bgp
, vn_addr
, un_addr
, &rn
);
251 for (*rfd
= (struct rfapi_descriptor
*)(rn
->info
); *rfd
;
252 *rfd
= (*rfd
)->next
) {
253 if (!rfapi_ip_addr_cmp(&(*rfd
)->vn_addr
, vn_addr
))
263 /*------------------------------------------
267 * un underlay network address
268 * vn virtual network address
271 * pHandle pointer to location to store handle
275 * ENOENT no matching handle
276 * ENXIO BGP or VNC not configured
277 *------------------------------------------*/
278 static int rfapi_find_handle(struct bgp
*bgp
, struct rfapi_ip_addr
*vn_addr
,
279 struct rfapi_ip_addr
*un_addr
,
280 rfapi_handle
*handle
)
282 struct rfapi_descriptor
**rfd
;
284 rfd
= (struct rfapi_descriptor
**)handle
;
286 return rfapi_find_rfd(bgp
, vn_addr
, un_addr
, rfd
);
289 static int rfapi_find_handle_vty(struct vty
*vty
, struct rfapi_ip_addr
*vn_addr
,
290 struct rfapi_ip_addr
*un_addr
,
291 rfapi_handle
*handle
)
294 struct rfapi_descriptor
**rfd
;
296 bgp
= bgp_get_default(); /* assume 1 instance for now */
298 rfd
= (struct rfapi_descriptor
**)handle
;
300 return rfapi_find_rfd(bgp
, vn_addr
, un_addr
, rfd
);
303 static int is_valid_rfd(struct rfapi_descriptor
*rfd
)
307 if (!rfd
|| rfd
->bgp
== NULL
)
312 RFAPI_HD_FLAG_IS_VRF
)) /* assume VRF/internal are valid */
315 if (rfapi_find_handle(rfd
->bgp
, &rfd
->vn_addr
, &rfd
->un_addr
, &hh
))
325 * check status of descriptor
327 int rfapi_check(void *handle
)
329 struct rfapi_descriptor
*rfd
= (struct rfapi_descriptor
*)handle
;
333 if (!rfd
|| rfd
->bgp
== NULL
)
338 RFAPI_HD_FLAG_IS_VRF
)) /* assume VRF/internal are valid */
341 if ((rc
= rfapi_find_handle(rfd
->bgp
, &rfd
->vn_addr
, &rfd
->un_addr
,
355 void del_vnc_route(struct rfapi_descriptor
*rfd
,
356 struct peer
*peer
, /* rfd->peer for RFP regs */
357 struct bgp
*bgp
, safi_t safi
, struct prefix
*p
,
358 struct prefix_rd
*prd
, uint8_t type
, uint8_t sub_type
,
359 struct rfapi_nexthop
*lnh
, int kill
)
361 afi_t afi
; /* of the VN address */
366 struct prefix_rd prd0
;
368 prefix2str(p
, buf
, BUFSIZ
);
369 buf
[BUFSIZ
- 1] = 0; /* guarantee NUL-terminated */
371 prefix_rd2str(prd
, buf2
, BUFSIZ
);
372 buf2
[BUFSIZ
- 1] = 0;
374 afi
= family2afi(p
->family
);
375 assert(afi
== AFI_IP
|| afi
== AFI_IP6
);
377 if (safi
== SAFI_ENCAP
) {
378 memset(&prd0
, 0, sizeof(prd0
));
379 prd0
.family
= AF_UNSPEC
;
383 bn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
385 vnc_zlog_debug_verbose(
386 "%s: peer=%p, prefix=%s, prd=%s afi=%d, safi=%d bn=%p, bn->info=%p",
387 __func__
, peer
, buf
, buf2
, afi
, safi
, bn
,
388 (bn
? bn
->info
: NULL
));
390 for (bi
= (bn
? bn
->info
: NULL
); bi
; bi
= bi
->next
) {
392 vnc_zlog_debug_verbose(
393 "%s: trying bi=%p, bi->peer=%p, bi->type=%d, bi->sub_type=%d, bi->extra->vnc.export.rfapi_handle=%p, local_pref=%u",
394 __func__
, bi
, bi
->peer
, bi
->type
, bi
->sub_type
,
395 (bi
->extra
? bi
->extra
->vnc
.export
.rfapi_handle
: NULL
),
397 && CHECK_FLAG(bi
->attr
->flag
,
398 ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))
399 ? bi
->attr
->local_pref
402 if (bi
->peer
== peer
&& bi
->type
== type
403 && bi
->sub_type
== sub_type
&& bi
->extra
404 && bi
->extra
->vnc
.export
.rfapi_handle
== (void *)rfd
) {
406 vnc_zlog_debug_verbose("%s: matched it", __func__
);
414 * lnh set means to JUST delete the local nexthop from this
415 * route. Leave the route itself in place.
416 * TBD add return code reporting of success/failure
418 if (!bi
|| !bi
->extra
419 || !bi
->extra
->vnc
.export
.local_nexthops
) {
423 vnc_zlog_debug_verbose(
424 "%s: lnh list already empty at prefix %s",
432 struct listnode
*node
;
433 struct rfapi_nexthop
*pLnh
= NULL
;
435 for (ALL_LIST_ELEMENTS_RO(bi
->extra
->vnc
.export
.local_nexthops
,
438 if (prefix_same(&pLnh
->addr
, &lnh
->addr
)) {
444 listnode_delete(bi
->extra
->vnc
.export
.local_nexthops
,
447 /* silly rabbit, listnode_delete doesn't invoke
448 * list->del on data */
449 rfapi_nexthop_free(pLnh
);
451 vnc_zlog_debug_verbose("%s: desired lnh not found %s",
458 * loop back to import tables
459 * Do this before removing from BGP RIB because rfapiProcessWithdraw
462 rfapiProcessWithdraw(peer
, rfd
, p
, prd
, NULL
, afi
, safi
, type
, kill
);
467 prefix2str(p
, buf
, BUFSIZ
);
468 buf
[BUFSIZ
- 1] = 0; /* guarantee NUL-terminated */
470 vnc_zlog_debug_verbose(
471 "%s: Found route (safi=%d) to delete at prefix %s",
472 __func__
, safi
, buf
);
474 if (safi
== SAFI_MPLS_VPN
) {
475 struct bgp_node
*prn
= NULL
;
476 struct bgp_table
*table
= NULL
;
478 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
479 (struct prefix
*)prd
);
481 table
= (struct bgp_table
*)(prn
->info
);
483 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
484 bgp
, prd
, table
, p
, bi
);
486 bgp_unlock_node(prn
);
490 * Delete local_nexthops list
492 if (bi
->extra
&& bi
->extra
->vnc
.export
.local_nexthops
) {
493 list_delete(bi
->extra
->vnc
.export
.local_nexthops
);
496 bgp_aggregate_decrement(bgp
, p
, bi
, afi
, safi
);
497 bgp_info_delete(bn
, bi
);
498 bgp_process(bgp
, bn
, afi
, safi
);
500 vnc_zlog_debug_verbose(
501 "%s: Couldn't find route (safi=%d) at prefix %s",
502 __func__
, safi
, buf
);
508 struct rfapi_nexthop
*rfapi_nexthop_new(struct rfapi_nexthop
*copyme
)
510 struct rfapi_nexthop
*new =
511 XCALLOC(MTYPE_RFAPI_NEXTHOP
, sizeof(struct rfapi_nexthop
));
517 void rfapi_nexthop_free(void *p
)
519 struct rfapi_nexthop
*goner
= p
;
520 XFREE(MTYPE_RFAPI_NEXTHOP
, goner
);
523 struct rfapi_vn_option
*rfapi_vn_options_dup(struct rfapi_vn_option
*existing
)
525 struct rfapi_vn_option
*p
;
526 struct rfapi_vn_option
*head
= NULL
;
527 struct rfapi_vn_option
*tail
= NULL
;
529 for (p
= existing
; p
; p
= p
->next
) {
530 struct rfapi_vn_option
*new;
532 new = XCALLOC(MTYPE_RFAPI_VN_OPTION
,
533 sizeof(struct rfapi_vn_option
));
546 void rfapi_un_options_free(struct rfapi_un_option
*p
)
548 struct rfapi_un_option
*next
;
552 XFREE(MTYPE_RFAPI_UN_OPTION
, p
);
557 void rfapi_vn_options_free(struct rfapi_vn_option
*p
)
559 struct rfapi_vn_option
*next
;
563 XFREE(MTYPE_RFAPI_VN_OPTION
, p
);
568 /* Based on bgp_redistribute_add() */
569 void add_vnc_route(struct rfapi_descriptor
*rfd
, /* cookie, VPN UN addr, peer */
570 struct bgp
*bgp
, int safi
, struct prefix
*p
,
571 struct prefix_rd
*prd
, struct rfapi_ip_addr
*nexthop
,
572 uint32_t *local_pref
,
573 uint32_t *lifetime
, /* NULL => dont send lifetime */
574 struct bgp_tea_options
*rfp_options
,
575 struct rfapi_un_option
*options_un
,
576 struct rfapi_vn_option
*options_vn
,
577 struct ecommunity
*rt_export_list
, /* Copied, not consumed */
578 uint32_t *med
, /* NULL => don't set med */
579 uint32_t *label
, /* low order 3 bytes */
580 uint8_t type
, uint8_t sub_type
, /* RFP, NORMAL or REDIST */
583 afi_t afi
; /* of the VN address */
584 struct bgp_info
*new;
588 struct attr attr
= {0};
589 struct attr
*new_attr
;
592 struct bgp_attr_encap_subtlv
*encaptlv
;
596 struct prefix pfx_buf
;
599 struct rfapi_nexthop
*lnh
= NULL
; /* local nexthop */
600 struct rfapi_vn_option
*vo
;
601 struct rfapi_l2address_option
*l2o
= NULL
;
602 struct rfapi_ip_addr
*un_addr
= &rfd
->un_addr
;
604 bgp_encap_types TunnelType
= BGP_ENCAP_TYPE_RESERVED
;
605 struct bgp_redist
*red
;
607 if (safi
== SAFI_ENCAP
608 && !(bgp
->rfapi_cfg
->flags
& BGP_VNC_CONFIG_ADV_UN_METHOD_ENCAP
)) {
611 * Encap mode not enabled. UN addresses will be communicated
612 * via VNC Tunnel subtlv instead.
614 vnc_zlog_debug_verbose(
615 "%s: encap mode not enabled, not adding SAFI_ENCAP route",
621 if ((safi
== SAFI_MPLS_VPN
) && (flags
& RFAPI_AHR_SET_PFX_TO_NEXTHOP
))
624 if (rfapiRaddr2Qprefix (nexthop
, &pfx_buf
))
626 vnc_zlog_debug_verbose
627 ("%s: can't set pfx to vn addr, not adding SAFI_MPLS_VPN route",
634 for (vo
= options_vn
; vo
; vo
= vo
->next
) {
635 if (RFAPI_VN_OPTION_TYPE_L2ADDR
== vo
->type
) {
637 if (RFAPI_0_ETHERADDR(&l2o
->macaddr
))
638 l2o
= NULL
; /* not MAC resolution */
640 if (RFAPI_VN_OPTION_TYPE_LOCAL_NEXTHOP
== vo
->type
) {
641 lnh
= &vo
->v
.local_nexthop
;
648 label_val
= MPLS_LABEL_IMPLICIT_NULL
;
650 prefix_rd2str(prd
, buf2
, BUFSIZ
);
651 buf2
[BUFSIZ
- 1] = 0;
654 afi
= family2afi(p
->family
);
655 assert(afi
== AFI_IP
|| afi
== AFI_IP6
);
657 vnc_zlog_debug_verbose("%s: afi=%s, safi=%s", __func__
, afi2str(afi
),
660 /* Make default attribute. Produces already-interned attr.aspath */
661 /* Cripes, the memory management of attributes is byzantine */
663 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
668 * extra: dynamically allocated, owned by attr
669 * aspath: points to interned hash from aspath hash table
674 * Route-specific un_options get added to the VPN SAFI
675 * advertisement tunnel encap attribute. (the per-NVE
676 * "default" un_options are put into the 1-per-NVE ENCAP
677 * SAFI advertisement). The VPN SAFI also gets the
678 * default un_options if there are no route-specific options.
681 struct rfapi_un_option
*uo
;
683 for (uo
= options_un
; uo
; uo
= uo
->next
) {
684 if (RFAPI_UN_OPTION_TYPE_TUNNELTYPE
== uo
->type
) {
685 TunnelType
= rfapi_tunneltype_option_to_tlv(
686 bgp
, un_addr
, &uo
->v
.tunnel
, &attr
,
693 * These are the NVE-specific "default" un_options which are
694 * put into the 1-per-NVE ENCAP advertisement.
696 if (rfd
->default_tunneltype_option
.type
) {
697 TunnelType
= rfapi_tunneltype_option_to_tlv(
698 bgp
, un_addr
, &rfd
->default_tunneltype_option
,
700 } else /* create default for local addse */
701 if (type
== ZEBRA_ROUTE_BGP
702 && sub_type
== BGP_ROUTE_RFP
)
703 TunnelType
= rfapi_tunneltype_option_to_tlv(
704 bgp
, un_addr
, NULL
, &attr
, l2o
!= NULL
);
707 if (TunnelType
== BGP_ENCAP_TYPE_MPLS
) {
708 if (safi
== SAFI_ENCAP
) {
709 /* Encap SAFI not used with MPLS */
710 vnc_zlog_debug_verbose(
711 "%s: mpls tunnel type, encap safi omitted",
713 aspath_unintern(&attr
.aspath
); /* Unintern original. */
719 attr
.local_pref
= *local_pref
;
720 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
725 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
728 /* override default weight assigned by bgp_attr_default_set() */
729 attr
.weight
= rfd
->peer
? rfd
->peer
->weight
[afi
][safi
] : 0;
732 * NB: ticket 81: do not reset attr.aspath here because it would
733 * cause iBGP peers to drop route
737 * Set originator ID for routes imported from BGP directly.
738 * These routes could be synthetic, and therefore could
739 * reuse the peer pointers of the routes they are derived
740 * from. Setting the originator ID to "us" prevents the
741 * wrong originator ID from being sent when this route is
742 * sent from a route reflector.
744 if (type
== ZEBRA_ROUTE_BGP_DIRECT
745 || type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
) {
746 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
);
747 attr
.originator_id
= bgp
->router_id
;
751 /* Set up vnc attribute (sub-tlv for Prefix Lifetime) */
752 if (lifetime
&& *lifetime
!= RFAPI_INFINITE_LIFETIME
) {
756 XCALLOC(MTYPE_ENCAP_TLV
,
757 sizeof(struct bgp_attr_encap_subtlv
) - 1 + 4);
760 BGP_VNC_SUBTLV_TYPE_LIFETIME
; /* prefix lifetime */
761 encaptlv
->length
= 4;
762 lt
= htonl(*lifetime
);
763 memcpy(encaptlv
->value
, <
, 4);
764 attr
.vnc_subtlvs
= encaptlv
;
765 vnc_zlog_debug_verbose(
766 "%s: set Encap Attr Prefix Lifetime to %d", __func__
,
770 /* add rfp options to vnc attr */
773 if (flags
& RFAPI_AHR_RFPOPT_IS_VNCTLV
) {
776 * this flag means we're passing a pointer to an
777 * existing encap tlv chain which we should copy.
778 * It's a hack to avoid adding yet another argument
781 encaptlv
= encap_tlv_dup(
782 (struct bgp_attr_encap_subtlv
*)rfp_options
);
783 if (attr
.vnc_subtlvs
) {
784 attr
.vnc_subtlvs
->next
= encaptlv
;
786 attr
.vnc_subtlvs
= encaptlv
;
790 struct bgp_tea_options
*hop
;
791 /* XXX max of one tlv present so far from above code */
792 struct bgp_attr_encap_subtlv
*tail
= attr
.vnc_subtlvs
;
794 for (hop
= rfp_options
; hop
; hop
= hop
->next
) {
801 sizeof(struct bgp_attr_encap_subtlv
) - 1
805 BGP_VNC_SUBTLV_TYPE_RFPOPTION
; /* RFP
808 encaptlv
->length
= 2 + hop
->length
;
809 *((uint8_t *)(encaptlv
->value
) + 0) = hop
->type
;
810 *((uint8_t *)(encaptlv
->value
) + 1) =
812 memcpy(((uint8_t *)encaptlv
->value
) + 2,
813 hop
->value
, hop
->length
);
816 * add to end of subtlv chain
819 tail
->next
= encaptlv
;
821 attr
.vnc_subtlvs
= encaptlv
;
831 * extra: dynamically allocated, owned by attr
832 * vnc_subtlvs: dynamic chain, length 1
833 * aspath: points to interned hash from aspath hash table
837 attr
.ecommunity
= ecommunity_new();
838 assert(attr
.ecommunity
);
840 if (TunnelType
!= BGP_ENCAP_TYPE_MPLS
841 && TunnelType
!= BGP_ENCAP_TYPE_RESERVED
) {
843 * Add BGP Encapsulation Extended Community. Format described in
844 * section 4.5 of RFC 5512.
845 * Always include when not MPLS type, to disambiguate this case.
847 struct ecommunity_val beec
;
849 memset(&beec
, 0, sizeof(beec
));
850 beec
.val
[0] = ECOMMUNITY_ENCODE_OPAQUE
;
851 beec
.val
[1] = ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP
;
852 beec
.val
[6] = ((TunnelType
) >> 8) & 0xff;
853 beec
.val
[7] = (TunnelType
)&0xff;
854 ecommunity_add_val(attr
.ecommunity
, &beec
);
858 * Add extended community attributes to match rt export list
860 if (rt_export_list
) {
862 ecommunity_merge(attr
.ecommunity
, rt_export_list
);
865 if (attr
.ecommunity
->size
) {
866 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
868 ecommunity_free(&attr
.ecommunity
);
869 attr
.ecommunity
= NULL
;
871 vnc_zlog_debug_verbose("%s: attr.ecommunity=%p", __func__
,
878 * extra: dynamically allocated, owned by attr
879 * vnc_subtlvs: dynamic chain, length 1
880 * ecommunity: dynamic 2-part
881 * aspath: points to interned hash from aspath hash table
884 /* stuff nexthop in attr_extra; which field depends on IPv4 or IPv6 */
885 switch (nexthop
->addr_family
) {
888 * set this field to prevent bgp_route.c code from setting
889 * mp_nexthop_global_in to self
891 attr
.nexthop
.s_addr
= nexthop
->addr
.v4
.s_addr
;
893 attr
.mp_nexthop_global_in
= nexthop
->addr
.v4
;
894 attr
.mp_nexthop_len
= 4;
898 attr
.mp_nexthop_global
= nexthop
->addr
.v6
;
899 attr
.mp_nexthop_len
= 16;
907 prefix2str(p
, buf
, BUFSIZ
);
908 buf
[BUFSIZ
- 1] = 0; /* guarantee NUL-terminated */
914 * extra: dynamically allocated, owned by attr
915 * vnc_subtlvs: dynamic chain, length 1
916 * ecommunity: dynamic 2-part
917 * aspath: points to interned hash from aspath hash table
920 red
= bgp_redist_lookup(bgp
, afi
, type
, VRF_DEFAULT
);
922 if (red
&& red
->redist_metric_flag
) {
923 attr
.med
= red
->redist_metric
;
924 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
927 bn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
930 * bgp_attr_intern creates a new reference to a cached
931 * attribute, but leaves the following bits of trash:
933 * - old attr->extra (free via bgp_attr_extra_free(attr))
935 * Note that it frees the original attr->extra->ecommunity
936 * but leaves the new attribute pointing to the ORIGINAL
937 * vnc options (which therefore we needn't free from the
940 new_attr
= bgp_attr_intern(&attr
);
942 aspath_unintern(&attr
.aspath
); /* Unintern original. */
948 * extra: dynamically allocated, owned by attr
949 * vnc_subtlvs: dynamic chain, length 1
950 * ecommunity: POINTS TO INTERNED ecom, THIS REF NOT COUNTED
952 * new_attr: an attr that is part of the hash table, distinct
953 * from attr which is static.
954 * extra: dynamically allocated, owned by new_attr (in hash table)
955 * vnc_subtlvs: POINTS TO SAME dynamic chain AS attr
956 * ecommunity: POINTS TO interned/refcounted dynamic 2-part AS attr
957 * aspath: POINTS TO interned/refcounted hashed block
959 for (bi
= bn
->info
; bi
; bi
= bi
->next
) {
960 /* probably only need to check
961 * bi->extra->vnc.export.rfapi_handle */
962 if (bi
->peer
== rfd
->peer
&& bi
->type
== type
963 && bi
->sub_type
== sub_type
&& bi
->extra
964 && bi
->extra
->vnc
.export
.rfapi_handle
== (void *)rfd
) {
973 * Adding new local_nexthop, which does not by itself change
974 * what is advertised via BGP
977 if (!bi
->extra
->vnc
.export
.local_nexthops
) {
978 /* TBD make arrangements to free when needed */
979 bi
->extra
->vnc
.export
.local_nexthops
=
981 bi
->extra
->vnc
.export
.local_nexthops
->del
=
988 struct listnode
*node
;
989 struct rfapi_nexthop
*pLnh
= NULL
;
991 for (ALL_LIST_ELEMENTS_RO(
992 bi
->extra
->vnc
.export
.local_nexthops
, node
,
995 if (prefix_same(&pLnh
->addr
, &lnh
->addr
)) {
1001 * Not present, add new one
1004 pLnh
= rfapi_nexthop_new(lnh
);
1006 bi
->extra
->vnc
.export
.local_nexthops
,
1011 if (attrhash_cmp(bi
->attr
, new_attr
)
1012 && !CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
)) {
1013 bgp_attr_unintern(&new_attr
);
1014 bgp_unlock_node(bn
);
1017 "%s: Found route (safi=%d) at prefix %s, no change",
1018 __func__
, safi
, buf
);
1022 /* The attribute is changed. */
1023 bgp_info_set_flag(bn
, bi
, BGP_INFO_ATTR_CHANGED
);
1025 if (safi
== SAFI_MPLS_VPN
) {
1026 struct bgp_node
*prn
= NULL
;
1027 struct bgp_table
*table
= NULL
;
1029 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
1030 (struct prefix
*)prd
);
1032 table
= (struct bgp_table
*)(prn
->info
);
1034 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
1035 bgp
, prd
, table
, p
, bi
);
1037 bgp_unlock_node(prn
);
1040 /* Rewrite BGP route information. */
1041 if (CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
))
1042 bgp_info_restore(bn
, bi
);
1044 bgp_aggregate_decrement(bgp
, p
, bi
, afi
, safi
);
1045 bgp_attr_unintern(&bi
->attr
);
1046 bi
->attr
= new_attr
;
1047 bi
->uptime
= bgp_clock();
1050 if (safi
== SAFI_MPLS_VPN
) {
1051 struct bgp_node
*prn
= NULL
;
1052 struct bgp_table
*table
= NULL
;
1054 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
1055 (struct prefix
*)prd
);
1057 table
= (struct bgp_table
*)(prn
->info
);
1059 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
1060 bgp
, prd
, table
, p
, bi
);
1062 bgp_unlock_node(prn
);
1065 /* Process change. */
1066 bgp_aggregate_increment(bgp
, p
, bi
, afi
, safi
);
1067 bgp_process(bgp
, bn
, afi
, safi
);
1068 bgp_unlock_node(bn
);
1071 "%s: Found route (safi=%d) at prefix %s, changed attr",
1072 __func__
, safi
, buf
);
1079 new = bgp_info_new();
1081 new->sub_type
= sub_type
;
1082 new->peer
= rfd
->peer
;
1083 SET_FLAG(new->flags
, BGP_INFO_VALID
);
1084 new->attr
= new_attr
;
1085 new->uptime
= bgp_clock();
1087 /* save backref to rfapi handle */
1088 assert(bgp_info_extra_get(new));
1089 new->extra
->vnc
.export
.rfapi_handle
= (void *)rfd
;
1090 encode_label(label_val
, &new->extra
->label
);
1094 if (VNC_DEBUG(VERBOSE
)) {
1095 vnc_zlog_debug_verbose("%s: printing BI", __func__
);
1096 rfapiPrintBi(NULL
, new);
1099 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
1100 bgp_info_add(bn
, new);
1102 if (safi
== SAFI_MPLS_VPN
) {
1103 struct bgp_node
*prn
= NULL
;
1104 struct bgp_table
*table
= NULL
;
1106 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
1108 table
= (struct bgp_table
*)(prn
->info
);
1110 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
1111 bgp
, prd
, table
, p
, new);
1113 bgp_unlock_node(prn
);
1114 encode_label(label_val
, &bn
->local_label
);
1117 bgp_unlock_node(bn
);
1118 bgp_process(bgp
, bn
, afi
, safi
);
1121 "%s: Added route (safi=%s) at prefix %s (bn=%p, prd=%s)",
1122 __func__
, safi2str(safi
), buf
, bn
, buf2
);
1125 /* Loop back to import tables */
1126 rfapiProcessUpdate(rfd
->peer
, rfd
, p
, prd
, new_attr
, afi
, safi
, type
,
1127 sub_type
, &label_val
);
1128 vnc_zlog_debug_verbose("%s: looped back import route (safi=%d)",
1132 uint32_t rfp_cost_to_localpref(uint8_t cost
)
1137 static void rfapiTunnelRouteAnnounce(struct bgp
*bgp
,
1138 struct rfapi_descriptor
*rfd
,
1139 uint32_t *pLifetime
)
1141 struct prefix_rd prd
;
1142 struct prefix pfx_vn
;
1144 uint32_t local_pref
= rfp_cost_to_localpref(0);
1146 rc
= rfapiRaddr2Qprefix(&(rfd
->vn_addr
), &pfx_vn
);
1150 * Construct route distinguisher = 0
1152 memset(&prd
, 0, sizeof(prd
));
1153 prd
.family
= AF_UNSPEC
;
1156 add_vnc_route(rfd
, /* rfapi descr, for export list & backref */
1157 bgp
, /* which bgp instance */
1158 SAFI_ENCAP
, /* which SAFI */
1159 &pfx_vn
, /* prefix to advertise */
1160 &prd
, /* route distinguisher to use */
1161 &rfd
->un_addr
, /* nexthop */
1163 pLifetime
, /* max lifetime of child VPN routes */
1164 NULL
, /* no rfp options for ENCAP safi */
1165 NULL
, /* rfp un options */
1166 NULL
, /* rfp vn options */
1167 rfd
->rt_export_list
, NULL
, /* med */
1168 NULL
, /* label: default */
1169 ZEBRA_ROUTE_BGP
, BGP_ROUTE_RFP
, 0);
1173 /***********************************************************************
1174 * RFP processing behavior configuration
1175 ***********************************************************************/
1177 /*------------------------------------------
1178 * rfapi_rfp_set_configuration
1180 * This is used to change rfapi's processing behavior based on
1184 * rfp_start_val value returned by rfp_start
1185 * rfapi_rfp_cfg Pointer to configuration structure
1192 * ENXIO Unabled to locate configured BGP/VNC
1193 --------------------------------------------*/
1194 int rfapi_rfp_set_configuration(void *rfp_start_val
, struct rfapi_rfp_cfg
*new)
1196 struct rfapi_rfp_cfg
*rcfg
;
1199 bgp
= rfapi_bgp_lookup_by_rfp(rfp_start_val
);
1201 if (!new || !bgp
|| !bgp
->rfapi_cfg
)
1204 rcfg
= &bgp
->rfapi_cfg
->rfp_cfg
;
1205 rcfg
->download_type
= new->download_type
;
1206 rcfg
->ftd_advertisement_interval
= new->ftd_advertisement_interval
;
1207 rcfg
->holddown_factor
= new->holddown_factor
;
1209 if (rcfg
->use_updated_response
!= new->use_updated_response
) {
1210 rcfg
->use_updated_response
= new->use_updated_response
;
1211 if (rcfg
->use_updated_response
)
1212 rfapiMonitorCallbacksOn(bgp
);
1214 rfapiMonitorCallbacksOff(bgp
);
1216 if (rcfg
->use_removes
!= new->use_removes
) {
1217 rcfg
->use_removes
= new->use_removes
;
1218 if (rcfg
->use_removes
)
1219 rfapiMonitorResponseRemovalOn(bgp
);
1221 rfapiMonitorResponseRemovalOff(bgp
);
1226 /*------------------------------------------
1227 * rfapi_rfp_set_cb_methods
1229 * Change registered callback functions for asynchronous notifications
1230 * from RFAPI to the RFP client.
1233 * rfp_start_val value returned by rfp_start
1234 * methods Pointer to struct rfapi_rfp_cb_methods containing
1235 * pointers to callback methods as described above
1239 * ENXIO BGP or VNC not configured
1240 *------------------------------------------*/
1241 int rfapi_rfp_set_cb_methods(void *rfp_start_val
,
1242 struct rfapi_rfp_cb_methods
*methods
)
1247 bgp
= rfapi_bgp_lookup_by_rfp(rfp_start_val
);
1255 h
->rfp_methods
= *methods
;
1260 /***********************************************************************
1262 ***********************************************************************/
1264 * Caller must supply an already-allocated rfd with the "caller"
1265 * fields already set (vn_addr, un_addr, callback, cookie)
1266 * The advertised_prefixes[] array elements should be NULL to
1267 * have this function set them to newly-allocated radix trees.
1269 static int rfapi_open_inner(struct rfapi_descriptor
*rfd
, struct bgp
*bgp
,
1270 struct rfapi
*h
, struct rfapi_nve_group_cfg
*rfg
)
1274 if (h
->flags
& RFAPI_INCALLBACK
)
1278 * Fill in configured fields
1282 * If group's RD is specified as "auto", then fill in based
1283 * on NVE's VN address
1287 if (rfd
->rd
.family
== AF_UNIX
) {
1288 ret
= rfapi_set_autord_from_vn(&rfd
->rd
, &rfd
->vn_addr
);
1292 rfd
->rt_export_list
= (rfg
->rt_export_list
)
1293 ? ecommunity_dup(rfg
->rt_export_list
)
1295 rfd
->response_lifetime
= rfg
->response_lifetime
;
1299 * Fill in BGP peer structure
1301 rfd
->peer
= peer_new(bgp
);
1302 rfd
->peer
->status
= Established
; /* keep bgp core happy */
1303 bgp_sync_delete(rfd
->peer
); /* don't need these */
1304 if (rfd
->peer
->ibuf
) {
1305 stream_free(rfd
->peer
->ibuf
); /* don't need it */
1306 rfd
->peer
->ibuf
= NULL
;
1308 if (rfd
->peer
->obuf
) {
1309 stream_fifo_free(rfd
->peer
->obuf
); /* don't need it */
1310 rfd
->peer
->obuf
= NULL
;
1312 if (rfd
->peer
->work
) {
1313 stream_free(rfd
->peer
->work
); /* don't need it */
1314 rfd
->peer
->work
= NULL
;
1316 { /* base code assumes have valid host pointer */
1320 if (rfd
->vn_addr
.addr_family
== AF_INET
) {
1321 inet_ntop(AF_INET
, &rfd
->vn_addr
.addr
.v4
, buf
, BUFSIZ
);
1322 } else if (rfd
->vn_addr
.addr_family
== AF_INET6
) {
1323 inet_ntop(AF_INET6
, &rfd
->vn_addr
.addr
.v6
, buf
, BUFSIZ
);
1325 rfd
->peer
->host
= XSTRDUP(MTYPE_BGP_PEER_HOST
, buf
);
1327 /* Mark peer as belonging to HD */
1328 SET_FLAG(rfd
->peer
->flags
, PEER_FLAG_IS_RFAPI_HD
);
1331 * Set min prefix lifetime to max value so it will get set
1332 * upon first rfapi_register()
1334 rfd
->min_prefix_lifetime
= UINT32_MAX
;
1337 * Allocate response tables if needed
1339 #define RFD_RTINIT_AFI(rh, ary, afi) \
1342 ary[afi] = route_table_init(); \
1343 ary[afi]->info = rh; \
1347 #define RFD_RTINIT(rh, ary) \
1349 RFD_RTINIT_AFI(rh, ary, AFI_IP); \
1350 RFD_RTINIT_AFI(rh, ary, AFI_IP6); \
1351 RFD_RTINIT_AFI(rh, ary, AFI_L2VPN); \
1354 RFD_RTINIT(rfd
, rfd
->rib
);
1355 RFD_RTINIT(rfd
, rfd
->rib_pending
);
1356 RFD_RTINIT(rfd
, rfd
->rsp_times
);
1359 * Link to Import Table
1361 rfd
->import_table
= rfg
->rfapi_import_table
;
1362 rfd
->import_table
->refcount
+= 1;
1364 rfapiApInit(&rfd
->advertised
);
1367 * add this NVE descriptor to the list of NVEs in the NVE group
1370 rfg
->nves
= list_new();
1372 listnode_add(rfg
->nves
, rfd
);
1374 vnc_direct_bgp_add_nve(bgp
, rfd
);
1375 vnc_zebra_add_nve(bgp
, rfd
);
1380 /* moved from rfapi_register */
1381 int rfapi_init_and_open(struct bgp
*bgp
, struct rfapi_descriptor
*rfd
,
1382 struct rfapi_nve_group_cfg
*rfg
)
1384 struct rfapi
*h
= bgp
->rfapi
;
1385 char buf_vn
[BUFSIZ
];
1386 char buf_un
[BUFSIZ
];
1387 afi_t afi_vn
, afi_un
;
1388 struct prefix pfx_un
;
1389 struct route_node
*rn
;
1392 rfapi_time(&rfd
->open_time
);
1394 if (rfg
->type
== RFAPI_GROUP_CFG_VRF
)
1395 SET_FLAG(rfd
->flags
, RFAPI_HD_FLAG_IS_VRF
);
1397 rfapiRfapiIpAddr2Str(&rfd
->vn_addr
, buf_vn
, BUFSIZ
);
1398 rfapiRfapiIpAddr2Str(&rfd
->un_addr
, buf_un
, BUFSIZ
);
1400 vnc_zlog_debug_verbose("%s: new RFD with VN=%s UN=%s cookie=%p",
1401 __func__
, buf_vn
, buf_un
, rfd
->cookie
);
1403 if (rfg
->type
!= RFAPI_GROUP_CFG_VRF
) /* unclear if needed for VRF */
1405 listnode_add(&h
->descriptors
, rfd
);
1406 if (h
->descriptors
.count
> h
->stat
.max_descriptors
) {
1407 h
->stat
.max_descriptors
= h
->descriptors
.count
;
1411 * attach to UN radix tree
1413 afi_vn
= family2afi(rfd
->vn_addr
.addr_family
);
1414 afi_un
= family2afi(rfd
->un_addr
.addr_family
);
1415 assert(afi_vn
&& afi_un
);
1416 assert(!rfapiRaddr2Qprefix(&rfd
->un_addr
, &pfx_un
));
1418 rn
= route_node_get(&(h
->un
[afi_un
]), &pfx_un
);
1420 rfd
->next
= rn
->info
;
1424 return rfapi_open_inner(rfd
, bgp
, h
, rfg
);
1427 struct rfapi_vn_option
*rfapiVnOptionsDup(struct rfapi_vn_option
*orig
)
1429 struct rfapi_vn_option
*head
= NULL
;
1430 struct rfapi_vn_option
*tail
= NULL
;
1431 struct rfapi_vn_option
*vo
= NULL
;
1433 for (vo
= orig
; vo
; vo
= vo
->next
) {
1434 struct rfapi_vn_option
*new;
1436 new = XCALLOC(MTYPE_RFAPI_VN_OPTION
,
1437 sizeof(struct rfapi_vn_option
));
1438 memcpy(new, vo
, sizeof(struct rfapi_vn_option
));
1450 struct rfapi_un_option
*rfapiUnOptionsDup(struct rfapi_un_option
*orig
)
1452 struct rfapi_un_option
*head
= NULL
;
1453 struct rfapi_un_option
*tail
= NULL
;
1454 struct rfapi_un_option
*uo
= NULL
;
1456 for (uo
= orig
; uo
; uo
= uo
->next
) {
1457 struct rfapi_un_option
*new;
1459 new = XCALLOC(MTYPE_RFAPI_UN_OPTION
,
1460 sizeof(struct rfapi_un_option
));
1461 memcpy(new, uo
, sizeof(struct rfapi_un_option
));
1473 struct bgp_tea_options
*rfapiOptionsDup(struct bgp_tea_options
*orig
)
1475 struct bgp_tea_options
*head
= NULL
;
1476 struct bgp_tea_options
*tail
= NULL
;
1477 struct bgp_tea_options
*hop
= NULL
;
1479 for (hop
= orig
; hop
; hop
= hop
->next
) {
1480 struct bgp_tea_options
*new;
1482 new = XCALLOC(MTYPE_BGP_TEA_OPTIONS
,
1483 sizeof(struct bgp_tea_options
));
1484 memcpy(new, hop
, sizeof(struct bgp_tea_options
));
1487 new->value
= XCALLOC(MTYPE_BGP_TEA_OPTIONS_VALUE
,
1489 memcpy(new->value
, hop
->value
, hop
->length
);
1500 void rfapiFreeBgpTeaOptionChain(struct bgp_tea_options
*p
)
1502 struct bgp_tea_options
*next
;
1508 XFREE(MTYPE_BGP_TEA_OPTIONS_VALUE
, p
->value
);
1511 XFREE(MTYPE_BGP_TEA_OPTIONS
, p
);
1517 void rfapiAdbFree(struct rfapi_adb
*adb
)
1519 XFREE(MTYPE_RFAPI_ADB
, adb
);
1523 rfapi_query_inner(void *handle
, struct rfapi_ip_addr
*target
,
1524 struct rfapi_l2address_option
*l2o
, /* may be NULL */
1525 struct rfapi_next_hop_entry
**ppNextHopEntry
)
1529 struct prefix p_original
;
1530 struct route_node
*rn
;
1531 struct rfapi_descriptor
*rfd
= (struct rfapi_descriptor
*)handle
;
1532 struct bgp
*bgp
= rfd
->bgp
;
1533 struct rfapi_next_hop_entry
*pNHE
= NULL
;
1534 struct rfapi_ip_addr
*self_vn_addr
= NULL
;
1536 int use_eth_resolution
= 0;
1537 struct rfapi_next_hop_entry
*i_nhe
;
1541 vnc_zlog_debug_verbose("%s: No BGP instance, returning ENXIO",
1546 vnc_zlog_debug_verbose("%s: No RFAPI instance, returning ENXIO",
1550 if (bgp
->rfapi
->flags
& RFAPI_INCALLBACK
) {
1551 vnc_zlog_debug_verbose(
1552 "%s: Called during calback, returning EDEADLK",
1557 if (!is_valid_rfd(rfd
)) {
1558 vnc_zlog_debug_verbose("%s: invalid handle, returning EBADF",
1563 rfd
->rsp_counter
++; /* dedup: identify this generation */
1564 rfd
->rsp_time
= rfapi_time(NULL
); /* response content dedup */
1565 rfd
->ftd_last_allowed_time
=
1567 - bgp
->rfapi_cfg
->rfp_cfg
.ftd_advertisement_interval
;
1570 if (!memcmp(l2o
->macaddr
.octet
, rfapi_ethaddr0
.octet
,
1574 /* per t/c Paul/Lou 151022 */
1575 if (!eth_is_0
|| l2o
->logical_net_id
) {
1576 use_eth_resolution
= 1;
1581 *ppNextHopEntry
= NULL
;
1584 * Save original target in prefix form. In case of L2-based queries,
1585 * p_original will be modified to reflect the L2 target
1587 assert(!rfapiRaddr2Qprefix(target
, &p_original
));
1589 if (bgp
->rfapi_cfg
->rfp_cfg
.download_type
== RFAPI_RFP_DOWNLOAD_FULL
) {
1590 /* convert query to 0/0 when full-table download is enabled */
1591 memset((char *)&p
, 0, sizeof(p
));
1592 p
.family
= target
->addr_family
;
1601 prefix2str(&p
, buf
, BUFSIZ
);
1602 buf
[BUFSIZ
- 1] = 0; /* guarantee NUL-terminated */
1603 vnc_zlog_debug_verbose("%s(rfd=%p, target=%s, ppNextHop=%p)",
1604 __func__
, rfd
, buf
, ppNextHopEntry
);
1606 s
= ecommunity_ecom2str(rfd
->import_table
->rt_import_list
,
1607 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1608 vnc_zlog_debug_verbose(
1609 "%s rfd->import_table=%p, rfd->import_table->rt_import_list: %s",
1610 __func__
, rfd
->import_table
, s
);
1611 XFREE(MTYPE_ECOMMUNITY_STR
, s
);
1614 afi
= family2afi(p
.family
);
1617 if (CHECK_FLAG(bgp
->rfapi_cfg
->flags
,
1618 BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP
)) {
1619 self_vn_addr
= &rfd
->vn_addr
;
1622 if (use_eth_resolution
) {
1623 uint32_t logical_net_id
= l2o
->logical_net_id
;
1624 struct ecommunity
*l2com
;
1627 * fix up p_original to contain L2 address
1629 rfapiL2o2Qprefix(l2o
, &p_original
);
1631 l2com
= bgp_rfapi_get_ecommunity_by_lni_label(
1632 bgp
, 1, logical_net_id
, l2o
->label
);
1634 uint8_t *v
= l2com
->val
;
1635 logical_net_id
= (v
[5] << 16) + (v
[6] << 8) + (v
[7]);
1638 * Ethernet/L2-based lookup
1640 * Always returns IT node corresponding to route
1643 if (RFAPI_RFP_DOWNLOAD_FULL
1644 == bgp
->rfapi_cfg
->rfp_cfg
.download_type
) {
1648 rn
= rfapiMonitorEthAdd(
1649 bgp
, rfd
, (eth_is_0
? &rfapi_ethaddr0
: &l2o
->macaddr
),
1653 struct rfapi_ip_prefix rprefix
;
1655 memset(&rprefix
, 0, sizeof(rprefix
));
1656 rprefix
.prefix
.addr_family
= target
->addr_family
;
1657 if (target
->addr_family
== AF_INET
) {
1658 rprefix
.length
= 32;
1660 rprefix
.length
= 128;
1663 pNHE
= rfapiEthRouteTable2NextHopList(
1664 logical_net_id
, &rprefix
,
1665 rfd
->response_lifetime
, self_vn_addr
,
1666 rfd
->rib
[afi
], &p_original
);
1676 rn
= rfapiMonitorAdd(bgp
, rfd
, &p
);
1679 * If target address is 0, this request is special: means to
1680 * return ALL routes in the table
1682 * Monitors for All-Routes queries get put on a special list,
1683 * not in the VPN tree
1685 if (RFAPI_0_PREFIX(&p
)) {
1687 vnc_zlog_debug_verbose("%s: 0-prefix", __func__
);
1690 * Generate nexthop list for caller
1692 pNHE
= rfapiRouteTable2NextHopList(
1693 rfd
->import_table
->imported_vpn
[afi
],
1694 rfd
->response_lifetime
, self_vn_addr
,
1695 rfd
->rib
[afi
], &p_original
);
1700 route_lock_node(rn
); /* so we can unlock below */
1703 * returns locked node. Don't unlock yet because the
1705 * might free it before we're done with it. This
1707 * could occur when rfapiMonitorGetAttachNode() returns
1709 * newly-created default node.
1711 rn
= rfapiMonitorGetAttachNode(rfd
, &p
);
1717 route_unlock_node(rn
);
1718 vnc_zlog_debug_verbose(
1719 "%s: VPN route not found, returning ENOENT", __func__
);
1723 if (VNC_DEBUG(RFAPI_QUERY
)) {
1724 rfapiShowImportTable(NULL
, "query",
1725 rfd
->import_table
->imported_vpn
[afi
], 1);
1728 if (use_eth_resolution
) {
1730 struct rfapi_ip_prefix rprefix
;
1732 memset(&rprefix
, 0, sizeof(rprefix
));
1733 rprefix
.prefix
.addr_family
= target
->addr_family
;
1734 if (target
->addr_family
== AF_INET
) {
1735 rprefix
.length
= 32;
1737 rprefix
.length
= 128;
1740 pNHE
= rfapiEthRouteNode2NextHopList(
1741 rn
, &rprefix
, rfd
->response_lifetime
, self_vn_addr
,
1742 rfd
->rib
[afi
], &p_original
);
1747 * Generate answer to query
1749 pNHE
= rfapiRouteNode2NextHopList(rn
, rfd
->response_lifetime
,
1750 self_vn_addr
, rfd
->rib
[afi
],
1754 route_unlock_node(rn
);
1757 if (ppNextHopEntry
) {
1758 /* only count if caller gets it */
1759 ++bgp
->rfapi
->response_immediate_count
;
1763 vnc_zlog_debug_verbose("%s: NO NHEs, returning ENOENT",
1769 * count nexthops for statistics
1771 for (i_nhe
= pNHE
; i_nhe
; i_nhe
= i_nhe
->next
) {
1772 ++rfd
->stat_count_nh_reachable
;
1775 if (ppNextHopEntry
) {
1776 *ppNextHopEntry
= pNHE
;
1778 rfapi_free_next_hop_list(pNHE
);
1781 vnc_zlog_debug_verbose("%s: success", __func__
);
1786 * support on-the-fly reassignment of an already-open nve to a new
1787 * nve-group in the event that its original nve-group is
1788 * administratively deleted.
1790 static int rfapi_open_rfd(struct rfapi_descriptor
*rfd
, struct bgp
*bgp
)
1792 struct prefix pfx_vn
;
1793 struct prefix pfx_un
;
1794 struct rfapi_nve_group_cfg
*rfg
;
1796 struct rfapi_cfg
*hc
;
1803 hc
= bgp
->rfapi_cfg
;
1807 rc
= rfapiRaddr2Qprefix(&rfd
->vn_addr
, &pfx_vn
);
1810 rc
= rfapiRaddr2Qprefix(&rfd
->un_addr
, &pfx_un
);
1814 * Find the matching nve group config block
1816 rfg
= bgp_rfapi_cfg_match_group(hc
, &pfx_vn
, &pfx_un
);
1822 * check nve group config block for required values
1824 if (!rfg
->rt_export_list
|| !rfg
->rfapi_import_table
) {
1829 rc
= rfapi_open_inner(rfd
, bgp
, h
, rfg
);
1835 * re-advertise registered routes, this time as part of new NVE-group
1837 rfapiApReadvertiseAll(bgp
, rfd
);
1840 * re-attach callbacks to import table
1842 if (!(bgp
->rfapi_cfg
->flags
& BGP_VNC_CONFIG_CALLBACK_DISABLE
)) {
1843 rfapiMonitorAttachImportHd(rfd
);
1849 /*------------------------------------------
1852 * This function initializes a NVE record and associates it with
1853 * the specified VN and underlay network addresses
1856 * rfp_start_val value returned by rfp_start
1857 * vn NVE virtual network address
1859 * un NVE underlay network address
1861 * default_options Default options to use on registrations.
1862 * For now only tunnel type is supported.
1863 * May be overridden per-prefix in rfapi_register().
1864 * Caller owns (rfapi_open() does not free)
1866 * response_cb Pointer to next hop list update callback function or
1867 * NULL when no callbacks are desired.
1869 * userdata Passed to subsequent response_cb invocations.
1872 * response_lifetime The length of time that responses sent to this
1875 * pHandle pointer to location to store rfapi handle. The
1876 * handle must be passed on subsequent rfapi_ calls.
1881 * EEXIST NVE with this {vn,un} already open
1882 * ENOENT No matching nve group config
1883 * ENOMSG Matched nve group config was incomplete
1884 * ENXIO BGP or VNC not configured
1885 * EAFNOSUPPORT Matched nve group specifies auto-assignment of RD,
1886 * but underlay network address is not IPv4
1887 * EDEADLK Called from within a callback procedure
1888 *------------------------------------------*/
1889 int rfapi_open(void *rfp_start_val
, struct rfapi_ip_addr
*vn
,
1890 struct rfapi_ip_addr
*un
,
1891 struct rfapi_un_option
*default_options
,
1892 uint32_t *response_lifetime
,
1893 void *userdata
, /* callback cookie */
1894 rfapi_handle
*pHandle
)
1898 struct rfapi_descriptor
*rfd
;
1899 struct rfapi_cfg
*hc
;
1900 struct rfapi_nve_group_cfg
*rfg
;
1902 struct prefix pfx_vn
;
1903 struct prefix pfx_un
;
1906 rfapi_handle hh
= NULL
;
1907 int reusing_provisional
= 0;
1910 char buf
[2][INET_ADDRSTRLEN
];
1911 vnc_zlog_debug_verbose(
1912 "%s: VN=%s UN=%s", __func__
,
1913 rfapiRfapiIpAddr2Str(vn
, buf
[0], INET_ADDRSTRLEN
),
1914 rfapiRfapiIpAddr2Str(un
, buf
[1], INET_ADDRSTRLEN
));
1920 bgp
= rfapi_bgp_lookup_by_rfp(rfp_start_val
);
1928 hc
= bgp
->rfapi_cfg
;
1932 if (h
->flags
& RFAPI_INCALLBACK
)
1935 rc
= rfapiRaddr2Qprefix(vn
, &pfx_vn
);
1938 rc
= rfapiRaddr2Qprefix(un
, &pfx_un
);
1942 * already have a descriptor with VN and UN?
1944 if (!rfapi_find_handle(bgp
, vn
, un
, &hh
)) {
1946 * we might have set up a handle for static routes before
1947 * this NVE was opened. In that case, reuse the handle
1950 if (!CHECK_FLAG(rfd
->flags
, RFAPI_HD_FLAG_PROVISIONAL
)) {
1955 * reuse provisional descriptor
1958 reusing_provisional
= 1;
1962 * Find the matching nve group config block
1964 rfg
= bgp_rfapi_cfg_match_group(hc
, &pfx_vn
, &pfx_un
);
1966 ++h
->stat
.count_unknown_nves
;
1968 char buf
[2][INET_ADDRSTRLEN
];
1969 zlog_notice("%s: no matching group VN=%s UN=%s",
1971 rfapiRfapiIpAddr2Str(vn
, buf
[0],
1973 rfapiRfapiIpAddr2Str(un
, buf
[1],
1980 * check nve group config block for required values
1982 if (!rfg
->rt_export_list
|| !rfg
->rfapi_import_table
) {
1984 ++h
->stat
.count_unknown_nves
;
1989 * If group config specifies auto-rd assignment, check that
1990 * VN address is IPv4|v6 so we don't fail in rfapi_open_inner().
1991 * Check here so we don't need to unwind memory allocations, &c.
1993 if ((rfg
->rd
.family
== AF_UNIX
) && (vn
->addr_family
!= AF_INET
)
1994 && (vn
->addr_family
!= AF_INET6
)) {
1995 return EAFNOSUPPORT
;
2000 * reusing provisional rfd
2004 rfd
= XCALLOC(MTYPE_RFAPI_DESC
,
2005 sizeof(struct rfapi_descriptor
));
2010 if (default_options
) {
2011 struct rfapi_un_option
*p
;
2013 for (p
= default_options
; p
; p
= p
->next
) {
2014 if ((RFAPI_UN_OPTION_TYPE_PROVISIONAL
== p
->type
)) {
2015 rfd
->flags
|= RFAPI_HD_FLAG_PROVISIONAL
;
2017 if ((RFAPI_UN_OPTION_TYPE_TUNNELTYPE
== p
->type
)) {
2018 rfd
->default_tunneltype_option
= p
->v
.tunnel
;
2024 * Fill in caller fields
2028 rfd
->cookie
= userdata
;
2030 if (!reusing_provisional
) {
2031 rc
= rfapi_init_and_open(bgp
, rfd
, rfg
);
2033 * This can fail only if the VN address is IPv6 and the group
2034 * specified auto-assignment of RDs, which only works for v4,
2035 * and the check above should catch it.
2037 * Another failure possibility is that we were called
2038 * during an rfapi callback. Also checked above.
2043 if (response_lifetime
)
2044 *response_lifetime
= rfd
->response_lifetime
;
2050 * For use with debug functions
2052 static int rfapi_set_response_cb(struct rfapi_descriptor
*rfd
,
2053 rfapi_response_cb_t
*response_cb
)
2055 if (!is_valid_rfd(rfd
))
2057 rfd
->response_cb
= response_cb
;
2064 * Does almost all the work of rfapi_close, except:
2065 * 1. preserves the descriptor (doesn't free it)
2066 * 2. preserves the prefix query list (i.e., rfd->mon list)
2067 * 3. preserves the advertised prefix list (rfd->advertised)
2068 * 4. preserves the rib and rib_pending tables
2070 * The purpose of organizing it this way is to support on-the-fly
2071 * reassignment of an already-open nve to a new nve-group in the
2072 * event that its original nve-group is administratively deleted.
2074 static int rfapi_close_inner(struct rfapi_descriptor
*rfd
, struct bgp
*bgp
)
2077 struct prefix pfx_vn
;
2078 struct prefix_rd prd
; /* currently always 0 for VN->UN */
2080 if (!is_valid_rfd(rfd
))
2083 rc
= rfapiRaddr2Qprefix(&rfd
->vn_addr
, &pfx_vn
);
2084 assert(!rc
); /* should never have bad AF in stored vn address */
2087 * update exported routes to reflect disappearance of this NVE as
2090 vnc_direct_bgp_del_nve(bgp
, rfd
);
2091 vnc_zebra_del_nve(bgp
, rfd
);
2094 * unlink this HD's monitors from import table
2096 rfapiMonitorDetachImportHd(rfd
);
2099 * Unlink from Import Table
2100 * NB rfd->import_table will be NULL if we are closing a stale
2103 if (rfd
->import_table
)
2104 rfapiImportTableRefDelByIt(bgp
, rfd
->import_table
);
2105 rfd
->import_table
= NULL
;
2108 * Construct route distinguisher
2110 memset(&prd
, 0, sizeof(prd
));
2112 prd
.family
= AF_UNSPEC
;
2118 del_vnc_route(rfd
, rfd
->peer
, bgp
, SAFI_ENCAP
,
2119 &pfx_vn
, /* prefix being advertised */
2120 &prd
, /* route distinguisher to use (0 for ENCAP) */
2121 ZEBRA_ROUTE_BGP
, BGP_ROUTE_RFP
, NULL
, 0); /* no kill */
2124 * Construct route distinguisher for VPN routes
2127 prd
.family
= AF_UNSPEC
;
2131 * find all VPN routes associated with this rfd and delete them, too
2133 rfapiApWithdrawAll(bgp
, rfd
);
2136 * remove this nve descriptor from the list of nves
2137 * associated with the nve group
2140 listnode_delete(rfd
->rfg
->nves
, rfd
);
2141 rfd
->rfg
= NULL
; /* XXX mark as orphaned/stale */
2144 if (rfd
->rt_export_list
)
2145 ecommunity_free(&rfd
->rt_export_list
);
2146 rfd
->rt_export_list
= NULL
;
2149 * free peer structure (possibly delayed until its
2150 * refcount reaches zero)
2153 vnc_zlog_debug_verbose("%s: calling peer_delete(%p), #%d",
2154 __func__
, rfd
->peer
, rfd
->peer
->lock
);
2155 peer_delete(rfd
->peer
);
2162 int rfapi_close(void *handle
)
2164 struct rfapi_descriptor
*rfd
= (struct rfapi_descriptor
*)handle
;
2166 struct route_node
*node
;
2170 vnc_zlog_debug_verbose("%s: rfd=%p", __func__
, rfd
);
2172 #if RFAPI_WHO_IS_CALLING_ME
2173 #ifdef HAVE_GLIBC_BACKTRACE
2174 #define RFAPI_DEBUG_BACKTRACE_NENTRIES 5
2176 void *buf
[RFAPI_DEBUG_BACKTRACE_NENTRIES
];
2181 size
= backtrace(buf
, RFAPI_DEBUG_BACKTRACE_NENTRIES
);
2182 syms
= backtrace_symbols(buf
, size
);
2183 for (i
= 0; i
< size
&& i
< RFAPI_DEBUG_BACKTRACE_NENTRIES
;
2185 vnc_zlog_debug_verbose("backtrace[%2d]: %s", i
,
2201 if (!is_valid_rfd(rfd
))
2204 if (h
->flags
& RFAPI_INCALLBACK
) {
2206 * Queue these close requests for processing after callback
2209 if (!CHECK_FLAG(rfd
->flags
,
2210 RFAPI_HD_FLAG_CLOSING_ADMINISTRATIVELY
)) {
2211 work_queue_add(h
->deferred_close_q
, handle
);
2212 vnc_zlog_debug_verbose(
2213 "%s: added handle %p to deferred close queue",
2219 if (CHECK_FLAG(rfd
->flags
, RFAPI_HD_FLAG_CLOSING_ADMINISTRATIVELY
)) {
2221 vnc_zlog_debug_verbose("%s administrative close rfd=%p",
2224 if (h
&& h
->rfp_methods
.close_cb
) {
2225 vnc_zlog_debug_verbose(
2226 "%s calling close callback rfd=%p", __func__
,
2230 * call the callback fairly early so that it can still
2234 * NB RFAPI_INCALLBACK is tested above, so if we reach
2236 * we are not already in the context of a callback.
2238 h
->flags
|= RFAPI_INCALLBACK
;
2239 (*h
->rfp_methods
.close_cb
)(handle
, EIDRM
);
2240 h
->flags
&= ~RFAPI_INCALLBACK
;
2246 * Orphaned descriptors have already done this part, so do
2247 * only for non-orphaned descriptors.
2249 if ((rc
= rfapi_close_inner(rfd
, bgp
)))
2254 * Remove descriptor from UN index
2255 * (remove from chain at node)
2257 rc
= rfapi_find_node(bgp
, &rfd
->vn_addr
, &rfd
->un_addr
, &node
);
2259 struct rfapi_descriptor
*hh
;
2261 if (node
->info
== rfd
) {
2262 node
->info
= rfd
->next
;
2265 for (hh
= node
->info
; hh
; hh
= hh
->next
) {
2266 if (hh
->next
== rfd
) {
2267 hh
->next
= rfd
->next
;
2272 route_unlock_node(node
);
2276 * remove from descriptor list
2278 listnode_delete(&h
->descriptors
, rfd
);
2281 * Delete monitor list items and free monitor structures
2283 (void)rfapiMonitorDelHd(rfd
);
2286 * release advertised prefix data
2288 rfapiApRelease(&rfd
->advertised
);
2291 * Release RFP callback RIB
2298 memset(rfd
, 0, sizeof(struct rfapi_descriptor
));
2299 XFREE(MTYPE_RFAPI_DESC
, rfd
);
2305 * Reopen a nve descriptor. If the descriptor's NVE-group
2306 * does not exist (e.g., if it has been administratively removed),
2307 * reassignment to a new NVE-group is attempted.
2309 * If NVE-group reassignment fails, the descriptor becomes "stale"
2310 * (rfd->rfg == NULL implies "stale:). The only permissible API operation
2311 * on a stale descriptor is rfapi_close(). Any other rfapi_* API operation
2312 * on the descriptor will return ESTALE.
2314 * Reopening a descriptor is a potentially expensive operation, because
2315 * it involves withdrawing any routes advertised by the NVE, withdrawing
2316 * the NVE's route queries, and then re-adding them all after a new
2317 * NVE-group is assigned. There are also possible route-export affects
2318 * caused by deleting and then adding the NVE: advertised prefixes
2319 * and nexthop lists for exported routes can turn over.
2321 int rfapi_reopen(struct rfapi_descriptor
*rfd
, struct bgp
*bgp
)
2326 if ((rc
= rfapi_close_inner(rfd
, bgp
))) {
2329 if ((rc
= rfapi_open_rfd(rfd
, bgp
))) {
2333 assert(!CHECK_FLAG(h
->flags
, RFAPI_INCALLBACK
));
2335 if (CHECK_FLAG(rfd
->flags
,
2336 RFAPI_HD_FLAG_CLOSING_ADMINISTRATIVELY
)
2337 && h
&& h
->rfp_methods
.close_cb
) {
2340 * NB RFAPI_INCALLBACK is tested above, so if we reach
2342 * we are not already in the context of a callback.
2344 h
->flags
|= RFAPI_INCALLBACK
;
2345 (*h
->rfp_methods
.close_cb
)((rfapi_handle
)rfd
, ESTALE
);
2346 h
->flags
&= ~RFAPI_INCALLBACK
;
2353 /***********************************************************************
2355 ***********************************************************************/
2357 * Announce reachability to this prefix via the NVE
2359 int rfapi_register(void *handle
, struct rfapi_ip_prefix
*prefix
,
2360 uint32_t lifetime
, /* host byte order */
2361 struct rfapi_un_option
*options_un
,
2362 struct rfapi_vn_option
*options_vn
,
2363 rfapi_register_action action
)
2365 struct rfapi_descriptor
*rfd
= (struct rfapi_descriptor
*)handle
;
2368 struct prefix
*pfx_ip
= NULL
;
2369 struct prefix_rd prd
;
2371 struct prefix pfx_mac_buf
;
2372 struct prefix
*pfx_mac
= NULL
;
2373 struct prefix pfx_vn_buf
;
2374 const char *action_str
= NULL
;
2375 uint32_t *label
= NULL
;
2376 struct rfapi_vn_option
*vo
;
2377 struct rfapi_l2address_option
*l2o
= NULL
;
2378 struct prefix_rd
*prd_override
= NULL
;
2381 case RFAPI_REGISTER_ADD
:
2384 case RFAPI_REGISTER_WITHDRAW
:
2385 action_str
= "withdraw";
2387 case RFAPI_REGISTER_KILL
:
2388 action_str
= "kill";
2396 * Inspect VN options
2398 for (vo
= options_vn
; vo
; vo
= vo
->next
) {
2399 if (RFAPI_VN_OPTION_TYPE_L2ADDR
== vo
->type
) {
2400 l2o
= &vo
->v
.l2addr
;
2402 if (RFAPI_VN_OPTION_TYPE_INTERNAL_RD
== vo
->type
) {
2403 prd_override
= &vo
->v
.internal_rd
;
2407 /*********************************************************************
2409 *********************************************************************/
2412 * set <p> based on <prefix>
2414 assert(!rfapiRprefix2Qprefix(prefix
, &p
));
2416 afi
= family2afi(prefix
->prefix
.addr_family
);
2423 prefix2str(&p
, buf
, BUFSIZ
);
2424 buf
[BUFSIZ
- 1] = 0; /* guarantee NUL-terminated */
2425 vnc_zlog_debug_verbose(
2426 "%s(rfd=%p, pfx=%s, lifetime=%d, opts_un=%p, opts_vn=%p, action=%s)",
2427 __func__
, rfd
, buf
, lifetime
, options_un
, options_vn
,
2432 * These tests come after the prefix conversion so that we can
2433 * print the prefix in a debug message before failing
2438 vnc_zlog_debug_verbose("%s: no BGP instance: returning ENXIO",
2443 vnc_zlog_debug_verbose("%s: no RFAPI instance: returning ENXIO",
2448 if (RFAPI_REGISTER_ADD
== action
) {
2449 ++bgp
->rfapi
->stat
.count_registrations_failed
;
2451 vnc_zlog_debug_verbose(
2452 "%s: rfd=%p, no RF GRP instance: returning ESTALE",
2457 if (bgp
->rfapi
->flags
& RFAPI_INCALLBACK
) {
2458 if (RFAPI_REGISTER_ADD
== action
) {
2459 ++bgp
->rfapi
->stat
.count_registrations_failed
;
2461 vnc_zlog_debug_verbose("%s: in callback: returning EDEADLK",
2466 if (!is_valid_rfd(rfd
)) {
2467 if (RFAPI_REGISTER_ADD
== action
) {
2468 ++bgp
->rfapi
->stat
.count_registrations_failed
;
2470 vnc_zlog_debug_verbose("%s: invalid handle: returning EBADF",
2476 * Is there a MAC address in this registration?
2478 if (l2o
&& !RFAPI_0_ETHERADDR(&l2o
->macaddr
)) {
2479 rfapiL2o2Qprefix(l2o
, &pfx_mac_buf
);
2480 pfx_mac
= &pfx_mac_buf
;
2484 * Is there an IP prefix in this registration?
2486 if (!(RFAPI_0_PREFIX(&p
) && RFAPI_HOST_PREFIX(&p
))) {
2490 vnc_zlog_debug_verbose(
2491 "%s: missing mac addr that is required for host 0 pfx",
2493 if (RFAPI_REGISTER_ADD
== action
) {
2494 ++bgp
->rfapi
->stat
.count_registrations_failed
;
2498 if (rfapiRaddr2Qprefix(&rfd
->vn_addr
, &pfx_vn_buf
)) {
2499 vnc_zlog_debug_verbose(
2500 "%s: handle has bad vn_addr: returning EBADF",
2502 if (RFAPI_REGISTER_ADD
== action
) {
2503 ++bgp
->rfapi
->stat
.count_registrations_failed
;
2509 if (RFAPI_REGISTER_ADD
== action
) {
2510 ++bgp
->rfapi
->stat
.count_registrations
;
2514 * Figure out if this registration is missing an IP address
2518 * In RFAPI, we use prefixes in family AF_LINK to store
2519 * the MAC addresses. These prefixes are used for the
2520 * list of advertised prefixes and in the RFAPI import
2523 * In BGP proper, we use the prefix matching the NVE's
2524 * VN address with a host prefix-length (i.e., 32 or 128).
2527 if (l2o
&& l2o
->logical_net_id
&& RFAPI_0_PREFIX(&p
)
2528 && RFAPI_HOST_PREFIX(&p
)) {
2530 rfapiL2o2Qprefix(l2o
, &pfx_mac_buf
);
2531 pfx_mac
= &pfx_mac_buf
;
2535 * Construct route distinguisher
2538 prd
= *prd_override
;
2540 memset(&prd
, 0, sizeof(prd
));
2542 prd
.family
= AF_UNSPEC
;
2544 encode_rd_type(RD_TYPE_VNC_ETH
, prd
.val
);
2545 if (l2o
->local_nve_id
2546 || !(rfd
->rfg
->flags
& RFAPI_RFG_L2RD
)) {
2548 * If Local NVE ID is specified in message, use
2550 * (if no local default configured, also use it
2553 prd
.val
[1] = l2o
->local_nve_id
;
2555 if (rfd
->rfg
->l2rd
) {
2557 * locally-configured literal value
2559 prd
.val
[1] = rfd
->rfg
->l2rd
;
2562 * 0 means auto:vn, which means use LSB
2565 if (rfd
->vn_addr
.addr_family
2568 *(((char *)&rfd
->vn_addr
2574 *(((char *)&rfd
->vn_addr
2581 memcpy(prd
.val
+ 2, pfx_mac
->u
.prefix_eth
.octet
, 6);
2584 prd
.family
= AF_UNSPEC
;
2590 if (action
== RFAPI_REGISTER_WITHDRAW
2591 || action
== RFAPI_REGISTER_KILL
) {
2596 * withdraw previous advertisement
2599 rfd
, rfd
->peer
, bgp
, SAFI_MPLS_VPN
,
2601 : &pfx_vn_buf
, /* prefix being advertised */
2602 &prd
, /* route distinguisher (0 for ENCAP) */
2603 ZEBRA_ROUTE_BGP
, BGP_ROUTE_RFP
, NULL
,
2604 action
== RFAPI_REGISTER_KILL
);
2607 == rfapiApDelete(bgp
, rfd
, &p
, pfx_mac
, &prd
,
2610 rfapiTunnelRouteAnnounce(
2611 bgp
, rfd
, &rfd
->max_prefix_lifetime
);
2617 uint32_t local_pref
;
2618 struct ecommunity
*rtlist
= NULL
;
2619 struct ecommunity_val ecom_value
;
2621 if (!rfapiApCount(rfd
)) {
2623 * make sure we advertise tunnel route upon adding the
2629 if (rfapiApAdd(bgp
, rfd
, &p
, pfx_mac
, &prd
, lifetime
,
2630 prefix
->cost
, l2o
)) {
2634 vnc_zlog_debug_verbose("%s: adv_tunnel = %d", __func__
,
2637 vnc_zlog_debug_verbose("%s: announcing tunnel route",
2639 rfapiTunnelRouteAnnounce(bgp
, rfd
,
2640 &rfd
->max_prefix_lifetime
);
2643 vnc_zlog_debug_verbose("%s: calling add_vnc_route", __func__
);
2645 local_pref
= rfp_cost_to_localpref(prefix
->cost
);
2647 if (l2o
&& l2o
->label
)
2648 label
= &l2o
->label
;
2651 struct ecommunity
*l2com
= NULL
;
2654 l2com
= bgp_rfapi_get_ecommunity_by_lni_label(
2655 bgp
, 1, l2o
->logical_net_id
, *label
);
2658 rtlist
= ecommunity_dup(l2com
);
2661 * If mac address is set, add an RT based on the
2664 memset((char *)&ecom_value
, 0,
2665 sizeof(ecom_value
));
2666 ecom_value
.val
[1] = ECOMMUNITY_ROUTE_TARGET
;
2668 (l2o
->logical_net_id
>> 16) & 0xff;
2670 (l2o
->logical_net_id
>> 8) & 0xff;
2672 (l2o
->logical_net_id
>> 0) & 0xff;
2673 rtlist
= ecommunity_new();
2674 ecommunity_add_val(rtlist
, &ecom_value
);
2678 uint16_t val
= l2o
->tag_id
;
2679 memset((char *)&ecom_value
, 0,
2680 sizeof(ecom_value
));
2681 ecom_value
.val
[1] = ECOMMUNITY_ROUTE_TARGET
;
2682 if (as
> BGP_AS_MAX
) {
2684 ECOMMUNITY_ENCODE_AS4
;
2685 ecom_value
.val
[2] = (as
>> 24) & 0xff;
2686 ecom_value
.val
[3] = (as
>> 16) & 0xff;
2687 ecom_value
.val
[4] = (as
>> 8) & 0xff;
2688 ecom_value
.val
[5] = as
& 0xff;
2691 ECOMMUNITY_ENCODE_AS
;
2692 ecom_value
.val
[2] = (as
>> 8) & 0xff;
2693 ecom_value
.val
[3] = as
& 0xff;
2695 ecom_value
.val
[6] = (val
>> 8) & 0xff;
2696 ecom_value
.val
[7] = val
& 0xff;
2698 rtlist
= ecommunity_new();
2699 ecommunity_add_val(rtlist
, &ecom_value
);
2704 * advertise prefix via tunnel endpoint
2707 rfd
, /* rfapi descr, for export list & backref */
2708 bgp
, /* which bgp instance */
2709 SAFI_MPLS_VPN
, /* which SAFI */
2711 : &pfx_vn_buf
), /* prefix being advertised */
2712 &prd
, /* route distinguisher to use (0 for ENCAP) */
2713 &rfd
->vn_addr
, /* nexthop */
2715 &lifetime
, /* prefix lifetime -> Tunnel Encap attr */
2716 NULL
, options_un
, /* rfapi un options */
2717 options_vn
, /* rfapi vn options */
2718 (rtlist
? rtlist
: rfd
->rt_export_list
), NULL
, /* med */
2719 label
, /* label: default */
2720 ZEBRA_ROUTE_BGP
, BGP_ROUTE_RFP
, 0);
2723 ecommunity_free(&rtlist
); /* sets rtlist = NULL */
2726 vnc_zlog_debug_verbose("%s: success", __func__
);
2730 int rfapi_query(void *handle
, struct rfapi_ip_addr
*target
,
2731 struct rfapi_l2address_option
*l2o
, /* may be NULL */
2732 struct rfapi_next_hop_entry
**ppNextHopEntry
)
2734 struct rfapi_descriptor
*rfd
= (struct rfapi_descriptor
*)handle
;
2735 struct bgp
*bgp
= rfd
->bgp
;
2738 assert(ppNextHopEntry
);
2739 *ppNextHopEntry
= NULL
;
2741 if (bgp
&& bgp
->rfapi
) {
2742 bgp
->rfapi
->stat
.count_queries
++;
2746 if (bgp
&& bgp
->rfapi
)
2747 ++bgp
->rfapi
->stat
.count_queries_failed
;
2751 if ((rc
= rfapi_query_inner(handle
, target
, l2o
, ppNextHopEntry
))) {
2752 if (bgp
&& bgp
->rfapi
)
2753 ++bgp
->rfapi
->stat
.count_queries_failed
;
2758 int rfapi_query_done(rfapi_handle handle
, struct rfapi_ip_addr
*target
)
2762 struct rfapi_descriptor
*rfd
= (struct rfapi_descriptor
*)handle
;
2763 struct bgp
*bgp
= rfd
->bgp
;
2769 rc
= rfapiRaddr2Qprefix(target
, &p
);
2772 if (!is_valid_rfd(rfd
))
2776 if (!bgp
|| !bgp
->rfapi
)
2779 if (bgp
->rfapi
->flags
& RFAPI_INCALLBACK
)
2782 rfapiMonitorDel(bgp
, rfd
, &p
);
2787 int rfapi_query_done_all(rfapi_handle handle
, int *count
)
2789 struct rfapi_descriptor
*rfd
= (struct rfapi_descriptor
*)handle
;
2790 struct bgp
*bgp
= rfd
->bgp
;
2797 if (!is_valid_rfd(rfd
))
2801 if (!bgp
|| !bgp
->rfapi
)
2804 if (bgp
->rfapi
->flags
& RFAPI_INCALLBACK
)
2807 num
= rfapiMonitorDelHd(rfd
);
2815 void rfapi_free_next_hop_list(struct rfapi_next_hop_entry
*list
)
2817 struct rfapi_next_hop_entry
*nh
;
2818 struct rfapi_next_hop_entry
*next
;
2820 for (nh
= list
; nh
; nh
= next
) {
2822 rfapi_un_options_free(nh
->un_options
);
2823 nh
->un_options
= NULL
;
2824 rfapi_vn_options_free(nh
->vn_options
);
2825 nh
->vn_options
= NULL
;
2826 XFREE(MTYPE_RFAPI_NEXTHOP
, nh
);
2831 * NULL handle => return total count across all nves
2833 uint32_t rfapi_monitor_count(void *handle
)
2835 struct bgp
*bgp
= bgp_get_default();
2839 struct rfapi_descriptor
*rfd
=
2840 (struct rfapi_descriptor
*)handle
;
2841 count
= rfd
->monitor_count
;
2844 if (!bgp
|| !bgp
->rfapi
)
2847 count
= bgp
->rfapi
->monitor_count
;
2853 /***********************************************************************
2855 ***********************************************************************/
2857 DEFUN (debug_rfapi_show_nves
,
2858 debug_rfapi_show_nves_cmd
,
2859 "debug rfapi-dev show nves",
2863 "NVE Information\n")
2865 rfapiPrintMatchingDescriptors(vty
, NULL
, NULL
);
2870 debug_rfapi_show_nves_vn_un
,
2871 debug_rfapi_show_nves_vn_un_cmd
,
2872 "debug rfapi-dev show nves <vn|un> <A.B.C.D|X:X::X:X>", /* prefix also ok */
2877 "Specify virtual network\n"
2878 "Specify underlay network interface\n"
2884 if (!str2prefix(argv
[5]->arg
, &pfx
)) {
2885 vty_out(vty
, "Malformed address \"%s\"\n", argv
[5]->arg
);
2886 return CMD_WARNING_CONFIG_FAILED
;
2888 if (pfx
.family
!= AF_INET
&& pfx
.family
!= AF_INET6
) {
2889 vty_out(vty
, "Invalid address \"%s\"\n", argv
[5]->arg
);
2890 return CMD_WARNING_CONFIG_FAILED
;
2893 if (argv
[4]->arg
[0] == 'u') {
2894 rfapiPrintMatchingDescriptors(vty
, NULL
, &pfx
);
2896 rfapiPrintMatchingDescriptors(vty
, &pfx
, NULL
);
2902 * Note: this function does not flush vty output, so if it is called
2903 * with a stream pointing to a vty, the user will have to type something
2904 * before the callback output shows up
2906 static void test_nexthops_callback(
2907 // struct rfapi_ip_addr *target,
2908 struct rfapi_next_hop_entry
*next_hops
, void *userdata
)
2910 void *stream
= userdata
;
2912 int (*fp
)(void *, const char *, ...);
2915 const char *vty_newline
;
2917 if (rfapiStream2Vty(stream
, &fp
, &vty
, &out
, &vty_newline
) == 0)
2920 fp(out
, "Nexthops Callback, Target=(");
2921 // rfapiPrintRfapiIpAddr(stream, target);
2924 rfapiPrintNhl(stream
, next_hops
);
2926 rfapi_free_next_hop_list(next_hops
);
2929 DEFUN (debug_rfapi_open
,
2930 debug_rfapi_open_cmd
,
2931 "debug rfapi-dev open vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X>",
2935 "indicate vn addr follows\n"
2936 "virtual network interface IPv4 address\n"
2937 "virtual network interface IPv6 address\n"
2938 "indicate xt addr follows\n"
2939 "underlay network interface IPv4 address\n"
2940 "underlay network interface IPv6 address\n")
2942 struct rfapi_ip_addr vn
;
2943 struct rfapi_ip_addr un
;
2946 rfapi_handle handle
;
2951 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[4]->arg
, &vn
)))
2957 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[6]->arg
, &un
)))
2960 rc
= rfapi_open(rfapi_get_rfp_start_val_by_bgp(bgp_get_default()), &vn
,
2961 &un
, /*&uo */ NULL
, &lifetime
, NULL
, &handle
);
2963 vty_out(vty
, "rfapi_open: status %d, handle %p, lifetime %d\n", rc
,
2966 rc
= rfapi_set_response_cb(handle
, test_nexthops_callback
);
2968 vty_out(vty
, "rfapi_set_response_cb: status %d\n", rc
);
2974 DEFUN (debug_rfapi_close_vn_un
,
2975 debug_rfapi_close_vn_un_cmd
,
2976 "debug rfapi-dev close vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X>",
2980 "indicate vn addr follows\n"
2981 "virtual network interface IPv4 address\n"
2982 "virtual network interface IPv6 address\n"
2983 "indicate xt addr follows\n"
2984 "underlay network interface IPv4 address\n"
2985 "underlay network interface IPv6 address\n")
2987 struct rfapi_ip_addr vn
;
2988 struct rfapi_ip_addr un
;
2989 rfapi_handle handle
;
2995 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[4]->arg
, &vn
)))
3002 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[6]->arg
, &un
)))
3006 if (rfapi_find_handle_vty(vty
, &vn
, &un
, &handle
)) {
3007 vty_out(vty
, "can't locate handle matching vn=%s, un=%s\n",
3008 argv
[4]->arg
, argv
[6]->arg
);
3009 return CMD_WARNING_CONFIG_FAILED
;
3012 rc
= rfapi_close(handle
);
3014 vty_out(vty
, "rfapi_close(handle=%p): status %d\n", handle
, rc
);
3019 DEFUN (debug_rfapi_close_rfd
,
3020 debug_rfapi_close_rfd_cmd
,
3021 "debug rfapi-dev close rfd HANDLE",
3025 "indicate handle follows\n" "rfapi handle in hexadecimal\n")
3027 rfapi_handle handle
;
3029 char *endptr
= NULL
;
3031 handle
= (rfapi_handle
)(uintptr_t)(strtoull(argv
[4]->arg
, &endptr
, 16));
3033 if (*endptr
!= '\0' || (uintptr_t)handle
== UINTPTR_MAX
) {
3034 vty_out(vty
, "Invalid value: %s\n", argv
[4]->arg
);
3035 return CMD_WARNING_CONFIG_FAILED
;
3038 rc
= rfapi_close(handle
);
3040 vty_out(vty
, "rfapi_close(handle=%p): status %d\n", handle
, rc
);
3045 DEFUN (debug_rfapi_register_vn_un
,
3046 debug_rfapi_register_vn_un_cmd
,
3047 "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",
3051 "indicate vn addr follows\n"
3052 "virtual network IPv4 interface address\n"
3053 "virtual network IPv6 interface address\n"
3054 "indicate un addr follows\n"
3055 "underlay network IPv4 interface address\n"
3056 "underlay network IPv6 interface address\n"
3057 "indicate prefix follows\n"
3060 "indicate lifetime follows\n"
3063 struct rfapi_ip_addr vn
;
3064 struct rfapi_ip_addr un
;
3065 rfapi_handle handle
;
3068 struct rfapi_ip_prefix hpfx
;
3074 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[4]->arg
, &vn
)))
3081 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[6]->arg
, &un
)))
3085 if (rfapi_find_handle_vty(vty
, &vn
, &un
, &handle
)) {
3086 vty_out(vty
, "can't locate handle matching vn=%s, un=%s\n",
3087 argv
[4]->arg
, argv
[6]->arg
);
3088 return CMD_WARNING_CONFIG_FAILED
;
3092 * Get prefix to advertise
3094 if (!str2prefix(argv
[8]->arg
, &pfx
)) {
3095 vty_out(vty
, "Malformed prefix \"%s\"\n", argv
[8]->arg
);
3096 return CMD_WARNING_CONFIG_FAILED
;
3098 if (pfx
.family
!= AF_INET
&& pfx
.family
!= AF_INET6
) {
3099 vty_out(vty
, "Bad family for prefix \"%s\"\n", argv
[8]->arg
);
3100 return CMD_WARNING_CONFIG_FAILED
;
3102 rfapiQprefix2Rprefix(&pfx
, &hpfx
);
3104 if (strmatch(argv
[10]->text
, "infinite")) {
3105 lifetime
= RFAPI_INFINITE_LIFETIME
;
3107 lifetime
= strtoul(argv
[10]->arg
, NULL
, 10);
3111 rc
= rfapi_register(handle
, &hpfx
, lifetime
, NULL
, NULL
, 0);
3113 vty_out(vty
, "rfapi_register failed with rc=%d (%s)\n", rc
,
3120 DEFUN (debug_rfapi_register_vn_un_l2o
,
3121 debug_rfapi_register_vn_un_l2o_cmd
,
3122 "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)",
3126 "indicate vn addr follows\n"
3127 "virtual network IPv4 interface address\n"
3128 "virtual network IPv6 interface address\n"
3129 "indicate un addr follows\n"
3130 "underlay network IPv4 interface address\n"
3131 "underlay network IPv6 interface address\n"
3132 "indicate prefix follows\n"
3135 "indicate lifetime follows\n"
3136 "Seconds of lifetime\n"
3137 "indicate MAC address follows\n"
3139 "indicate lni follows\n"
3140 "lni value range\n")
3142 struct rfapi_ip_addr vn
;
3143 struct rfapi_ip_addr un
;
3144 rfapi_handle handle
;
3147 struct rfapi_ip_prefix hpfx
;
3149 struct rfapi_vn_option optary
[10]; /* XXX must be big enough */
3150 struct rfapi_vn_option
*opt
= NULL
;
3156 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[4]->arg
, &vn
)))
3163 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[6]->arg
, &un
)))
3167 if (rfapi_find_handle_vty(vty
, &vn
, &un
, &handle
)) {
3168 vty_out(vty
, "can't locate handle matching vn=%s, un=%s\n",
3169 argv
[4]->arg
, argv
[6]->arg
);
3170 return CMD_WARNING_CONFIG_FAILED
;
3174 * Get prefix to advertise
3176 if (!str2prefix(argv
[8]->arg
, &pfx
)) {
3177 vty_out(vty
, "Malformed prefix \"%s\"\n", argv
[8]->arg
);
3178 return CMD_WARNING_CONFIG_FAILED
;
3180 if (pfx
.family
!= AF_INET
&& pfx
.family
!= AF_INET6
) {
3181 vty_out(vty
, "Bad family for prefix \"%s\"\n", argv
[8]->arg
);
3182 return CMD_WARNING_CONFIG_FAILED
;
3184 rfapiQprefix2Rprefix(&pfx
, &hpfx
);
3186 if (strmatch(argv
[10]->text
, "infinite")) {
3187 lifetime
= RFAPI_INFINITE_LIFETIME
;
3189 lifetime
= strtoul(argv
[10]->arg
, NULL
, 10);
3192 /* L2 option parsing START */
3193 memset(optary
, 0, sizeof(optary
));
3194 optary
[opt_next
].v
.l2addr
.logical_net_id
=
3195 strtoul(argv
[14]->arg
, NULL
, 10);
3196 if ((rc
= rfapiStr2EthAddr(argv
[12]->arg
,
3197 &optary
[opt_next
].v
.l2addr
.macaddr
))) {
3198 vty_out(vty
, "Bad mac address \"%s\"\n", argv
[12]->arg
);
3199 return CMD_WARNING_CONFIG_FAILED
;
3201 optary
[opt_next
].type
= RFAPI_VN_OPTION_TYPE_L2ADDR
;
3203 optary
[opt_next
- 1].next
= optary
+ opt_next
;
3208 /* L2 option parsing END */
3211 rc
= rfapi_register(handle
, &hpfx
, lifetime
, NULL
/* &uo */, opt
, 0);
3213 vty_out(vty
, "rfapi_register failed with rc=%d (%s)\n", rc
,
3221 DEFUN (debug_rfapi_unregister_vn_un
,
3222 debug_rfapi_unregister_vn_un_cmd
,
3223 "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>",
3227 "indicate vn addr follows\n"
3228 "virtual network interface address\n"
3229 "indicate xt addr follows\n"
3230 "underlay network interface address\n"
3231 "indicate prefix follows\n" "prefix")
3233 struct rfapi_ip_addr vn
;
3234 struct rfapi_ip_addr un
;
3235 rfapi_handle handle
;
3237 struct rfapi_ip_prefix hpfx
;
3243 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[4]->arg
, &vn
)))
3250 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[6]->arg
, &un
)))
3254 if (rfapi_find_handle_vty(vty
, &vn
, &un
, &handle
)) {
3255 vty_out(vty
, "can't locate handle matching vn=%s, un=%s\n",
3256 argv
[4]->arg
, argv
[6]->arg
);
3257 return CMD_WARNING_CONFIG_FAILED
;
3261 * Get prefix to advertise
3263 if (!str2prefix(argv
[8]->arg
, &pfx
)) {
3264 vty_out(vty
, "Malformed prefix \"%s\"\n", argv
[8]->arg
);
3265 return CMD_WARNING_CONFIG_FAILED
;
3267 if (pfx
.family
!= AF_INET
&& pfx
.family
!= AF_INET6
) {
3268 vty_out(vty
, "Bad family for prefix \"%s\"\n", argv
[8]->arg
);
3269 return CMD_WARNING_CONFIG_FAILED
;
3271 rfapiQprefix2Rprefix(&pfx
, &hpfx
);
3273 rfapi_register(handle
, &hpfx
, 0, NULL
, NULL
, 1);
3278 DEFUN (debug_rfapi_query_vn_un
,
3279 debug_rfapi_query_vn_un_cmd
,
3280 "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>",
3284 "indicate vn addr follows\n"
3285 "virtual network interface IPv4 address\n"
3286 "virtual network interface IPv6 address\n"
3287 "indicate un addr follows\n"
3290 "indicate target follows\n"
3291 "target IPv4 address\n"
3292 "target IPv6 address\n")
3294 struct rfapi_ip_addr vn
;
3295 struct rfapi_ip_addr un
;
3296 struct rfapi_ip_addr target
;
3297 rfapi_handle handle
;
3299 struct rfapi_next_hop_entry
*pNextHopEntry
;
3304 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[4]->arg
, &vn
)))
3311 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[6]->arg
, &un
)))
3318 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[8]->arg
, &target
)))
3322 if (rfapi_find_handle_vty(vty
, &vn
, &un
, &handle
)) {
3323 vty_out(vty
, "can't locate handle matching vn=%s, un=%s\n",
3324 argv
[4]->arg
, argv
[6]->arg
);
3325 return CMD_WARNING_CONFIG_FAILED
;
3329 * options parameter not used? Set to NULL for now
3331 rc
= rfapi_query(handle
, &target
, NULL
, &pNextHopEntry
);
3334 vty_out(vty
, "rfapi_query failed with rc=%d (%s)\n", rc
,
3338 * print nexthop list
3340 test_nexthops_callback(/*&target, */ pNextHopEntry
,
3341 vty
); /* frees nh list! */
3348 DEFUN (debug_rfapi_query_vn_un_l2o
,
3349 debug_rfapi_query_vn_un_l2o_cmd
,
3350 "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",
3354 "indicate vn addr follows\n"
3355 "virtual network interface IPv4 address\n"
3356 "virtual network interface IPv6 address\n"
3357 "indicate xt addr follows\n"
3358 "underlay network interface IPv4 address\n"
3359 "underlay network interface IPv6 address\n"
3360 "logical network ID follows\n"
3361 "logical network ID\n"
3362 "indicate target MAC addr follows\n"
3363 "target MAC addr\n")
3365 struct rfapi_ip_addr vn
;
3366 struct rfapi_ip_addr un
;
3367 struct rfapi_ip_addr target
;
3368 rfapi_handle handle
;
3370 struct rfapi_next_hop_entry
*pNextHopEntry
;
3371 struct rfapi_l2address_option l2o_buf
;
3372 struct bgp_tea_options hopt
;
3378 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[4]->arg
, &vn
)))
3385 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[6]->arg
, &un
)))
3389 #if 0 /* there is no IP target arg here ?????? */
3393 if ((rc
= rfapiCliGetRfapiIpAddr (vty
, argv
[2], &target
)))
3396 vty_out(vty
, "%% This command is broken.\n");
3397 return CMD_WARNING_CONFIG_FAILED
;
3400 if (rfapi_find_handle_vty(vty
, &vn
, &un
, &handle
)) {
3401 vty_out(vty
, "can't locate handle matching vn=%s, un=%s\n",
3402 argv
[4]->arg
, argv
[6]->arg
);
3403 return CMD_WARNING_CONFIG_FAILED
;
3407 * Set up L2 parameters
3409 memset(&l2o_buf
, 0, sizeof(l2o_buf
));
3410 if (rfapiStr2EthAddr(argv
[10]->arg
, &l2o_buf
.macaddr
)) {
3411 vty_out(vty
, "Bad mac address \"%s\"\n", argv
[10]->arg
);
3412 return CMD_WARNING_CONFIG_FAILED
;
3415 l2o_buf
.logical_net_id
= strtoul(argv
[8]->arg
, NULL
, 10);
3417 /* construct option chain */
3419 memset(valbuf
, 0, sizeof(valbuf
));
3420 memcpy(valbuf
, &l2o_buf
.macaddr
.octet
, ETHER_ADDR_LEN
);
3421 valbuf
[11] = (l2o_buf
.logical_net_id
>> 16) & 0xff;
3422 valbuf
[12] = (l2o_buf
.logical_net_id
>> 8) & 0xff;
3423 valbuf
[13] = l2o_buf
.logical_net_id
& 0xff;
3425 memset(&hopt
, 0, sizeof(hopt
));
3426 hopt
.options_count
= 1;
3427 hopt
.options_length
= sizeof(valbuf
); /* is this right? */
3428 hopt
.type
= RFAPI_VN_OPTION_TYPE_L2ADDR
;
3429 hopt
.length
= sizeof(valbuf
);
3430 hopt
.value
= valbuf
;
3434 * options parameter not used? Set to NULL for now
3436 rc
= rfapi_query(handle
, &target
, &l2o_buf
, &pNextHopEntry
);
3439 vty_out(vty
, "rfapi_query failed with rc=%d (%s)\n", rc
,
3443 * print nexthop list
3445 /* TBD enhance to print L2 information */
3446 test_nexthops_callback(/*&target, */ pNextHopEntry
,
3447 vty
); /* frees nh list! */
3454 DEFUN (debug_rfapi_query_done_vn_un
,
3455 debug_rfapi_query_vn_un_done_cmd
,
3456 "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>",
3459 "rfapi_query_done\n"
3460 "rfapi_query_done\n"
3461 "indicate vn addr follows\n"
3462 "virtual network interface IPv4 address\n"
3463 "virtual network interface IPv6 address\n"
3464 "indicate xt addr follows\n"
3465 "underlay network interface IPv4 address\n"
3466 "underlay network interface IPv6 address\n"
3467 "indicate target follows\n"
3468 "Target IPv4 address\n"
3469 "Target IPv6 address\n")
3471 struct rfapi_ip_addr vn
;
3472 struct rfapi_ip_addr un
;
3473 struct rfapi_ip_addr target
;
3474 rfapi_handle handle
;
3480 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[5]->arg
, &vn
)))
3487 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[7]->arg
, &un
)))
3494 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[9]->arg
, &target
)))
3498 if (rfapi_find_handle_vty(vty
, &vn
, &un
, &handle
)) {
3499 vty_out(vty
, "can't locate handle matching vn=%s, un=%s\n",
3500 argv
[5]->arg
, argv
[7]->arg
);
3501 return CMD_WARNING_CONFIG_FAILED
;
3505 * options parameter not used? Set to NULL for now
3507 rc
= rfapi_query_done(handle
, &target
);
3509 vty_out(vty
, "rfapi_query_done returned %d\n", rc
);
3514 DEFUN (debug_rfapi_show_import
,
3515 debug_rfapi_show_import_cmd
,
3516 "debug rfapi-dev show import",
3524 struct rfapi_import_table
*it
;
3529 * Show all import tables
3532 bgp
= bgp_get_default(); /* assume 1 instance for now */
3534 vty_out(vty
, "No BGP instance\n");
3535 return CMD_WARNING_CONFIG_FAILED
;
3540 vty_out(vty
, "No RFAPI instance\n");
3541 return CMD_WARNING_CONFIG_FAILED
;
3545 * Iterate over all import tables; do a filtered import
3546 * for the afi/safi combination
3550 for (it
= h
->imports
; it
; it
= it
->next
) {
3551 s
= ecommunity_ecom2str(it
->rt_import_list
,
3552 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3553 vty_out(vty
, "Import Table %p, RTs: %s\n", it
, s
);
3554 XFREE(MTYPE_ECOMMUNITY_STR
, s
);
3556 rfapiShowImportTable(vty
, "IP VPN", it
->imported_vpn
[AFI_IP
],
3558 rfapiShowImportTable(vty
, "IP ENCAP",
3559 it
->imported_encap
[AFI_IP
], 0);
3560 rfapiShowImportTable(vty
, "IP6 VPN", it
->imported_vpn
[AFI_IP6
],
3562 rfapiShowImportTable(vty
, "IP6 ENCAP",
3563 it
->imported_encap
[AFI_IP6
], 0);
3566 if (h
->import_mac
) {
3567 void *cursor
= NULL
;
3569 uintptr_t lni_as_ptr
;
3573 for (rc
= skiplist_next(h
->import_mac
, (void **)&lni_as_ptr
,
3574 (void **)&it
, &cursor
);
3576 rc
= skiplist_next(h
->import_mac
, (void **)&lni_as_ptr
,
3577 (void **)&it
, &cursor
)) {
3579 if (it
->imported_vpn
[AFI_L2VPN
]) {
3583 "\nLNI-based Ethernet Tables:\n");
3586 snprintf(buf
, BUFSIZ
, "L2VPN LNI=%u", lni
);
3587 rfapiShowImportTable(
3588 vty
, buf
, it
->imported_vpn
[AFI_L2VPN
],
3594 rfapiShowImportTable(vty
, "CE IT - IP VPN",
3595 h
->it_ce
->imported_vpn
[AFI_IP
], 1);
3600 DEFUN (debug_rfapi_show_import_vn_un
,
3601 debug_rfapi_show_import_vn_un_cmd
,
3602 "debug rfapi-dev show import vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X>",
3607 "indicate vn addr follows\n"
3608 "virtual network interface IPv4 address\n"
3609 "virtual network interface IPv6 address\n"
3610 "indicate xt addr follows\n"
3611 "underlay network interface IPv4 address\n"
3612 "underlay network interface IPv6 address\n")
3614 struct rfapi_ip_addr vn
;
3615 struct rfapi_ip_addr un
;
3616 rfapi_handle handle
;
3618 struct rfapi_descriptor
*rfd
;
3623 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[5]->arg
, &vn
)))
3630 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[7]->arg
, &un
)))
3634 if (rfapi_find_handle_vty(vty
, &vn
, &un
, &handle
)) {
3635 vty_out(vty
, "can't locate handle matching vn=%s, un=%s\n",
3636 argv
[5]->arg
, argv
[7]->arg
);
3637 return CMD_WARNING_CONFIG_FAILED
;
3640 rfd
= (struct rfapi_descriptor
*)handle
;
3642 rfapiShowImportTable(vty
, "IP VPN",
3643 rfd
->import_table
->imported_vpn
[AFI_IP
], 1);
3644 rfapiShowImportTable(vty
, "IP ENCAP",
3645 rfd
->import_table
->imported_encap
[AFI_IP
], 0);
3646 rfapiShowImportTable(vty
, "IP6 VPN",
3647 rfd
->import_table
->imported_vpn
[AFI_IP6
], 1);
3648 rfapiShowImportTable(vty
, "IP6 ENCAP",
3649 rfd
->import_table
->imported_encap
[AFI_IP6
], 0);
3654 DEFUN (debug_rfapi_response_omit_self
,
3655 debug_rfapi_response_omit_self_cmd
,
3656 "debug rfapi-dev response-omit-self <on|off>",
3659 "Omit self in RFP responses\n"
3660 "filter out self from responses\n" "leave self in responses\n")
3662 struct bgp
*bgp
= bgp_get_default();
3665 vty_out(vty
, "No BGP process is configured\n");
3666 return CMD_WARNING_CONFIG_FAILED
;
3668 if (!bgp
->rfapi_cfg
) {
3669 vty_out(vty
, "VNC not configured\n");
3670 return CMD_WARNING_CONFIG_FAILED
;
3673 if (strmatch(argv
[3]->text
, "on"))
3674 SET_FLAG(bgp
->rfapi_cfg
->flags
,
3675 BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP
);
3677 UNSET_FLAG(bgp
->rfapi_cfg
->flags
,
3678 BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP
);
3684 #ifdef RFAPI_DEBUG_SKIPLIST_CLI
3686 #include "lib/skiplist.h"
3687 DEFUN (skiplist_test_cli
,
3688 skiplist_test_cli_cmd
,
3690 "skiplist command\n"
3698 DEFUN (skiplist_debug_cli
,
3699 skiplist_debug_cli_cmd
,
3701 "skiplist command\n"
3704 skiplist_debug(vty
, NULL
);
3708 #endif /* RFAPI_DEBUG_SKIPLIST_CLI */
3710 void rfapi_init(void)
3712 bgp_rfapi_cfg_init();
3715 install_element(ENABLE_NODE
, &debug_rfapi_show_import_cmd
);
3716 install_element(ENABLE_NODE
, &debug_rfapi_show_import_vn_un_cmd
);
3718 install_element(ENABLE_NODE
, &debug_rfapi_open_cmd
);
3719 install_element(ENABLE_NODE
, &debug_rfapi_close_vn_un_cmd
);
3720 install_element(ENABLE_NODE
, &debug_rfapi_close_rfd_cmd
);
3721 install_element(ENABLE_NODE
, &debug_rfapi_register_vn_un_cmd
);
3722 install_element(ENABLE_NODE
, &debug_rfapi_unregister_vn_un_cmd
);
3723 install_element(ENABLE_NODE
, &debug_rfapi_query_vn_un_cmd
);
3724 install_element(ENABLE_NODE
, &debug_rfapi_query_vn_un_done_cmd
);
3725 install_element(ENABLE_NODE
, &debug_rfapi_query_vn_un_l2o_cmd
);
3727 install_element(ENABLE_NODE
, &debug_rfapi_response_omit_self_cmd
);
3729 /* Need the following show commands for gpz test scripts */
3730 install_element(ENABLE_NODE
, &debug_rfapi_show_nves_cmd
);
3731 install_element(ENABLE_NODE
, &debug_rfapi_show_nves_vn_un_cmd
);
3732 install_element(ENABLE_NODE
, &debug_rfapi_register_vn_un_l2o_cmd
);
3734 #ifdef RFAPI_DEBUG_SKIPLIST_CLI
3735 install_element(ENABLE_NODE
, &skiplist_test_cli_cmd
);
3736 install_element(ENABLE_NODE
, &skiplist_debug_cli_cmd
);
3743 static void rfapi_print_exported(struct bgp
*bgp
)
3745 struct bgp_node
*rdn
;
3746 struct bgp_node
*rn
;
3747 struct bgp_info
*bi
;
3752 for (rdn
= bgp_table_top(bgp
->rib
[AFI_IP
][SAFI_MPLS_VPN
]); rdn
;
3753 rdn
= bgp_route_next(rdn
)) {
3756 fprintf(stderr
, "%s: vpn rdn=%p\n", __func__
, rdn
);
3757 for (rn
= bgp_table_top(rdn
->info
); rn
;
3758 rn
= bgp_route_next(rn
)) {
3761 fprintf(stderr
, "%s: rn=%p\n", __func__
, rn
);
3762 for (bi
= rn
->info
; bi
; bi
= bi
->next
) {
3763 rfapiPrintBi((void *)2, bi
); /* 2 => stderr */
3767 for (rdn
= bgp_table_top(bgp
->rib
[AFI_IP
][SAFI_ENCAP
]); rdn
;
3768 rdn
= bgp_route_next(rdn
)) {
3771 fprintf(stderr
, "%s: encap rdn=%p\n", __func__
, rdn
);
3772 for (rn
= bgp_table_top(rdn
->info
); rn
;
3773 rn
= bgp_route_next(rn
)) {
3776 fprintf(stderr
, "%s: rn=%p\n", __func__
, rn
);
3777 for (bi
= rn
->info
; bi
; bi
= bi
->next
) {
3778 rfapiPrintBi((void *)2, bi
); /* 2 => stderr */
3783 #endif /* defined(DEBUG_RFAPI) */
3786 * Free all memory to prepare for clean exit as seen by valgrind memcheck
3788 void rfapi_delete(struct bgp
*bgp
)
3790 extern void rfp_clear_vnc_nve_all(void); /* can't fix correctly yet */
3793 * This clears queries and registered routes, and closes nves
3796 rfp_clear_vnc_nve_all();
3797 bgp_rfapi_cfg_destroy(bgp
, bgp
->rfapi_cfg
);
3798 bgp
->rfapi_cfg
= NULL
;
3799 bgp_rfapi_destroy(bgp
, bgp
->rfapi
);
3803 * show what's left in the BGP MPLSVPN RIB
3805 rfapi_print_exported(bgp
);
3809 int rfapi_set_autord_from_vn(struct prefix_rd
*rd
, struct rfapi_ip_addr
*vn
)
3811 vnc_zlog_debug_verbose("%s: auto-assigning RD", __func__
);
3812 if (vn
->addr_family
!= AF_INET
&& vn
->addr_family
!= AF_INET6
) {
3813 vnc_zlog_debug_verbose(
3814 "%s: can't auto-assign RD, VN addr family is not IPv4"
3817 return EAFNOSUPPORT
;
3819 rd
->family
= AF_UNSPEC
;
3821 rd
->val
[1] = RD_TYPE_IP
;
3822 if (vn
->addr_family
== AF_INET
) {
3823 memcpy(rd
->val
+ 2, &vn
->addr
.v4
.s_addr
, 4);
3824 } else { /* is v6 */
3825 memcpy(rd
->val
+ 2, &vn
->addr
.v6
.s6_addr32
[3],
3826 4); /* low order 4 bytes */
3831 prefix_rd2str(rd
, buf
, BUFSIZ
);
3832 buf
[BUFSIZ
- 1] = 0;
3833 vnc_zlog_debug_verbose("%s: auto-RD is set to %s", __func__
,
3839 /*------------------------------------------
3840 * rfapi_bgp_lookup_by_rfp
3842 * Find bgp instance pointer based on value returned by rfp_start
3845 * rfp_start_val value returned by rfp_startor
3846 * NULL (=get default instance)
3852 * bgp bgp instance pointer
3855 --------------------------------------------*/
3856 struct bgp
*rfapi_bgp_lookup_by_rfp(void *rfp_start_val
)
3858 struct bgp
*bgp
= NULL
;
3859 struct listnode
*node
, *nnode
;
3861 if (rfp_start_val
== NULL
)
3862 bgp
= bgp_get_default();
3864 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
3865 if (bgp
->rfapi
!= NULL
3866 && bgp
->rfapi
->rfp
== rfp_start_val
)
3871 /*------------------------------------------
3872 * rfapi_get_rfp_start_val_by_bgp
3874 * Find bgp instance pointer based on value returned by rfp_start
3877 * bgp bgp instance pointer
3886 --------------------------------------------*/
3887 void *rfapi_get_rfp_start_val_by_bgp(struct bgp
*bgp
)
3889 if (!bgp
|| !bgp
->rfapi
)
3891 return bgp
->rfapi
->rfp
;
3894 /***********************************************************************
3895 * RFP group specific configuration
3896 ***********************************************************************/
3897 static void *rfapi_rfp_get_or_init_group_config_default(struct rfapi_cfg
*rfc
,
3901 if (rfc
->default_rfp_cfg
== NULL
&& size
> 0) {
3902 rfc
->default_rfp_cfg
= XCALLOC(MTYPE_RFAPI_RFP_GROUP_CFG
, size
);
3903 vnc_zlog_debug_verbose("%s: allocated, size=%d", __func__
,
3906 return rfc
->default_rfp_cfg
;
3909 static void *rfapi_rfp_get_or_init_group_config_nve(struct rfapi_cfg
*rfc
,
3913 struct rfapi_nve_group_cfg
*rfg
=
3914 VTY_GET_CONTEXT_SUB(rfapi_nve_group_cfg
);
3916 /* make sure group is still in list */
3917 if (!rfg
|| !listnode_lookup(rfc
->nve_groups_sequential
, rfg
)) {
3918 /* Not in list anymore */
3919 vty_out(vty
, "Current NVE group no longer exists\n");
3923 if (rfg
->rfp_cfg
== NULL
&& size
> 0) {
3924 rfg
->rfp_cfg
= XCALLOC(MTYPE_RFAPI_RFP_GROUP_CFG
, size
);
3925 vnc_zlog_debug_verbose("%s: allocated, size=%d", __func__
,
3928 return rfg
->rfp_cfg
;
3931 static void *rfapi_rfp_get_or_init_group_config_l2(struct rfapi_cfg
*rfc
,
3935 struct rfapi_l2_group_cfg
*rfg
=
3936 VTY_GET_CONTEXT_SUB(rfapi_l2_group_cfg
);
3938 /* make sure group is still in list */
3939 if (!rfg
|| !listnode_lookup(rfc
->l2_groups
, rfg
)) {
3940 /* Not in list anymore */
3941 vty_out(vty
, "Current L2 group no longer exists\n");
3944 if (rfg
->rfp_cfg
== NULL
&& size
> 0) {
3945 rfg
->rfp_cfg
= XCALLOC(MTYPE_RFAPI_RFP_GROUP_CFG
, size
);
3946 vnc_zlog_debug_verbose("%s: allocated, size=%d", __func__
,
3949 return rfg
->rfp_cfg
;
3952 /*------------------------------------------
3953 * rfapi_rfp_init_group_config_ptr_vty
3955 * This is used to init or return a previously init'ed group specific
3956 * configuration pointer. Group is identified by vty context.
3957 * NOTE: size is ignored when a previously init'ed value is returned.
3958 * RFAPI frees rfp_cfg_group when group is deleted during reconfig,
3959 * bgp restart or shutdown.
3962 * rfp_start_val value returned by rfp_start
3964 * vty quagga vty context
3965 * size number of bytes to allocation
3971 * rfp_cfg_group NULL or Pointer to configuration structure
3972 --------------------------------------------*/
3973 void *rfapi_rfp_init_group_config_ptr_vty(void *rfp_start_val
,
3974 rfapi_rfp_cfg_group_type type
,
3975 struct vty
*vty
, uint32_t size
)
3980 if (rfp_start_val
== NULL
|| vty
== NULL
)
3983 bgp
= rfapi_bgp_lookup_by_rfp(rfp_start_val
);
3984 if (!bgp
|| !bgp
->rfapi_cfg
)
3988 case RFAPI_RFP_CFG_GROUP_DEFAULT
:
3989 ret
= rfapi_rfp_get_or_init_group_config_default(bgp
->rfapi_cfg
,
3992 case RFAPI_RFP_CFG_GROUP_NVE
:
3993 ret
= rfapi_rfp_get_or_init_group_config_nve(bgp
->rfapi_cfg
,
3996 case RFAPI_RFP_CFG_GROUP_L2
:
3997 ret
= rfapi_rfp_get_or_init_group_config_l2(bgp
->rfapi_cfg
, vty
,
4001 zlog_err("%s: Unknown group type=%d", __func__
, type
);
4002 /* should never happen */
4003 assert("Unknown type" == NULL
);
4009 /*------------------------------------------
4010 * rfapi_rfp_get_group_config_ptr_vty
4012 * This is used to get group specific configuration pointer.
4013 * Group is identified by type and vty context.
4014 * RFAPI frees rfp_cfg_group when group is deleted during reconfig,
4015 * bgp restart or shutdown.
4018 * rfp_start_val value returned by rfp_start
4020 * vty quagga vty context
4026 * rfp_cfg_group Pointer to configuration structure
4027 --------------------------------------------*/
4028 void *rfapi_rfp_get_group_config_ptr_vty(void *rfp_start_val
,
4029 rfapi_rfp_cfg_group_type type
,
4032 return rfapi_rfp_init_group_config_ptr_vty(rfp_start_val
, type
, vty
, 0);
4036 rfapi_rfp_get_group_config_name_nve(struct rfapi_cfg
*rfc
, const char *name
,
4038 rfp_group_config_search_cb_t
*search_cb
)
4040 struct rfapi_nve_group_cfg
*rfg
;
4041 struct listnode
*node
;
4043 for (ALL_LIST_ELEMENTS_RO(rfc
->nve_groups_sequential
, node
, rfg
)) {
4044 if (!strcmp(rfg
->name
, name
) && /* name match */
4045 (search_cb
== NULL
|| !search_cb(criteria
, rfg
->rfp_cfg
)))
4046 return rfg
->rfp_cfg
;
4052 rfapi_rfp_get_group_config_name_l2(struct rfapi_cfg
*rfc
, const char *name
,
4054 rfp_group_config_search_cb_t
*search_cb
)
4056 struct rfapi_l2_group_cfg
*rfg
;
4057 struct listnode
*node
;
4059 for (ALL_LIST_ELEMENTS_RO(rfc
->l2_groups
, node
, rfg
)) {
4060 if (!strcmp(rfg
->name
, name
) && /* name match */
4061 (search_cb
== NULL
|| !search_cb(criteria
, rfg
->rfp_cfg
)))
4062 return rfg
->rfp_cfg
;
4067 /*------------------------------------------
4068 * rfapi_rfp_get_group_config_ptr_name
4070 * This is used to get group specific configuration pointer.
4071 * Group is identified by type and name context.
4072 * RFAPI frees rfp_cfg_group when group is deleted during reconfig,
4073 * bgp restart or shutdown.
4076 * rfp_start_val value returned by rfp_start
4079 * criteria RFAPI caller provided serach criteria
4080 * search_cb optional rfp_group_config_search_cb_t
4086 * rfp_cfg_group Pointer to configuration structure
4087 --------------------------------------------*/
4088 void *rfapi_rfp_get_group_config_ptr_name(
4089 void *rfp_start_val
, rfapi_rfp_cfg_group_type type
, const char *name
,
4090 void *criteria
, rfp_group_config_search_cb_t
*search_cb
)
4095 if (rfp_start_val
== NULL
|| name
== NULL
)
4098 bgp
= rfapi_bgp_lookup_by_rfp(rfp_start_val
);
4099 if (!bgp
|| !bgp
->rfapi_cfg
)
4103 case RFAPI_RFP_CFG_GROUP_DEFAULT
:
4104 ret
= bgp
->rfapi_cfg
->default_rfp_cfg
;
4106 case RFAPI_RFP_CFG_GROUP_NVE
:
4107 ret
= rfapi_rfp_get_group_config_name_nve(bgp
->rfapi_cfg
, name
,
4108 criteria
, search_cb
);
4110 case RFAPI_RFP_CFG_GROUP_L2
:
4111 ret
= rfapi_rfp_get_group_config_name_l2(bgp
->rfapi_cfg
, name
,
4112 criteria
, search_cb
);
4115 zlog_err("%s: Unknown group type=%d", __func__
, type
);
4116 /* should never happen */
4117 assert("Unknown type" == NULL
);
4123 /*------------------------------------------
4124 * rfapi_rfp_get_l2_group_config_ptr_lni
4126 * This is used to get group specific configuration pointer.
4127 * Group is identified by type and logical network identifier.
4128 * RFAPI frees rfp_cfg_group when group is deleted during reconfig,
4129 * bgp restart or shutdown.
4132 * rfp_start_val value returned by rfp_start
4134 * logical_net_id group logical network identifier
4135 * criteria RFAPI caller provided serach criteria
4136 * search_cb optional rfp_group_config_search_cb_t
4142 * rfp_cfg_group Pointer to configuration structure
4143 --------------------------------------------*/
4145 rfapi_rfp_get_l2_group_config_ptr_lni(void *rfp_start_val
,
4146 uint32_t logical_net_id
, void *criteria
,
4147 rfp_group_config_search_cb_t
*search_cb
)
4150 struct rfapi_l2_group_cfg
*rfg
;
4151 struct listnode
*node
;
4153 if (rfp_start_val
== NULL
)
4156 bgp
= rfapi_bgp_lookup_by_rfp(rfp_start_val
);
4157 if (!bgp
|| !bgp
->rfapi_cfg
)
4160 for (ALL_LIST_ELEMENTS_RO(bgp
->rfapi_cfg
->l2_groups
, node
, rfg
)) {
4161 if (rfg
->logical_net_id
== logical_net_id
4162 && (search_cb
== NULL
4163 || !search_cb(criteria
, rfg
->rfp_cfg
))) {
4164 if (rfg
->rfp_cfg
== NULL
)
4165 vnc_zlog_debug_verbose(
4166 "%s: returning rfp group config for lni=0",
4168 return rfg
->rfp_cfg
;