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
);
2606 if (0 == rfapiApDelete(bgp
, rfd
, &p
, pfx_mac
, &prd
,
2609 rfapiTunnelRouteAnnounce(
2610 bgp
, rfd
, &rfd
->max_prefix_lifetime
);
2616 uint32_t local_pref
;
2617 struct ecommunity
*rtlist
= NULL
;
2618 struct ecommunity_val ecom_value
;
2620 if (!rfapiApCount(rfd
)) {
2622 * make sure we advertise tunnel route upon adding the
2628 if (rfapiApAdd(bgp
, rfd
, &p
, pfx_mac
, &prd
, lifetime
,
2629 prefix
->cost
, l2o
)) {
2633 vnc_zlog_debug_verbose("%s: adv_tunnel = %d", __func__
,
2636 vnc_zlog_debug_verbose("%s: announcing tunnel route",
2638 rfapiTunnelRouteAnnounce(bgp
, rfd
,
2639 &rfd
->max_prefix_lifetime
);
2642 vnc_zlog_debug_verbose("%s: calling add_vnc_route", __func__
);
2644 local_pref
= rfp_cost_to_localpref(prefix
->cost
);
2646 if (l2o
&& l2o
->label
)
2647 label
= &l2o
->label
;
2650 struct ecommunity
*l2com
= NULL
;
2653 l2com
= bgp_rfapi_get_ecommunity_by_lni_label(
2654 bgp
, 1, l2o
->logical_net_id
, *label
);
2657 rtlist
= ecommunity_dup(l2com
);
2660 * If mac address is set, add an RT based on the
2663 memset((char *)&ecom_value
, 0,
2664 sizeof(ecom_value
));
2665 ecom_value
.val
[1] = ECOMMUNITY_ROUTE_TARGET
;
2667 (l2o
->logical_net_id
>> 16) & 0xff;
2669 (l2o
->logical_net_id
>> 8) & 0xff;
2671 (l2o
->logical_net_id
>> 0) & 0xff;
2672 rtlist
= ecommunity_new();
2673 ecommunity_add_val(rtlist
, &ecom_value
);
2677 uint16_t val
= l2o
->tag_id
;
2678 memset((char *)&ecom_value
, 0,
2679 sizeof(ecom_value
));
2680 ecom_value
.val
[1] = ECOMMUNITY_ROUTE_TARGET
;
2681 if (as
> BGP_AS_MAX
) {
2683 ECOMMUNITY_ENCODE_AS4
;
2684 ecom_value
.val
[2] = (as
>> 24) & 0xff;
2685 ecom_value
.val
[3] = (as
>> 16) & 0xff;
2686 ecom_value
.val
[4] = (as
>> 8) & 0xff;
2687 ecom_value
.val
[5] = as
& 0xff;
2690 ECOMMUNITY_ENCODE_AS
;
2691 ecom_value
.val
[2] = (as
>> 8) & 0xff;
2692 ecom_value
.val
[3] = as
& 0xff;
2694 ecom_value
.val
[6] = (val
>> 8) & 0xff;
2695 ecom_value
.val
[7] = val
& 0xff;
2697 rtlist
= ecommunity_new();
2698 ecommunity_add_val(rtlist
, &ecom_value
);
2703 * advertise prefix via tunnel endpoint
2706 rfd
, /* rfapi descr, for export list & backref */
2707 bgp
, /* which bgp instance */
2708 SAFI_MPLS_VPN
, /* which SAFI */
2710 : &pfx_vn_buf
), /* prefix being advertised */
2711 &prd
, /* route distinguisher to use (0 for ENCAP) */
2712 &rfd
->vn_addr
, /* nexthop */
2714 &lifetime
, /* prefix lifetime -> Tunnel Encap attr */
2715 NULL
, options_un
, /* rfapi un options */
2716 options_vn
, /* rfapi vn options */
2717 (rtlist
? rtlist
: rfd
->rt_export_list
), NULL
, /* med */
2718 label
, /* label: default */
2719 ZEBRA_ROUTE_BGP
, BGP_ROUTE_RFP
, 0);
2722 ecommunity_free(&rtlist
); /* sets rtlist = NULL */
2725 vnc_zlog_debug_verbose("%s: success", __func__
);
2729 int rfapi_query(void *handle
, struct rfapi_ip_addr
*target
,
2730 struct rfapi_l2address_option
*l2o
, /* may be NULL */
2731 struct rfapi_next_hop_entry
**ppNextHopEntry
)
2733 struct rfapi_descriptor
*rfd
= (struct rfapi_descriptor
*)handle
;
2734 struct bgp
*bgp
= rfd
->bgp
;
2737 assert(ppNextHopEntry
);
2738 *ppNextHopEntry
= NULL
;
2740 if (bgp
&& bgp
->rfapi
) {
2741 bgp
->rfapi
->stat
.count_queries
++;
2745 if (bgp
&& bgp
->rfapi
)
2746 ++bgp
->rfapi
->stat
.count_queries_failed
;
2750 if ((rc
= rfapi_query_inner(handle
, target
, l2o
, ppNextHopEntry
))) {
2751 if (bgp
&& bgp
->rfapi
)
2752 ++bgp
->rfapi
->stat
.count_queries_failed
;
2757 int rfapi_query_done(rfapi_handle handle
, struct rfapi_ip_addr
*target
)
2761 struct rfapi_descriptor
*rfd
= (struct rfapi_descriptor
*)handle
;
2762 struct bgp
*bgp
= rfd
->bgp
;
2768 rc
= rfapiRaddr2Qprefix(target
, &p
);
2771 if (!is_valid_rfd(rfd
))
2775 if (!bgp
|| !bgp
->rfapi
)
2778 if (bgp
->rfapi
->flags
& RFAPI_INCALLBACK
)
2781 rfapiMonitorDel(bgp
, rfd
, &p
);
2786 int rfapi_query_done_all(rfapi_handle handle
, int *count
)
2788 struct rfapi_descriptor
*rfd
= (struct rfapi_descriptor
*)handle
;
2789 struct bgp
*bgp
= rfd
->bgp
;
2796 if (!is_valid_rfd(rfd
))
2800 if (!bgp
|| !bgp
->rfapi
)
2803 if (bgp
->rfapi
->flags
& RFAPI_INCALLBACK
)
2806 num
= rfapiMonitorDelHd(rfd
);
2814 void rfapi_free_next_hop_list(struct rfapi_next_hop_entry
*list
)
2816 struct rfapi_next_hop_entry
*nh
;
2817 struct rfapi_next_hop_entry
*next
;
2819 for (nh
= list
; nh
; nh
= next
) {
2821 rfapi_un_options_free(nh
->un_options
);
2822 nh
->un_options
= NULL
;
2823 rfapi_vn_options_free(nh
->vn_options
);
2824 nh
->vn_options
= NULL
;
2825 XFREE(MTYPE_RFAPI_NEXTHOP
, nh
);
2830 * NULL handle => return total count across all nves
2832 uint32_t rfapi_monitor_count(void *handle
)
2834 struct bgp
*bgp
= bgp_get_default();
2838 struct rfapi_descriptor
*rfd
=
2839 (struct rfapi_descriptor
*)handle
;
2840 count
= rfd
->monitor_count
;
2843 if (!bgp
|| !bgp
->rfapi
)
2846 count
= bgp
->rfapi
->monitor_count
;
2852 /***********************************************************************
2854 ***********************************************************************/
2856 DEFUN (debug_rfapi_show_nves
,
2857 debug_rfapi_show_nves_cmd
,
2858 "debug rfapi-dev show nves",
2862 "NVE Information\n")
2864 rfapiPrintMatchingDescriptors(vty
, NULL
, NULL
);
2869 debug_rfapi_show_nves_vn_un
,
2870 debug_rfapi_show_nves_vn_un_cmd
,
2871 "debug rfapi-dev show nves <vn|un> <A.B.C.D|X:X::X:X>", /* prefix also ok */
2876 "Specify virtual network\n"
2877 "Specify underlay network interface\n"
2883 if (!str2prefix(argv
[5]->arg
, &pfx
)) {
2884 vty_out(vty
, "Malformed address \"%s\"\n", argv
[5]->arg
);
2885 return CMD_WARNING_CONFIG_FAILED
;
2887 if (pfx
.family
!= AF_INET
&& pfx
.family
!= AF_INET6
) {
2888 vty_out(vty
, "Invalid address \"%s\"\n", argv
[5]->arg
);
2889 return CMD_WARNING_CONFIG_FAILED
;
2892 if (argv
[4]->arg
[0] == 'u') {
2893 rfapiPrintMatchingDescriptors(vty
, NULL
, &pfx
);
2895 rfapiPrintMatchingDescriptors(vty
, &pfx
, NULL
);
2901 * Note: this function does not flush vty output, so if it is called
2902 * with a stream pointing to a vty, the user will have to type something
2903 * before the callback output shows up
2905 static void test_nexthops_callback(
2906 // struct rfapi_ip_addr *target,
2907 struct rfapi_next_hop_entry
*next_hops
, void *userdata
)
2909 void *stream
= userdata
;
2911 int (*fp
)(void *, const char *, ...);
2914 const char *vty_newline
;
2916 if (rfapiStream2Vty(stream
, &fp
, &vty
, &out
, &vty_newline
) == 0)
2919 fp(out
, "Nexthops Callback, Target=(");
2920 // rfapiPrintRfapiIpAddr(stream, target);
2923 rfapiPrintNhl(stream
, next_hops
);
2925 rfapi_free_next_hop_list(next_hops
);
2928 DEFUN (debug_rfapi_open
,
2929 debug_rfapi_open_cmd
,
2930 "debug rfapi-dev open vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X>",
2934 "indicate vn addr follows\n"
2935 "virtual network interface IPv4 address\n"
2936 "virtual network interface IPv6 address\n"
2937 "indicate xt addr follows\n"
2938 "underlay network interface IPv4 address\n"
2939 "underlay network interface IPv6 address\n")
2941 struct rfapi_ip_addr vn
;
2942 struct rfapi_ip_addr un
;
2945 rfapi_handle handle
;
2950 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[4]->arg
, &vn
)))
2956 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[6]->arg
, &un
)))
2959 rc
= rfapi_open(rfapi_get_rfp_start_val_by_bgp(bgp_get_default()), &vn
,
2960 &un
, /*&uo */ NULL
, &lifetime
, NULL
, &handle
);
2962 vty_out(vty
, "rfapi_open: status %d, handle %p, lifetime %d\n", rc
,
2965 rc
= rfapi_set_response_cb(handle
, test_nexthops_callback
);
2967 vty_out(vty
, "rfapi_set_response_cb: status %d\n", rc
);
2973 DEFUN (debug_rfapi_close_vn_un
,
2974 debug_rfapi_close_vn_un_cmd
,
2975 "debug rfapi-dev close vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X>",
2979 "indicate vn addr follows\n"
2980 "virtual network interface IPv4 address\n"
2981 "virtual network interface IPv6 address\n"
2982 "indicate xt addr follows\n"
2983 "underlay network interface IPv4 address\n"
2984 "underlay network interface IPv6 address\n")
2986 struct rfapi_ip_addr vn
;
2987 struct rfapi_ip_addr un
;
2988 rfapi_handle handle
;
2994 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[4]->arg
, &vn
)))
3001 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[6]->arg
, &un
)))
3005 if (rfapi_find_handle_vty(vty
, &vn
, &un
, &handle
)) {
3006 vty_out(vty
, "can't locate handle matching vn=%s, un=%s\n",
3007 argv
[4]->arg
, argv
[6]->arg
);
3008 return CMD_WARNING_CONFIG_FAILED
;
3011 rc
= rfapi_close(handle
);
3013 vty_out(vty
, "rfapi_close(handle=%p): status %d\n", handle
, rc
);
3018 DEFUN (debug_rfapi_close_rfd
,
3019 debug_rfapi_close_rfd_cmd
,
3020 "debug rfapi-dev close rfd HANDLE",
3024 "indicate handle follows\n" "rfapi handle in hexadecimal\n")
3026 rfapi_handle handle
;
3028 char *endptr
= NULL
;
3030 handle
= (rfapi_handle
)(uintptr_t)(strtoull(argv
[4]->arg
, &endptr
, 16));
3032 if (*endptr
!= '\0' || (uintptr_t)handle
== UINTPTR_MAX
) {
3033 vty_out(vty
, "Invalid value: %s\n", argv
[4]->arg
);
3034 return CMD_WARNING_CONFIG_FAILED
;
3037 rc
= rfapi_close(handle
);
3039 vty_out(vty
, "rfapi_close(handle=%p): status %d\n", handle
, rc
);
3044 DEFUN (debug_rfapi_register_vn_un
,
3045 debug_rfapi_register_vn_un_cmd
,
3046 "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",
3050 "indicate vn addr follows\n"
3051 "virtual network IPv4 interface address\n"
3052 "virtual network IPv6 interface address\n"
3053 "indicate un addr follows\n"
3054 "underlay network IPv4 interface address\n"
3055 "underlay network IPv6 interface address\n"
3056 "indicate prefix follows\n"
3059 "indicate lifetime follows\n"
3062 struct rfapi_ip_addr vn
;
3063 struct rfapi_ip_addr un
;
3064 rfapi_handle handle
;
3067 struct rfapi_ip_prefix hpfx
;
3073 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[4]->arg
, &vn
)))
3080 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[6]->arg
, &un
)))
3084 if (rfapi_find_handle_vty(vty
, &vn
, &un
, &handle
)) {
3085 vty_out(vty
, "can't locate handle matching vn=%s, un=%s\n",
3086 argv
[4]->arg
, argv
[6]->arg
);
3087 return CMD_WARNING_CONFIG_FAILED
;
3091 * Get prefix to advertise
3093 if (!str2prefix(argv
[8]->arg
, &pfx
)) {
3094 vty_out(vty
, "Malformed prefix \"%s\"\n", argv
[8]->arg
);
3095 return CMD_WARNING_CONFIG_FAILED
;
3097 if (pfx
.family
!= AF_INET
&& pfx
.family
!= AF_INET6
) {
3098 vty_out(vty
, "Bad family for prefix \"%s\"\n", argv
[8]->arg
);
3099 return CMD_WARNING_CONFIG_FAILED
;
3101 rfapiQprefix2Rprefix(&pfx
, &hpfx
);
3103 if (strmatch(argv
[10]->text
, "infinite")) {
3104 lifetime
= RFAPI_INFINITE_LIFETIME
;
3106 lifetime
= strtoul(argv
[10]->arg
, NULL
, 10);
3110 rc
= rfapi_register(handle
, &hpfx
, lifetime
, NULL
, NULL
, 0);
3112 vty_out(vty
, "rfapi_register failed with rc=%d (%s)\n", rc
,
3119 DEFUN (debug_rfapi_register_vn_un_l2o
,
3120 debug_rfapi_register_vn_un_l2o_cmd
,
3121 "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)",
3125 "indicate vn addr follows\n"
3126 "virtual network IPv4 interface address\n"
3127 "virtual network IPv6 interface address\n"
3128 "indicate un addr follows\n"
3129 "underlay network IPv4 interface address\n"
3130 "underlay network IPv6 interface address\n"
3131 "indicate prefix follows\n"
3134 "indicate lifetime follows\n"
3135 "Seconds of lifetime\n"
3136 "indicate MAC address follows\n"
3138 "indicate lni follows\n"
3139 "lni value range\n")
3141 struct rfapi_ip_addr vn
;
3142 struct rfapi_ip_addr un
;
3143 rfapi_handle handle
;
3146 struct rfapi_ip_prefix hpfx
;
3148 struct rfapi_vn_option optary
[10]; /* XXX must be big enough */
3149 struct rfapi_vn_option
*opt
= NULL
;
3155 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[4]->arg
, &vn
)))
3162 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[6]->arg
, &un
)))
3166 if (rfapi_find_handle_vty(vty
, &vn
, &un
, &handle
)) {
3167 vty_out(vty
, "can't locate handle matching vn=%s, un=%s\n",
3168 argv
[4]->arg
, argv
[6]->arg
);
3169 return CMD_WARNING_CONFIG_FAILED
;
3173 * Get prefix to advertise
3175 if (!str2prefix(argv
[8]->arg
, &pfx
)) {
3176 vty_out(vty
, "Malformed prefix \"%s\"\n", argv
[8]->arg
);
3177 return CMD_WARNING_CONFIG_FAILED
;
3179 if (pfx
.family
!= AF_INET
&& pfx
.family
!= AF_INET6
) {
3180 vty_out(vty
, "Bad family for prefix \"%s\"\n", argv
[8]->arg
);
3181 return CMD_WARNING_CONFIG_FAILED
;
3183 rfapiQprefix2Rprefix(&pfx
, &hpfx
);
3185 if (strmatch(argv
[10]->text
, "infinite")) {
3186 lifetime
= RFAPI_INFINITE_LIFETIME
;
3188 lifetime
= strtoul(argv
[10]->arg
, NULL
, 10);
3191 /* L2 option parsing START */
3192 memset(optary
, 0, sizeof(optary
));
3193 optary
[opt_next
].v
.l2addr
.logical_net_id
=
3194 strtoul(argv
[14]->arg
, NULL
, 10);
3195 if ((rc
= rfapiStr2EthAddr(argv
[12]->arg
,
3196 &optary
[opt_next
].v
.l2addr
.macaddr
))) {
3197 vty_out(vty
, "Bad mac address \"%s\"\n", argv
[12]->arg
);
3198 return CMD_WARNING_CONFIG_FAILED
;
3200 optary
[opt_next
].type
= RFAPI_VN_OPTION_TYPE_L2ADDR
;
3202 optary
[opt_next
- 1].next
= optary
+ opt_next
;
3207 /* L2 option parsing END */
3210 rc
= rfapi_register(handle
, &hpfx
, lifetime
, NULL
/* &uo */, opt
, 0);
3212 vty_out(vty
, "rfapi_register failed with rc=%d (%s)\n", rc
,
3220 DEFUN (debug_rfapi_unregister_vn_un
,
3221 debug_rfapi_unregister_vn_un_cmd
,
3222 "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>",
3226 "indicate vn addr follows\n"
3227 "virtual network interface address\n"
3228 "indicate xt addr follows\n"
3229 "underlay network interface address\n"
3230 "indicate prefix follows\n" "prefix")
3232 struct rfapi_ip_addr vn
;
3233 struct rfapi_ip_addr un
;
3234 rfapi_handle handle
;
3236 struct rfapi_ip_prefix hpfx
;
3242 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[4]->arg
, &vn
)))
3249 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[6]->arg
, &un
)))
3253 if (rfapi_find_handle_vty(vty
, &vn
, &un
, &handle
)) {
3254 vty_out(vty
, "can't locate handle matching vn=%s, un=%s\n",
3255 argv
[4]->arg
, argv
[6]->arg
);
3256 return CMD_WARNING_CONFIG_FAILED
;
3260 * Get prefix to advertise
3262 if (!str2prefix(argv
[8]->arg
, &pfx
)) {
3263 vty_out(vty
, "Malformed prefix \"%s\"\n", argv
[8]->arg
);
3264 return CMD_WARNING_CONFIG_FAILED
;
3266 if (pfx
.family
!= AF_INET
&& pfx
.family
!= AF_INET6
) {
3267 vty_out(vty
, "Bad family for prefix \"%s\"\n", argv
[8]->arg
);
3268 return CMD_WARNING_CONFIG_FAILED
;
3270 rfapiQprefix2Rprefix(&pfx
, &hpfx
);
3272 rfapi_register(handle
, &hpfx
, 0, NULL
, NULL
, 1);
3277 DEFUN (debug_rfapi_query_vn_un
,
3278 debug_rfapi_query_vn_un_cmd
,
3279 "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>",
3283 "indicate vn addr follows\n"
3284 "virtual network interface IPv4 address\n"
3285 "virtual network interface IPv6 address\n"
3286 "indicate un addr follows\n"
3289 "indicate target follows\n"
3290 "target IPv4 address\n"
3291 "target IPv6 address\n")
3293 struct rfapi_ip_addr vn
;
3294 struct rfapi_ip_addr un
;
3295 struct rfapi_ip_addr target
;
3296 rfapi_handle handle
;
3298 struct rfapi_next_hop_entry
*pNextHopEntry
;
3303 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[4]->arg
, &vn
)))
3310 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[6]->arg
, &un
)))
3317 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[8]->arg
, &target
)))
3321 if (rfapi_find_handle_vty(vty
, &vn
, &un
, &handle
)) {
3322 vty_out(vty
, "can't locate handle matching vn=%s, un=%s\n",
3323 argv
[4]->arg
, argv
[6]->arg
);
3324 return CMD_WARNING_CONFIG_FAILED
;
3328 * options parameter not used? Set to NULL for now
3330 rc
= rfapi_query(handle
, &target
, NULL
, &pNextHopEntry
);
3333 vty_out(vty
, "rfapi_query failed with rc=%d (%s)\n", rc
,
3337 * print nexthop list
3339 test_nexthops_callback(/*&target, */ pNextHopEntry
,
3340 vty
); /* frees nh list! */
3347 DEFUN (debug_rfapi_query_vn_un_l2o
,
3348 debug_rfapi_query_vn_un_l2o_cmd
,
3349 "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",
3353 "indicate vn addr follows\n"
3354 "virtual network interface IPv4 address\n"
3355 "virtual network interface IPv6 address\n"
3356 "indicate xt addr follows\n"
3357 "underlay network interface IPv4 address\n"
3358 "underlay network interface IPv6 address\n"
3359 "logical network ID follows\n"
3360 "logical network ID\n"
3361 "indicate target MAC addr follows\n"
3362 "target MAC addr\n")
3364 struct rfapi_ip_addr vn
;
3365 struct rfapi_ip_addr un
;
3366 struct rfapi_ip_addr target
;
3367 rfapi_handle handle
;
3369 struct rfapi_next_hop_entry
*pNextHopEntry
;
3370 struct rfapi_l2address_option l2o_buf
;
3371 struct bgp_tea_options hopt
;
3377 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[4]->arg
, &vn
)))
3384 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[6]->arg
, &un
)))
3388 #if 0 /* there is no IP target arg here ?????? */
3392 if ((rc
= rfapiCliGetRfapiIpAddr (vty
, argv
[2], &target
)))
3395 vty_out(vty
, "%% This command is broken.\n");
3396 return CMD_WARNING_CONFIG_FAILED
;
3399 if (rfapi_find_handle_vty(vty
, &vn
, &un
, &handle
)) {
3400 vty_out(vty
, "can't locate handle matching vn=%s, un=%s\n",
3401 argv
[4]->arg
, argv
[6]->arg
);
3402 return CMD_WARNING_CONFIG_FAILED
;
3406 * Set up L2 parameters
3408 memset(&l2o_buf
, 0, sizeof(l2o_buf
));
3409 if (rfapiStr2EthAddr(argv
[10]->arg
, &l2o_buf
.macaddr
)) {
3410 vty_out(vty
, "Bad mac address \"%s\"\n", argv
[10]->arg
);
3411 return CMD_WARNING_CONFIG_FAILED
;
3414 l2o_buf
.logical_net_id
= strtoul(argv
[8]->arg
, NULL
, 10);
3416 /* construct option chain */
3418 memset(valbuf
, 0, sizeof(valbuf
));
3419 memcpy(valbuf
, &l2o_buf
.macaddr
.octet
, ETHER_ADDR_LEN
);
3420 valbuf
[11] = (l2o_buf
.logical_net_id
>> 16) & 0xff;
3421 valbuf
[12] = (l2o_buf
.logical_net_id
>> 8) & 0xff;
3422 valbuf
[13] = l2o_buf
.logical_net_id
& 0xff;
3424 memset(&hopt
, 0, sizeof(hopt
));
3425 hopt
.options_count
= 1;
3426 hopt
.options_length
= sizeof(valbuf
); /* is this right? */
3427 hopt
.type
= RFAPI_VN_OPTION_TYPE_L2ADDR
;
3428 hopt
.length
= sizeof(valbuf
);
3429 hopt
.value
= valbuf
;
3433 * options parameter not used? Set to NULL for now
3435 rc
= rfapi_query(handle
, &target
, &l2o_buf
, &pNextHopEntry
);
3438 vty_out(vty
, "rfapi_query failed with rc=%d (%s)\n", rc
,
3442 * print nexthop list
3444 /* TBD enhance to print L2 information */
3445 test_nexthops_callback(/*&target, */ pNextHopEntry
,
3446 vty
); /* frees nh list! */
3453 DEFUN (debug_rfapi_query_done_vn_un
,
3454 debug_rfapi_query_vn_un_done_cmd
,
3455 "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>",
3458 "rfapi_query_done\n"
3459 "rfapi_query_done\n"
3460 "indicate vn addr follows\n"
3461 "virtual network interface IPv4 address\n"
3462 "virtual network interface IPv6 address\n"
3463 "indicate xt addr follows\n"
3464 "underlay network interface IPv4 address\n"
3465 "underlay network interface IPv6 address\n"
3466 "indicate target follows\n"
3467 "Target IPv4 address\n"
3468 "Target IPv6 address\n")
3470 struct rfapi_ip_addr vn
;
3471 struct rfapi_ip_addr un
;
3472 struct rfapi_ip_addr target
;
3473 rfapi_handle handle
;
3479 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[5]->arg
, &vn
)))
3486 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[7]->arg
, &un
)))
3493 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[9]->arg
, &target
)))
3497 if (rfapi_find_handle_vty(vty
, &vn
, &un
, &handle
)) {
3498 vty_out(vty
, "can't locate handle matching vn=%s, un=%s\n",
3499 argv
[5]->arg
, argv
[7]->arg
);
3500 return CMD_WARNING_CONFIG_FAILED
;
3504 * options parameter not used? Set to NULL for now
3506 rc
= rfapi_query_done(handle
, &target
);
3508 vty_out(vty
, "rfapi_query_done returned %d\n", rc
);
3513 DEFUN (debug_rfapi_show_import
,
3514 debug_rfapi_show_import_cmd
,
3515 "debug rfapi-dev show import",
3523 struct rfapi_import_table
*it
;
3528 * Show all import tables
3531 bgp
= bgp_get_default(); /* assume 1 instance for now */
3533 vty_out(vty
, "No BGP instance\n");
3534 return CMD_WARNING_CONFIG_FAILED
;
3539 vty_out(vty
, "No RFAPI instance\n");
3540 return CMD_WARNING_CONFIG_FAILED
;
3544 * Iterate over all import tables; do a filtered import
3545 * for the afi/safi combination
3549 for (it
= h
->imports
; it
; it
= it
->next
) {
3550 s
= ecommunity_ecom2str(it
->rt_import_list
,
3551 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3552 vty_out(vty
, "Import Table %p, RTs: %s\n", it
, s
);
3553 XFREE(MTYPE_ECOMMUNITY_STR
, s
);
3555 rfapiShowImportTable(vty
, "IP VPN", it
->imported_vpn
[AFI_IP
],
3557 rfapiShowImportTable(vty
, "IP ENCAP",
3558 it
->imported_encap
[AFI_IP
], 0);
3559 rfapiShowImportTable(vty
, "IP6 VPN", it
->imported_vpn
[AFI_IP6
],
3561 rfapiShowImportTable(vty
, "IP6 ENCAP",
3562 it
->imported_encap
[AFI_IP6
], 0);
3565 if (h
->import_mac
) {
3566 void *cursor
= NULL
;
3568 uintptr_t lni_as_ptr
;
3572 for (rc
= skiplist_next(h
->import_mac
, (void **)&lni_as_ptr
,
3573 (void **)&it
, &cursor
);
3575 rc
= skiplist_next(h
->import_mac
, (void **)&lni_as_ptr
,
3576 (void **)&it
, &cursor
)) {
3578 if (it
->imported_vpn
[AFI_L2VPN
]) {
3582 "\nLNI-based Ethernet Tables:\n");
3585 snprintf(buf
, BUFSIZ
, "L2VPN LNI=%u", lni
);
3586 rfapiShowImportTable(
3587 vty
, buf
, it
->imported_vpn
[AFI_L2VPN
],
3593 rfapiShowImportTable(vty
, "CE IT - IP VPN",
3594 h
->it_ce
->imported_vpn
[AFI_IP
], 1);
3599 DEFUN (debug_rfapi_show_import_vn_un
,
3600 debug_rfapi_show_import_vn_un_cmd
,
3601 "debug rfapi-dev show import vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X>",
3606 "indicate vn addr follows\n"
3607 "virtual network interface IPv4 address\n"
3608 "virtual network interface IPv6 address\n"
3609 "indicate xt addr follows\n"
3610 "underlay network interface IPv4 address\n"
3611 "underlay network interface IPv6 address\n")
3613 struct rfapi_ip_addr vn
;
3614 struct rfapi_ip_addr un
;
3615 rfapi_handle handle
;
3617 struct rfapi_descriptor
*rfd
;
3622 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[5]->arg
, &vn
)))
3629 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[7]->arg
, &un
)))
3633 if (rfapi_find_handle_vty(vty
, &vn
, &un
, &handle
)) {
3634 vty_out(vty
, "can't locate handle matching vn=%s, un=%s\n",
3635 argv
[5]->arg
, argv
[7]->arg
);
3636 return CMD_WARNING_CONFIG_FAILED
;
3639 rfd
= (struct rfapi_descriptor
*)handle
;
3641 rfapiShowImportTable(vty
, "IP VPN",
3642 rfd
->import_table
->imported_vpn
[AFI_IP
], 1);
3643 rfapiShowImportTable(vty
, "IP ENCAP",
3644 rfd
->import_table
->imported_encap
[AFI_IP
], 0);
3645 rfapiShowImportTable(vty
, "IP6 VPN",
3646 rfd
->import_table
->imported_vpn
[AFI_IP6
], 1);
3647 rfapiShowImportTable(vty
, "IP6 ENCAP",
3648 rfd
->import_table
->imported_encap
[AFI_IP6
], 0);
3653 DEFUN (debug_rfapi_response_omit_self
,
3654 debug_rfapi_response_omit_self_cmd
,
3655 "debug rfapi-dev response-omit-self <on|off>",
3658 "Omit self in RFP responses\n"
3659 "filter out self from responses\n" "leave self in responses\n")
3661 struct bgp
*bgp
= bgp_get_default();
3664 vty_out(vty
, "No BGP process is configured\n");
3665 return CMD_WARNING_CONFIG_FAILED
;
3667 if (!bgp
->rfapi_cfg
) {
3668 vty_out(vty
, "VNC not configured\n");
3669 return CMD_WARNING_CONFIG_FAILED
;
3672 if (strmatch(argv
[3]->text
, "on"))
3673 SET_FLAG(bgp
->rfapi_cfg
->flags
,
3674 BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP
);
3676 UNSET_FLAG(bgp
->rfapi_cfg
->flags
,
3677 BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP
);
3683 #ifdef RFAPI_DEBUG_SKIPLIST_CLI
3685 #include "lib/skiplist.h"
3686 DEFUN (skiplist_test_cli
,
3687 skiplist_test_cli_cmd
,
3689 "skiplist command\n"
3697 DEFUN (skiplist_debug_cli
,
3698 skiplist_debug_cli_cmd
,
3700 "skiplist command\n"
3703 skiplist_debug(vty
, NULL
);
3707 #endif /* RFAPI_DEBUG_SKIPLIST_CLI */
3709 void rfapi_init(void)
3711 bgp_rfapi_cfg_init();
3714 install_element(ENABLE_NODE
, &debug_rfapi_show_import_cmd
);
3715 install_element(ENABLE_NODE
, &debug_rfapi_show_import_vn_un_cmd
);
3717 install_element(ENABLE_NODE
, &debug_rfapi_open_cmd
);
3718 install_element(ENABLE_NODE
, &debug_rfapi_close_vn_un_cmd
);
3719 install_element(ENABLE_NODE
, &debug_rfapi_close_rfd_cmd
);
3720 install_element(ENABLE_NODE
, &debug_rfapi_register_vn_un_cmd
);
3721 install_element(ENABLE_NODE
, &debug_rfapi_unregister_vn_un_cmd
);
3722 install_element(ENABLE_NODE
, &debug_rfapi_query_vn_un_cmd
);
3723 install_element(ENABLE_NODE
, &debug_rfapi_query_vn_un_done_cmd
);
3724 install_element(ENABLE_NODE
, &debug_rfapi_query_vn_un_l2o_cmd
);
3726 install_element(ENABLE_NODE
, &debug_rfapi_response_omit_self_cmd
);
3728 /* Need the following show commands for gpz test scripts */
3729 install_element(ENABLE_NODE
, &debug_rfapi_show_nves_cmd
);
3730 install_element(ENABLE_NODE
, &debug_rfapi_show_nves_vn_un_cmd
);
3731 install_element(ENABLE_NODE
, &debug_rfapi_register_vn_un_l2o_cmd
);
3733 #ifdef RFAPI_DEBUG_SKIPLIST_CLI
3734 install_element(ENABLE_NODE
, &skiplist_test_cli_cmd
);
3735 install_element(ENABLE_NODE
, &skiplist_debug_cli_cmd
);
3742 static void rfapi_print_exported(struct bgp
*bgp
)
3744 struct bgp_node
*rdn
;
3745 struct bgp_node
*rn
;
3746 struct bgp_info
*bi
;
3751 for (rdn
= bgp_table_top(bgp
->rib
[AFI_IP
][SAFI_MPLS_VPN
]); rdn
;
3752 rdn
= bgp_route_next(rdn
)) {
3755 fprintf(stderr
, "%s: vpn rdn=%p\n", __func__
, rdn
);
3756 for (rn
= bgp_table_top(rdn
->info
); rn
;
3757 rn
= bgp_route_next(rn
)) {
3760 fprintf(stderr
, "%s: rn=%p\n", __func__
, rn
);
3761 for (bi
= rn
->info
; bi
; bi
= bi
->next
) {
3762 rfapiPrintBi((void *)2, bi
); /* 2 => stderr */
3766 for (rdn
= bgp_table_top(bgp
->rib
[AFI_IP
][SAFI_ENCAP
]); rdn
;
3767 rdn
= bgp_route_next(rdn
)) {
3770 fprintf(stderr
, "%s: encap rdn=%p\n", __func__
, rdn
);
3771 for (rn
= bgp_table_top(rdn
->info
); rn
;
3772 rn
= bgp_route_next(rn
)) {
3775 fprintf(stderr
, "%s: rn=%p\n", __func__
, rn
);
3776 for (bi
= rn
->info
; bi
; bi
= bi
->next
) {
3777 rfapiPrintBi((void *)2, bi
); /* 2 => stderr */
3782 #endif /* defined(DEBUG_RFAPI) */
3785 * Free all memory to prepare for clean exit as seen by valgrind memcheck
3787 void rfapi_delete(struct bgp
*bgp
)
3789 extern void rfp_clear_vnc_nve_all(void); /* can't fix correctly yet */
3792 * This clears queries and registered routes, and closes nves
3795 rfp_clear_vnc_nve_all();
3796 bgp_rfapi_cfg_destroy(bgp
, bgp
->rfapi_cfg
);
3797 bgp
->rfapi_cfg
= NULL
;
3798 bgp_rfapi_destroy(bgp
, bgp
->rfapi
);
3802 * show what's left in the BGP MPLSVPN RIB
3804 rfapi_print_exported(bgp
);
3808 int rfapi_set_autord_from_vn(struct prefix_rd
*rd
, struct rfapi_ip_addr
*vn
)
3810 vnc_zlog_debug_verbose("%s: auto-assigning RD", __func__
);
3811 if (vn
->addr_family
!= AF_INET
&& vn
->addr_family
!= AF_INET6
) {
3812 vnc_zlog_debug_verbose(
3813 "%s: can't auto-assign RD, VN addr family is not IPv4"
3816 return EAFNOSUPPORT
;
3818 rd
->family
= AF_UNSPEC
;
3820 rd
->val
[1] = RD_TYPE_IP
;
3821 if (vn
->addr_family
== AF_INET
) {
3822 memcpy(rd
->val
+ 2, &vn
->addr
.v4
.s_addr
, 4);
3823 } else { /* is v6 */
3824 memcpy(rd
->val
+ 2, &vn
->addr
.v6
.s6_addr32
[3],
3825 4); /* low order 4 bytes */
3830 prefix_rd2str(rd
, buf
, BUFSIZ
);
3831 buf
[BUFSIZ
- 1] = 0;
3832 vnc_zlog_debug_verbose("%s: auto-RD is set to %s", __func__
,
3838 /*------------------------------------------
3839 * rfapi_bgp_lookup_by_rfp
3841 * Find bgp instance pointer based on value returned by rfp_start
3844 * rfp_start_val value returned by rfp_startor
3845 * NULL (=get default instance)
3851 * bgp bgp instance pointer
3854 --------------------------------------------*/
3855 struct bgp
*rfapi_bgp_lookup_by_rfp(void *rfp_start_val
)
3857 struct bgp
*bgp
= NULL
;
3858 struct listnode
*node
, *nnode
;
3860 if (rfp_start_val
== NULL
)
3861 bgp
= bgp_get_default();
3863 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
3864 if (bgp
->rfapi
!= NULL
3865 && bgp
->rfapi
->rfp
== rfp_start_val
)
3870 /*------------------------------------------
3871 * rfapi_get_rfp_start_val_by_bgp
3873 * Find bgp instance pointer based on value returned by rfp_start
3876 * bgp bgp instance pointer
3885 --------------------------------------------*/
3886 void *rfapi_get_rfp_start_val_by_bgp(struct bgp
*bgp
)
3888 if (!bgp
|| !bgp
->rfapi
)
3890 return bgp
->rfapi
->rfp
;
3893 /***********************************************************************
3894 * RFP group specific configuration
3895 ***********************************************************************/
3896 static void *rfapi_rfp_get_or_init_group_config_default(struct rfapi_cfg
*rfc
,
3900 if (rfc
->default_rfp_cfg
== NULL
&& size
> 0) {
3901 rfc
->default_rfp_cfg
= XCALLOC(MTYPE_RFAPI_RFP_GROUP_CFG
, size
);
3902 vnc_zlog_debug_verbose("%s: allocated, size=%d", __func__
,
3905 return rfc
->default_rfp_cfg
;
3908 static void *rfapi_rfp_get_or_init_group_config_nve(struct rfapi_cfg
*rfc
,
3912 struct rfapi_nve_group_cfg
*rfg
=
3913 VTY_GET_CONTEXT_SUB(rfapi_nve_group_cfg
);
3915 /* make sure group is still in list */
3916 if (!rfg
|| !listnode_lookup(rfc
->nve_groups_sequential
, rfg
)) {
3917 /* Not in list anymore */
3918 vty_out(vty
, "Current NVE group no longer exists\n");
3922 if (rfg
->rfp_cfg
== NULL
&& size
> 0) {
3923 rfg
->rfp_cfg
= XCALLOC(MTYPE_RFAPI_RFP_GROUP_CFG
, size
);
3924 vnc_zlog_debug_verbose("%s: allocated, size=%d", __func__
,
3927 return rfg
->rfp_cfg
;
3930 static void *rfapi_rfp_get_or_init_group_config_l2(struct rfapi_cfg
*rfc
,
3934 struct rfapi_l2_group_cfg
*rfg
=
3935 VTY_GET_CONTEXT_SUB(rfapi_l2_group_cfg
);
3937 /* make sure group is still in list */
3938 if (!rfg
|| !listnode_lookup(rfc
->l2_groups
, rfg
)) {
3939 /* Not in list anymore */
3940 vty_out(vty
, "Current L2 group no longer exists\n");
3943 if (rfg
->rfp_cfg
== NULL
&& size
> 0) {
3944 rfg
->rfp_cfg
= XCALLOC(MTYPE_RFAPI_RFP_GROUP_CFG
, size
);
3945 vnc_zlog_debug_verbose("%s: allocated, size=%d", __func__
,
3948 return rfg
->rfp_cfg
;
3951 /*------------------------------------------
3952 * rfapi_rfp_init_group_config_ptr_vty
3954 * This is used to init or return a previously init'ed group specific
3955 * configuration pointer. Group is identified by vty context.
3956 * NOTE: size is ignored when a previously init'ed value is returned.
3957 * RFAPI frees rfp_cfg_group when group is deleted during reconfig,
3958 * bgp restart or shutdown.
3961 * rfp_start_val value returned by rfp_start
3963 * vty quagga vty context
3964 * size number of bytes to allocation
3970 * rfp_cfg_group NULL or Pointer to configuration structure
3971 --------------------------------------------*/
3972 void *rfapi_rfp_init_group_config_ptr_vty(void *rfp_start_val
,
3973 rfapi_rfp_cfg_group_type type
,
3974 struct vty
*vty
, uint32_t size
)
3979 if (rfp_start_val
== NULL
|| vty
== NULL
)
3982 bgp
= rfapi_bgp_lookup_by_rfp(rfp_start_val
);
3983 if (!bgp
|| !bgp
->rfapi_cfg
)
3987 case RFAPI_RFP_CFG_GROUP_DEFAULT
:
3988 ret
= rfapi_rfp_get_or_init_group_config_default(bgp
->rfapi_cfg
,
3991 case RFAPI_RFP_CFG_GROUP_NVE
:
3992 ret
= rfapi_rfp_get_or_init_group_config_nve(bgp
->rfapi_cfg
,
3995 case RFAPI_RFP_CFG_GROUP_L2
:
3996 ret
= rfapi_rfp_get_or_init_group_config_l2(bgp
->rfapi_cfg
, vty
,
4000 zlog_err("%s: Unknown group type=%d", __func__
, type
);
4001 /* should never happen */
4002 assert("Unknown type" == NULL
);
4008 /*------------------------------------------
4009 * rfapi_rfp_get_group_config_ptr_vty
4011 * This is used to get group specific configuration pointer.
4012 * Group is identified by type and vty context.
4013 * RFAPI frees rfp_cfg_group when group is deleted during reconfig,
4014 * bgp restart or shutdown.
4017 * rfp_start_val value returned by rfp_start
4019 * vty quagga vty context
4025 * rfp_cfg_group Pointer to configuration structure
4026 --------------------------------------------*/
4027 void *rfapi_rfp_get_group_config_ptr_vty(void *rfp_start_val
,
4028 rfapi_rfp_cfg_group_type type
,
4031 return rfapi_rfp_init_group_config_ptr_vty(rfp_start_val
, type
, vty
, 0);
4035 rfapi_rfp_get_group_config_name_nve(struct rfapi_cfg
*rfc
, const char *name
,
4037 rfp_group_config_search_cb_t
*search_cb
)
4039 struct rfapi_nve_group_cfg
*rfg
;
4040 struct listnode
*node
;
4042 for (ALL_LIST_ELEMENTS_RO(rfc
->nve_groups_sequential
, node
, rfg
)) {
4043 if (!strcmp(rfg
->name
, name
) && /* name match */
4044 (search_cb
== NULL
|| !search_cb(criteria
, rfg
->rfp_cfg
)))
4045 return rfg
->rfp_cfg
;
4051 rfapi_rfp_get_group_config_name_l2(struct rfapi_cfg
*rfc
, const char *name
,
4053 rfp_group_config_search_cb_t
*search_cb
)
4055 struct rfapi_l2_group_cfg
*rfg
;
4056 struct listnode
*node
;
4058 for (ALL_LIST_ELEMENTS_RO(rfc
->l2_groups
, node
, rfg
)) {
4059 if (!strcmp(rfg
->name
, name
) && /* name match */
4060 (search_cb
== NULL
|| !search_cb(criteria
, rfg
->rfp_cfg
)))
4061 return rfg
->rfp_cfg
;
4066 /*------------------------------------------
4067 * rfapi_rfp_get_group_config_ptr_name
4069 * This is used to get group specific configuration pointer.
4070 * Group is identified by type and name context.
4071 * RFAPI frees rfp_cfg_group when group is deleted during reconfig,
4072 * bgp restart or shutdown.
4075 * rfp_start_val value returned by rfp_start
4078 * criteria RFAPI caller provided serach criteria
4079 * search_cb optional rfp_group_config_search_cb_t
4085 * rfp_cfg_group Pointer to configuration structure
4086 --------------------------------------------*/
4087 void *rfapi_rfp_get_group_config_ptr_name(
4088 void *rfp_start_val
, rfapi_rfp_cfg_group_type type
, const char *name
,
4089 void *criteria
, rfp_group_config_search_cb_t
*search_cb
)
4094 if (rfp_start_val
== NULL
|| name
== NULL
)
4097 bgp
= rfapi_bgp_lookup_by_rfp(rfp_start_val
);
4098 if (!bgp
|| !bgp
->rfapi_cfg
)
4102 case RFAPI_RFP_CFG_GROUP_DEFAULT
:
4103 ret
= bgp
->rfapi_cfg
->default_rfp_cfg
;
4105 case RFAPI_RFP_CFG_GROUP_NVE
:
4106 ret
= rfapi_rfp_get_group_config_name_nve(bgp
->rfapi_cfg
, name
,
4107 criteria
, search_cb
);
4109 case RFAPI_RFP_CFG_GROUP_L2
:
4110 ret
= rfapi_rfp_get_group_config_name_l2(bgp
->rfapi_cfg
, name
,
4111 criteria
, search_cb
);
4114 zlog_err("%s: Unknown group type=%d", __func__
, type
);
4115 /* should never happen */
4116 assert("Unknown type" == NULL
);
4122 /*------------------------------------------
4123 * rfapi_rfp_get_l2_group_config_ptr_lni
4125 * This is used to get group specific configuration pointer.
4126 * Group is identified by type and logical network identifier.
4127 * RFAPI frees rfp_cfg_group when group is deleted during reconfig,
4128 * bgp restart or shutdown.
4131 * rfp_start_val value returned by rfp_start
4133 * logical_net_id group logical network identifier
4134 * criteria RFAPI caller provided serach criteria
4135 * search_cb optional rfp_group_config_search_cb_t
4141 * rfp_cfg_group Pointer to configuration structure
4142 --------------------------------------------*/
4144 rfapi_rfp_get_l2_group_config_ptr_lni(void *rfp_start_val
,
4145 uint32_t logical_net_id
, void *criteria
,
4146 rfp_group_config_search_cb_t
*search_cb
)
4149 struct rfapi_l2_group_cfg
*rfg
;
4150 struct listnode
*node
;
4152 if (rfp_start_val
== NULL
)
4155 bgp
= rfapi_bgp_lookup_by_rfp(rfp_start_val
);
4156 if (!bgp
|| !bgp
->rfapi_cfg
)
4159 for (ALL_LIST_ELEMENTS_RO(bgp
->rfapi_cfg
->l2_groups
, node
, rfg
)) {
4160 if (rfg
->logical_net_id
== logical_net_id
4161 && (search_cb
== NULL
4162 || !search_cb(criteria
, rfg
->rfp_cfg
))) {
4163 if (rfg
->rfp_cfg
== NULL
)
4164 vnc_zlog_debug_verbose(
4165 "%s: returning rfp group config for lni=0",
4167 return rfg
->rfp_cfg
;