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"
34 #include "lib/ringbuf.h"
36 #include "bgpd/bgpd.h"
37 #include "bgpd/bgp_ecommunity.h"
38 #include "bgpd/bgp_attr.h"
40 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
41 #include "bgpd/rfapi/rfapi.h"
42 #include "bgpd/rfapi/rfapi_backend.h"
44 #include "bgpd/bgp_route.h"
45 #include "bgpd/bgp_mplsvpn.h"
46 #include "bgpd/bgp_aspath.h"
47 #include "bgpd/bgp_advertise.h"
48 #include "bgpd/bgp_vnc_types.h"
49 #include "bgpd/bgp_zebra.h"
51 #include "bgpd/rfapi/rfapi_import.h"
52 #include "bgpd/rfapi/rfapi_private.h"
53 #include "bgpd/rfapi/rfapi_monitor.h"
54 #include "bgpd/rfapi/rfapi_vty.h"
55 #include "bgpd/rfapi/vnc_export_bgp.h"
56 #include "bgpd/rfapi/vnc_export_bgp_p.h"
57 #include "bgpd/rfapi/vnc_zebra.h"
58 #include "bgpd/rfapi/vnc_import_bgp.h"
59 #include "bgpd/rfapi/rfapi_rib.h"
60 #include "bgpd/rfapi/rfapi_ap.h"
61 #include "bgpd/rfapi/rfapi_encap_tlv.h"
62 #include "bgpd/rfapi/vnc_debug.h"
64 #ifdef HAVE_GLIBC_BACKTRACE
65 /* for backtrace and friends */
67 #endif /* HAVE_GLIBC_BACKTRACE */
69 struct ethaddr rfapi_ethaddr0
= {{0}};
71 #define DEBUG_RFAPI_STR "RF API debugging/testing command\n"
73 const char *rfapi_error_str(int code
)
79 return "BGP or VNC not configured";
83 return "Handle already open";
85 return "Incomplete configuration";
87 return "Invalid address family";
89 return "Called from within a callback procedure";
91 return "Invalid handle";
93 return "Invalid argument";
95 return "Stale descriptor";
97 return "Unknown error";
101 /*------------------------------------------
102 * rfapi_get_response_lifetime_default
104 * Returns the default lifetime for a response.
105 * rfp_start_val value returned by rfp_start or
106 * NULL (=use default instance)
113 * return value: The bgp instance default lifetime for a response.
114 --------------------------------------------*/
115 int rfapi_get_response_lifetime_default(void *rfp_start_val
)
117 struct bgp
*bgp
= rfapi_bgp_lookup_by_rfp(rfp_start_val
);
119 return bgp
->rfapi_cfg
->default_response_lifetime
;
120 return BGP_VNC_DEFAULT_RESPONSE_LIFETIME_DEFAULT
;
123 /*------------------------------------------
124 * rfapi_is_vnc_configured
126 * Returns if VNC is configured
129 * rfp_start_val value returned by rfp_start or
130 * NULL (=use default instance)
134 * return value: If VNC is configured for the bgpd instance
136 * ENXIO VNC not configured
137 --------------------------------------------*/
138 int rfapi_is_vnc_configured(void *rfp_start_val
)
140 struct bgp
*bgp
= rfapi_bgp_lookup_by_rfp(rfp_start_val
);
141 if (bgp_rfapi_is_vnc_configured(bgp
) == 0)
147 /*------------------------------------------
150 * Get the virtual network address used by an NVE based on it's RFD
153 * rfd: rfapi descriptor returned by rfapi_open or rfapi_create_generic
158 * vn NVE virtual network address
159 *------------------------------------------*/
160 struct rfapi_ip_addr
*rfapi_get_vn_addr(void *rfd
)
162 struct rfapi_descriptor
*rrfd
= (struct rfapi_descriptor
*)rfd
;
163 return &rrfd
->vn_addr
;
166 /*------------------------------------------
169 * Get the underlay network address used by an NVE based on it's RFD
172 * rfd: rfapi descriptor returned by rfapi_open or rfapi_create_generic
177 * un NVE underlay network address
178 *------------------------------------------*/
179 struct rfapi_ip_addr
*rfapi_get_un_addr(void *rfd
)
181 struct rfapi_descriptor
*rrfd
= (struct rfapi_descriptor
*)rfd
;
182 return &rrfd
->un_addr
;
185 int rfapi_ip_addr_cmp(struct rfapi_ip_addr
*a1
, struct rfapi_ip_addr
*a2
)
187 if (a1
->addr_family
!= a2
->addr_family
)
188 return a1
->addr_family
- a2
->addr_family
;
190 if (a1
->addr_family
== AF_INET
) {
191 return IPV4_ADDR_CMP(&a1
->addr
.v4
, &a2
->addr
.v4
);
194 if (a1
->addr_family
== AF_INET6
) {
195 return IPV6_ADDR_CMP(&a1
->addr
.v6
, &a2
->addr
.v6
);
203 static int rfapi_find_node(struct bgp
*bgp
, struct rfapi_ip_addr
*vn_addr
,
204 struct rfapi_ip_addr
*un_addr
,
205 struct route_node
**node
)
209 struct route_node
*rn
;
222 afi
= family2afi(un_addr
->addr_family
);
227 if ((rc
= rfapiRaddr2Qprefix(un_addr
, &p
)))
230 rn
= route_node_lookup(h
->un
[afi
], &p
);
235 route_unlock_node(rn
);
243 int rfapi_find_rfd(struct bgp
*bgp
, struct rfapi_ip_addr
*vn_addr
,
244 struct rfapi_ip_addr
*un_addr
, struct rfapi_descriptor
**rfd
)
246 struct route_node
*rn
;
249 rc
= rfapi_find_node(bgp
, vn_addr
, un_addr
, &rn
);
254 for (*rfd
= (struct rfapi_descriptor
*)(rn
->info
); *rfd
;
255 *rfd
= (*rfd
)->next
) {
256 if (!rfapi_ip_addr_cmp(&(*rfd
)->vn_addr
, vn_addr
))
266 /*------------------------------------------
270 * un underlay network address
271 * vn virtual network address
274 * pHandle pointer to location to store handle
278 * ENOENT no matching handle
279 * ENXIO BGP or VNC not configured
280 *------------------------------------------*/
281 static int rfapi_find_handle(struct bgp
*bgp
, struct rfapi_ip_addr
*vn_addr
,
282 struct rfapi_ip_addr
*un_addr
,
283 rfapi_handle
*handle
)
285 struct rfapi_descriptor
**rfd
;
287 rfd
= (struct rfapi_descriptor
**)handle
;
289 return rfapi_find_rfd(bgp
, vn_addr
, un_addr
, rfd
);
292 static int rfapi_find_handle_vty(struct vty
*vty
, struct rfapi_ip_addr
*vn_addr
,
293 struct rfapi_ip_addr
*un_addr
,
294 rfapi_handle
*handle
)
297 struct rfapi_descriptor
**rfd
;
299 bgp
= bgp_get_default(); /* assume 1 instance for now */
301 rfd
= (struct rfapi_descriptor
**)handle
;
303 return rfapi_find_rfd(bgp
, vn_addr
, un_addr
, rfd
);
306 static int is_valid_rfd(struct rfapi_descriptor
*rfd
)
310 if (!rfd
|| rfd
->bgp
== NULL
)
315 RFAPI_HD_FLAG_IS_VRF
)) /* assume VRF/internal are valid */
318 if (rfapi_find_handle(rfd
->bgp
, &rfd
->vn_addr
, &rfd
->un_addr
, &hh
))
328 * check status of descriptor
330 int rfapi_check(void *handle
)
332 struct rfapi_descriptor
*rfd
= (struct rfapi_descriptor
*)handle
;
336 if (!rfd
|| rfd
->bgp
== NULL
)
341 RFAPI_HD_FLAG_IS_VRF
)) /* assume VRF/internal are valid */
344 if ((rc
= rfapi_find_handle(rfd
->bgp
, &rfd
->vn_addr
, &rfd
->un_addr
,
358 void del_vnc_route(struct rfapi_descriptor
*rfd
,
359 struct peer
*peer
, /* rfd->peer for RFP regs */
360 struct bgp
*bgp
, safi_t safi
, struct prefix
*p
,
361 struct prefix_rd
*prd
, uint8_t type
, uint8_t sub_type
,
362 struct rfapi_nexthop
*lnh
, int kill
)
364 afi_t afi
; /* of the VN address */
367 char buf
[PREFIX_STRLEN
];
368 char buf2
[RD_ADDRSTRLEN
];
369 struct prefix_rd prd0
;
371 prefix2str(p
, buf
, sizeof(buf
));
373 afi
= family2afi(p
->family
);
374 assert(afi
== AFI_IP
|| afi
== AFI_IP6
);
376 if (safi
== SAFI_ENCAP
) {
377 memset(&prd0
, 0, sizeof(prd0
));
378 prd0
.family
= AF_UNSPEC
;
382 bn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
384 vnc_zlog_debug_verbose(
385 "%s: peer=%p, prefix=%s, prd=%s afi=%d, safi=%d bn=%p, bn->info=%p",
386 __func__
, peer
, buf
, prefix_rd2str(prd
, buf2
, sizeof(buf2
)),
387 afi
, safi
, bn
, (bn
? bn
->info
: NULL
));
389 for (bi
= (bn
? bn
->info
: NULL
); bi
; bi
= bi
->next
) {
391 vnc_zlog_debug_verbose(
392 "%s: trying bi=%p, bi->peer=%p, bi->type=%d, bi->sub_type=%d, bi->extra->vnc.export.rfapi_handle=%p, local_pref=%u",
393 __func__
, bi
, bi
->peer
, bi
->type
, bi
->sub_type
,
394 (bi
->extra
? bi
->extra
->vnc
.export
.rfapi_handle
: NULL
),
396 && CHECK_FLAG(bi
->attr
->flag
,
397 ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))
398 ? bi
->attr
->local_pref
401 if (bi
->peer
== peer
&& bi
->type
== type
402 && bi
->sub_type
== sub_type
&& bi
->extra
403 && bi
->extra
->vnc
.export
.rfapi_handle
== (void *)rfd
) {
405 vnc_zlog_debug_verbose("%s: matched it", __func__
);
413 * lnh set means to JUST delete the local nexthop from this
414 * route. Leave the route itself in place.
415 * TBD add return code reporting of success/failure
417 if (!bi
|| !bi
->extra
418 || !bi
->extra
->vnc
.export
.local_nexthops
) {
422 vnc_zlog_debug_verbose(
423 "%s: lnh list already empty at prefix %s",
431 struct listnode
*node
;
432 struct rfapi_nexthop
*pLnh
= NULL
;
434 for (ALL_LIST_ELEMENTS_RO(bi
->extra
->vnc
.export
.local_nexthops
,
437 if (prefix_same(&pLnh
->addr
, &lnh
->addr
)) {
443 listnode_delete(bi
->extra
->vnc
.export
.local_nexthops
,
446 /* silly rabbit, listnode_delete doesn't invoke
447 * list->del on data */
448 rfapi_nexthop_free(pLnh
);
450 vnc_zlog_debug_verbose("%s: desired lnh not found %s",
457 * loop back to import tables
458 * Do this before removing from BGP RIB because rfapiProcessWithdraw
461 rfapiProcessWithdraw(peer
, rfd
, p
, prd
, NULL
, afi
, safi
, type
, kill
);
464 char buf
[PREFIX_STRLEN
];
466 prefix2str(p
, buf
, sizeof(buf
));
467 vnc_zlog_debug_verbose(
468 "%s: Found route (safi=%d) to delete at prefix %s",
469 __func__
, safi
, buf
);
471 if (safi
== SAFI_MPLS_VPN
) {
472 struct bgp_node
*prn
= NULL
;
473 struct bgp_table
*table
= NULL
;
475 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
476 (struct prefix
*)prd
);
478 table
= (struct bgp_table
*)(prn
->info
);
480 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
481 bgp
, prd
, table
, p
, bi
);
483 bgp_unlock_node(prn
);
487 * Delete local_nexthops list
489 if (bi
->extra
&& bi
->extra
->vnc
.export
.local_nexthops
) {
490 list_delete_and_null(
491 &bi
->extra
->vnc
.export
.local_nexthops
);
494 bgp_aggregate_decrement(bgp
, p
, bi
, afi
, safi
);
495 bgp_info_delete(bn
, bi
);
496 bgp_process(bgp
, bn
, afi
, safi
);
498 vnc_zlog_debug_verbose(
499 "%s: Couldn't find route (safi=%d) at prefix %s",
500 __func__
, safi
, buf
);
506 struct rfapi_nexthop
*rfapi_nexthop_new(struct rfapi_nexthop
*copyme
)
508 struct rfapi_nexthop
*new =
509 XCALLOC(MTYPE_RFAPI_NEXTHOP
, sizeof(struct rfapi_nexthop
));
515 void rfapi_nexthop_free(void *p
)
517 struct rfapi_nexthop
*goner
= p
;
518 XFREE(MTYPE_RFAPI_NEXTHOP
, goner
);
521 struct rfapi_vn_option
*rfapi_vn_options_dup(struct rfapi_vn_option
*existing
)
523 struct rfapi_vn_option
*p
;
524 struct rfapi_vn_option
*head
= NULL
;
525 struct rfapi_vn_option
*tail
= NULL
;
527 for (p
= existing
; p
; p
= p
->next
) {
528 struct rfapi_vn_option
*new;
530 new = XCALLOC(MTYPE_RFAPI_VN_OPTION
,
531 sizeof(struct rfapi_vn_option
));
544 void rfapi_un_options_free(struct rfapi_un_option
*p
)
546 struct rfapi_un_option
*next
;
550 XFREE(MTYPE_RFAPI_UN_OPTION
, p
);
555 void rfapi_vn_options_free(struct rfapi_vn_option
*p
)
557 struct rfapi_vn_option
*next
;
561 XFREE(MTYPE_RFAPI_VN_OPTION
, p
);
566 /* Based on bgp_redistribute_add() */
567 void add_vnc_route(struct rfapi_descriptor
*rfd
, /* cookie, VPN UN addr, peer */
568 struct bgp
*bgp
, int safi
, struct prefix
*p
,
569 struct prefix_rd
*prd
, struct rfapi_ip_addr
*nexthop
,
570 uint32_t *local_pref
,
571 uint32_t *lifetime
, /* NULL => dont send lifetime */
572 struct bgp_tea_options
*rfp_options
,
573 struct rfapi_un_option
*options_un
,
574 struct rfapi_vn_option
*options_vn
,
575 struct ecommunity
*rt_export_list
, /* Copied, not consumed */
576 uint32_t *med
, /* NULL => don't set med */
577 uint32_t *label
, /* low order 3 bytes */
578 uint8_t type
, uint8_t sub_type
, /* RFP, NORMAL or REDIST */
581 afi_t afi
; /* of the VN address */
582 struct bgp_info
*new;
586 struct attr attr
= {0};
587 struct attr
*new_attr
;
590 struct bgp_attr_encap_subtlv
*encaptlv
;
591 char buf
[PREFIX_STRLEN
];
592 char buf2
[RD_ADDRSTRLEN
];
594 struct prefix pfx_buf
;
597 struct rfapi_nexthop
*lnh
= NULL
; /* local nexthop */
598 struct rfapi_vn_option
*vo
;
599 struct rfapi_l2address_option
*l2o
= NULL
;
600 struct rfapi_ip_addr
*un_addr
= &rfd
->un_addr
;
602 bgp_encap_types TunnelType
= BGP_ENCAP_TYPE_RESERVED
;
603 struct bgp_redist
*red
;
605 if (safi
== SAFI_ENCAP
606 && !(bgp
->rfapi_cfg
->flags
& BGP_VNC_CONFIG_ADV_UN_METHOD_ENCAP
)) {
609 * Encap mode not enabled. UN addresses will be communicated
610 * via VNC Tunnel subtlv instead.
612 vnc_zlog_debug_verbose(
613 "%s: encap mode not enabled, not adding SAFI_ENCAP route",
619 if ((safi
== SAFI_MPLS_VPN
) && (flags
& RFAPI_AHR_SET_PFX_TO_NEXTHOP
))
622 if (rfapiRaddr2Qprefix (nexthop
, &pfx_buf
))
624 vnc_zlog_debug_verbose
625 ("%s: can't set pfx to vn addr, not adding SAFI_MPLS_VPN route",
632 for (vo
= options_vn
; vo
; vo
= vo
->next
) {
633 if (RFAPI_VN_OPTION_TYPE_L2ADDR
== vo
->type
) {
635 if (RFAPI_0_ETHERADDR(&l2o
->macaddr
))
636 l2o
= NULL
; /* not MAC resolution */
638 if (RFAPI_VN_OPTION_TYPE_LOCAL_NEXTHOP
== vo
->type
) {
639 lnh
= &vo
->v
.local_nexthop
;
646 label_val
= MPLS_LABEL_IMPLICIT_NULL
;
648 prefix_rd2str(prd
, buf2
, sizeof(buf2
));
650 afi
= family2afi(p
->family
);
651 assert(afi
== AFI_IP
|| afi
== AFI_IP6
);
653 vnc_zlog_debug_verbose("%s: afi=%s, safi=%s", __func__
, afi2str(afi
),
656 /* Make default attribute. Produces already-interned attr.aspath */
657 /* Cripes, the memory management of attributes is byzantine */
659 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
664 * extra: dynamically allocated, owned by attr
665 * aspath: points to interned hash from aspath hash table
670 * Route-specific un_options get added to the VPN SAFI
671 * advertisement tunnel encap attribute. (the per-NVE
672 * "default" un_options are put into the 1-per-NVE ENCAP
673 * SAFI advertisement). The VPN SAFI also gets the
674 * default un_options if there are no route-specific options.
677 struct rfapi_un_option
*uo
;
679 for (uo
= options_un
; uo
; uo
= uo
->next
) {
680 if (RFAPI_UN_OPTION_TYPE_TUNNELTYPE
== uo
->type
) {
681 TunnelType
= rfapi_tunneltype_option_to_tlv(
682 bgp
, un_addr
, &uo
->v
.tunnel
, &attr
,
689 * These are the NVE-specific "default" un_options which are
690 * put into the 1-per-NVE ENCAP advertisement.
692 if (rfd
->default_tunneltype_option
.type
) {
693 TunnelType
= rfapi_tunneltype_option_to_tlv(
694 bgp
, un_addr
, &rfd
->default_tunneltype_option
,
696 } else /* create default for local addse */
697 if (type
== ZEBRA_ROUTE_BGP
698 && sub_type
== BGP_ROUTE_RFP
)
699 TunnelType
= rfapi_tunneltype_option_to_tlv(
700 bgp
, un_addr
, NULL
, &attr
, l2o
!= NULL
);
703 if (TunnelType
== BGP_ENCAP_TYPE_MPLS
) {
704 if (safi
== SAFI_ENCAP
) {
705 /* Encap SAFI not used with MPLS */
706 vnc_zlog_debug_verbose(
707 "%s: mpls tunnel type, encap safi omitted",
709 aspath_unintern(&attr
.aspath
); /* Unintern original. */
715 attr
.local_pref
= *local_pref
;
716 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
721 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
724 /* override default weight assigned by bgp_attr_default_set() */
725 attr
.weight
= rfd
->peer
? rfd
->peer
->weight
[afi
][safi
] : 0;
728 * NB: ticket 81: do not reset attr.aspath here because it would
729 * cause iBGP peers to drop route
733 * Set originator ID for routes imported from BGP directly.
734 * These routes could be synthetic, and therefore could
735 * reuse the peer pointers of the routes they are derived
736 * from. Setting the originator ID to "us" prevents the
737 * wrong originator ID from being sent when this route is
738 * sent from a route reflector.
740 if (type
== ZEBRA_ROUTE_BGP_DIRECT
741 || type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
) {
742 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
);
743 attr
.originator_id
= bgp
->router_id
;
747 /* Set up vnc attribute (sub-tlv for Prefix Lifetime) */
748 if (lifetime
&& *lifetime
!= RFAPI_INFINITE_LIFETIME
) {
751 encaptlv
= XCALLOC(MTYPE_ENCAP_TLV
,
752 sizeof(struct bgp_attr_encap_subtlv
) + 4);
755 BGP_VNC_SUBTLV_TYPE_LIFETIME
; /* prefix lifetime */
756 encaptlv
->length
= 4;
757 lt
= htonl(*lifetime
);
758 memcpy(encaptlv
->value
, <
, 4);
759 attr
.vnc_subtlvs
= encaptlv
;
760 vnc_zlog_debug_verbose(
761 "%s: set Encap Attr Prefix Lifetime to %d", __func__
,
765 /* add rfp options to vnc attr */
768 if (flags
& RFAPI_AHR_RFPOPT_IS_VNCTLV
) {
771 * this flag means we're passing a pointer to an
772 * existing encap tlv chain which we should copy.
773 * It's a hack to avoid adding yet another argument
776 encaptlv
= encap_tlv_dup(
777 (struct bgp_attr_encap_subtlv
*)rfp_options
);
778 if (attr
.vnc_subtlvs
) {
779 attr
.vnc_subtlvs
->next
= encaptlv
;
781 attr
.vnc_subtlvs
= encaptlv
;
785 struct bgp_tea_options
*hop
;
786 /* XXX max of one tlv present so far from above code */
787 struct bgp_attr_encap_subtlv
*tail
= attr
.vnc_subtlvs
;
789 for (hop
= rfp_options
; hop
; hop
= hop
->next
) {
796 sizeof(struct bgp_attr_encap_subtlv
) + 2
800 BGP_VNC_SUBTLV_TYPE_RFPOPTION
; /* RFP
803 encaptlv
->length
= 2 + hop
->length
;
804 *((uint8_t *)(encaptlv
->value
) + 0) = hop
->type
;
805 *((uint8_t *)(encaptlv
->value
) + 1) =
807 memcpy(((uint8_t *)encaptlv
->value
) + 2,
808 hop
->value
, hop
->length
);
811 * add to end of subtlv chain
814 tail
->next
= encaptlv
;
816 attr
.vnc_subtlvs
= encaptlv
;
826 * extra: dynamically allocated, owned by attr
827 * vnc_subtlvs: dynamic chain, length 1
828 * aspath: points to interned hash from aspath hash table
832 attr
.ecommunity
= ecommunity_new();
833 assert(attr
.ecommunity
);
835 if (TunnelType
!= BGP_ENCAP_TYPE_MPLS
836 && TunnelType
!= BGP_ENCAP_TYPE_RESERVED
) {
838 * Add BGP Encapsulation Extended Community. Format described in
839 * section 4.5 of RFC 5512.
840 * Always include when not MPLS type, to disambiguate this case.
842 struct ecommunity_val beec
;
844 memset(&beec
, 0, sizeof(beec
));
845 beec
.val
[0] = ECOMMUNITY_ENCODE_OPAQUE
;
846 beec
.val
[1] = ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP
;
847 beec
.val
[6] = ((TunnelType
) >> 8) & 0xff;
848 beec
.val
[7] = (TunnelType
)&0xff;
849 ecommunity_add_val(attr
.ecommunity
, &beec
);
853 * Add extended community attributes to match rt export list
855 if (rt_export_list
) {
857 ecommunity_merge(attr
.ecommunity
, rt_export_list
);
860 if (attr
.ecommunity
->size
) {
861 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
863 ecommunity_free(&attr
.ecommunity
);
864 attr
.ecommunity
= NULL
;
866 vnc_zlog_debug_verbose("%s: attr.ecommunity=%p", __func__
,
873 * extra: dynamically allocated, owned by attr
874 * vnc_subtlvs: dynamic chain, length 1
875 * ecommunity: dynamic 2-part
876 * aspath: points to interned hash from aspath hash table
879 /* stuff nexthop in attr_extra; which field depends on IPv4 or IPv6 */
880 switch (nexthop
->addr_family
) {
883 * set this field to prevent bgp_route.c code from setting
884 * mp_nexthop_global_in to self
886 attr
.nexthop
.s_addr
= nexthop
->addr
.v4
.s_addr
;
888 attr
.mp_nexthop_global_in
= nexthop
->addr
.v4
;
889 attr
.mp_nexthop_len
= 4;
893 attr
.mp_nexthop_global
= nexthop
->addr
.v6
;
894 attr
.mp_nexthop_len
= 16;
902 prefix2str(p
, buf
, sizeof(buf
));
908 * extra: dynamically allocated, owned by attr
909 * vnc_subtlvs: dynamic chain, length 1
910 * ecommunity: dynamic 2-part
911 * aspath: points to interned hash from aspath hash table
914 red
= bgp_redist_lookup(bgp
, afi
, type
, 0);
916 if (red
&& red
->redist_metric_flag
) {
917 attr
.med
= red
->redist_metric
;
918 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
921 bn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
924 * bgp_attr_intern creates a new reference to a cached
925 * attribute, but leaves the following bits of trash:
927 * - old attr->extra (free via bgp_attr_extra_free(attr))
929 * Note that it frees the original attr->extra->ecommunity
930 * but leaves the new attribute pointing to the ORIGINAL
931 * vnc options (which therefore we needn't free from the
934 new_attr
= bgp_attr_intern(&attr
);
936 aspath_unintern(&attr
.aspath
); /* Unintern original. */
942 * extra: dynamically allocated, owned by attr
943 * vnc_subtlvs: dynamic chain, length 1
944 * ecommunity: POINTS TO INTERNED ecom, THIS REF NOT COUNTED
946 * new_attr: an attr that is part of the hash table, distinct
947 * from attr which is static.
948 * extra: dynamically allocated, owned by new_attr (in hash table)
949 * vnc_subtlvs: POINTS TO SAME dynamic chain AS attr
950 * ecommunity: POINTS TO interned/refcounted dynamic 2-part AS attr
951 * aspath: POINTS TO interned/refcounted hashed block
953 for (bi
= bn
->info
; bi
; bi
= bi
->next
) {
954 /* probably only need to check
955 * bi->extra->vnc.export.rfapi_handle */
956 if (bi
->peer
== rfd
->peer
&& bi
->type
== type
957 && bi
->sub_type
== sub_type
&& bi
->extra
958 && bi
->extra
->vnc
.export
.rfapi_handle
== (void *)rfd
) {
967 * Adding new local_nexthop, which does not by itself change
968 * what is advertised via BGP
971 if (!bi
->extra
->vnc
.export
.local_nexthops
) {
972 /* TBD make arrangements to free when needed */
973 bi
->extra
->vnc
.export
.local_nexthops
=
975 bi
->extra
->vnc
.export
.local_nexthops
->del
=
982 struct listnode
*node
;
983 struct rfapi_nexthop
*pLnh
= NULL
;
985 for (ALL_LIST_ELEMENTS_RO(
986 bi
->extra
->vnc
.export
.local_nexthops
, node
,
989 if (prefix_same(&pLnh
->addr
, &lnh
->addr
)) {
995 * Not present, add new one
998 pLnh
= rfapi_nexthop_new(lnh
);
1000 bi
->extra
->vnc
.export
.local_nexthops
,
1005 if (attrhash_cmp(bi
->attr
, new_attr
)
1006 && !CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
)) {
1007 bgp_attr_unintern(&new_attr
);
1008 bgp_unlock_node(bn
);
1011 "%s: Found route (safi=%d) at prefix %s, no change",
1012 __func__
, safi
, buf
);
1016 /* The attribute is changed. */
1017 bgp_info_set_flag(bn
, bi
, BGP_INFO_ATTR_CHANGED
);
1019 if (safi
== SAFI_MPLS_VPN
) {
1020 struct bgp_node
*prn
= NULL
;
1021 struct bgp_table
*table
= NULL
;
1023 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
1024 (struct prefix
*)prd
);
1026 table
= (struct bgp_table
*)(prn
->info
);
1028 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
1029 bgp
, prd
, table
, p
, bi
);
1031 bgp_unlock_node(prn
);
1034 /* Rewrite BGP route information. */
1035 if (CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
))
1036 bgp_info_restore(bn
, bi
);
1038 bgp_aggregate_decrement(bgp
, p
, bi
, afi
, safi
);
1039 bgp_attr_unintern(&bi
->attr
);
1040 bi
->attr
= new_attr
;
1041 bi
->uptime
= bgp_clock();
1044 if (safi
== SAFI_MPLS_VPN
) {
1045 struct bgp_node
*prn
= NULL
;
1046 struct bgp_table
*table
= NULL
;
1048 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
1049 (struct prefix
*)prd
);
1051 table
= (struct bgp_table
*)(prn
->info
);
1053 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
1054 bgp
, prd
, table
, p
, bi
);
1056 bgp_unlock_node(prn
);
1059 /* Process change. */
1060 bgp_aggregate_increment(bgp
, p
, bi
, afi
, safi
);
1061 bgp_process(bgp
, bn
, afi
, safi
);
1062 bgp_unlock_node(bn
);
1065 "%s: Found route (safi=%d) at prefix %s, changed attr",
1066 __func__
, safi
, buf
);
1073 new = bgp_info_new();
1075 new->sub_type
= sub_type
;
1076 new->peer
= rfd
->peer
;
1077 SET_FLAG(new->flags
, BGP_INFO_VALID
);
1078 new->attr
= new_attr
;
1079 new->uptime
= bgp_clock();
1081 /* save backref to rfapi handle */
1082 assert(bgp_info_extra_get(new));
1083 new->extra
->vnc
.export
.rfapi_handle
= (void *)rfd
;
1084 encode_label(label_val
, &new->extra
->label
[0]);
1088 if (VNC_DEBUG(VERBOSE
)) {
1089 vnc_zlog_debug_verbose("%s: printing BI", __func__
);
1090 rfapiPrintBi(NULL
, new);
1093 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
1094 bgp_info_add(bn
, new);
1096 if (safi
== SAFI_MPLS_VPN
) {
1097 struct bgp_node
*prn
= NULL
;
1098 struct bgp_table
*table
= NULL
;
1100 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
1102 table
= (struct bgp_table
*)(prn
->info
);
1104 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
1105 bgp
, prd
, table
, p
, new);
1107 bgp_unlock_node(prn
);
1108 encode_label(label_val
, &bn
->local_label
);
1111 bgp_unlock_node(bn
);
1112 bgp_process(bgp
, bn
, afi
, safi
);
1115 "%s: Added route (safi=%s) at prefix %s (bn=%p, prd=%s)",
1116 __func__
, safi2str(safi
), buf
, bn
, buf2
);
1119 /* Loop back to import tables */
1120 rfapiProcessUpdate(rfd
->peer
, rfd
, p
, prd
, new_attr
, afi
, safi
, type
,
1121 sub_type
, &label_val
);
1122 vnc_zlog_debug_verbose("%s: looped back import route (safi=%d)",
1126 uint32_t rfp_cost_to_localpref(uint8_t cost
)
1131 static void rfapiTunnelRouteAnnounce(struct bgp
*bgp
,
1132 struct rfapi_descriptor
*rfd
,
1133 uint32_t *pLifetime
)
1135 struct prefix_rd prd
;
1136 struct prefix pfx_vn
;
1138 uint32_t local_pref
= rfp_cost_to_localpref(0);
1140 rc
= rfapiRaddr2Qprefix(&(rfd
->vn_addr
), &pfx_vn
);
1144 * Construct route distinguisher = 0
1146 memset(&prd
, 0, sizeof(prd
));
1147 prd
.family
= AF_UNSPEC
;
1150 add_vnc_route(rfd
, /* rfapi descr, for export list & backref */
1151 bgp
, /* which bgp instance */
1152 SAFI_ENCAP
, /* which SAFI */
1153 &pfx_vn
, /* prefix to advertise */
1154 &prd
, /* route distinguisher to use */
1155 &rfd
->un_addr
, /* nexthop */
1157 pLifetime
, /* max lifetime of child VPN routes */
1158 NULL
, /* no rfp options for ENCAP safi */
1159 NULL
, /* rfp un options */
1160 NULL
, /* rfp vn options */
1161 rfd
->rt_export_list
, NULL
, /* med */
1162 NULL
, /* label: default */
1163 ZEBRA_ROUTE_BGP
, BGP_ROUTE_RFP
, 0);
1167 /***********************************************************************
1168 * RFP processing behavior configuration
1169 ***********************************************************************/
1171 /*------------------------------------------
1172 * rfapi_rfp_set_configuration
1174 * This is used to change rfapi's processing behavior based on
1178 * rfp_start_val value returned by rfp_start
1179 * rfapi_rfp_cfg Pointer to configuration structure
1186 * ENXIO Unabled to locate configured BGP/VNC
1187 --------------------------------------------*/
1188 int rfapi_rfp_set_configuration(void *rfp_start_val
, struct rfapi_rfp_cfg
*new)
1190 struct rfapi_rfp_cfg
*rcfg
;
1193 bgp
= rfapi_bgp_lookup_by_rfp(rfp_start_val
);
1195 if (!new || !bgp
|| !bgp
->rfapi_cfg
)
1198 rcfg
= &bgp
->rfapi_cfg
->rfp_cfg
;
1199 rcfg
->download_type
= new->download_type
;
1200 rcfg
->ftd_advertisement_interval
= new->ftd_advertisement_interval
;
1201 rcfg
->holddown_factor
= new->holddown_factor
;
1203 if (rcfg
->use_updated_response
!= new->use_updated_response
) {
1204 rcfg
->use_updated_response
= new->use_updated_response
;
1205 if (rcfg
->use_updated_response
)
1206 rfapiMonitorCallbacksOn(bgp
);
1208 rfapiMonitorCallbacksOff(bgp
);
1210 if (rcfg
->use_removes
!= new->use_removes
) {
1211 rcfg
->use_removes
= new->use_removes
;
1212 if (rcfg
->use_removes
)
1213 rfapiMonitorResponseRemovalOn(bgp
);
1215 rfapiMonitorResponseRemovalOff(bgp
);
1220 /*------------------------------------------
1221 * rfapi_rfp_set_cb_methods
1223 * Change registered callback functions for asynchronous notifications
1224 * from RFAPI to the RFP client.
1227 * rfp_start_val value returned by rfp_start
1228 * methods Pointer to struct rfapi_rfp_cb_methods containing
1229 * pointers to callback methods as described above
1233 * ENXIO BGP or VNC not configured
1234 *------------------------------------------*/
1235 int rfapi_rfp_set_cb_methods(void *rfp_start_val
,
1236 struct rfapi_rfp_cb_methods
*methods
)
1241 bgp
= rfapi_bgp_lookup_by_rfp(rfp_start_val
);
1249 h
->rfp_methods
= *methods
;
1254 /***********************************************************************
1256 ***********************************************************************/
1258 * Caller must supply an already-allocated rfd with the "caller"
1259 * fields already set (vn_addr, un_addr, callback, cookie)
1260 * The advertised_prefixes[] array elements should be NULL to
1261 * have this function set them to newly-allocated radix trees.
1263 static int rfapi_open_inner(struct rfapi_descriptor
*rfd
, struct bgp
*bgp
,
1264 struct rfapi
*h
, struct rfapi_nve_group_cfg
*rfg
)
1268 if (h
->flags
& RFAPI_INCALLBACK
)
1272 * Fill in configured fields
1276 * If group's RD is specified as "auto", then fill in based
1277 * on NVE's VN address
1281 if (rfd
->rd
.family
== AF_UNIX
) {
1282 ret
= rfapi_set_autord_from_vn(&rfd
->rd
, &rfd
->vn_addr
);
1286 rfd
->rt_export_list
= (rfg
->rt_export_list
)
1287 ? ecommunity_dup(rfg
->rt_export_list
)
1289 rfd
->response_lifetime
= rfg
->response_lifetime
;
1293 * Fill in BGP peer structure
1295 rfd
->peer
= peer_new(bgp
);
1296 rfd
->peer
->status
= Established
; /* keep bgp core happy */
1297 bgp_sync_delete(rfd
->peer
); /* don't need these */
1300 * since this peer is not on the I/O thread, this lock is not strictly
1301 * necessary, but serves as a reminder to those who may meddle...
1303 pthread_mutex_lock(&rfd
->peer
->io_mtx
);
1305 // we don't need any I/O related facilities
1306 if (rfd
->peer
->ibuf
)
1307 stream_fifo_free(rfd
->peer
->ibuf
);
1308 if (rfd
->peer
->obuf
)
1309 stream_fifo_free(rfd
->peer
->obuf
);
1311 if (rfd
->peer
->ibuf_work
)
1312 ringbuf_del(rfd
->peer
->ibuf_work
);
1313 if (rfd
->peer
->obuf_work
)
1314 stream_free(rfd
->peer
->obuf_work
);
1316 rfd
->peer
->ibuf
= NULL
;
1317 rfd
->peer
->obuf
= NULL
;
1318 rfd
->peer
->obuf_work
= NULL
;
1319 rfd
->peer
->ibuf_work
= NULL
;
1321 pthread_mutex_unlock(&rfd
->peer
->io_mtx
);
1323 { /* base code assumes have valid host pointer */
1327 if (rfd
->vn_addr
.addr_family
== AF_INET
) {
1328 inet_ntop(AF_INET
, &rfd
->vn_addr
.addr
.v4
, buf
, BUFSIZ
);
1329 } else if (rfd
->vn_addr
.addr_family
== AF_INET6
) {
1330 inet_ntop(AF_INET6
, &rfd
->vn_addr
.addr
.v6
, buf
, BUFSIZ
);
1332 rfd
->peer
->host
= XSTRDUP(MTYPE_BGP_PEER_HOST
, buf
);
1334 /* Mark peer as belonging to HD */
1335 SET_FLAG(rfd
->peer
->flags
, PEER_FLAG_IS_RFAPI_HD
);
1338 * Set min prefix lifetime to max value so it will get set
1339 * upon first rfapi_register()
1341 rfd
->min_prefix_lifetime
= UINT32_MAX
;
1344 * Allocate response tables if needed
1346 #define RFD_RTINIT_AFI(rh, ary, afi) \
1349 ary[afi] = route_table_init(); \
1350 ary[afi]->info = rh; \
1354 #define RFD_RTINIT(rh, ary) \
1356 RFD_RTINIT_AFI(rh, ary, AFI_IP); \
1357 RFD_RTINIT_AFI(rh, ary, AFI_IP6); \
1358 RFD_RTINIT_AFI(rh, ary, AFI_L2VPN); \
1361 RFD_RTINIT(rfd
, rfd
->rib
);
1362 RFD_RTINIT(rfd
, rfd
->rib_pending
);
1363 RFD_RTINIT(rfd
, rfd
->rsp_times
);
1366 * Link to Import Table
1368 rfd
->import_table
= rfg
->rfapi_import_table
;
1369 rfd
->import_table
->refcount
+= 1;
1371 rfapiApInit(&rfd
->advertised
);
1374 * add this NVE descriptor to the list of NVEs in the NVE group
1377 rfg
->nves
= list_new();
1379 listnode_add(rfg
->nves
, rfd
);
1381 vnc_direct_bgp_add_nve(bgp
, rfd
);
1382 vnc_zebra_add_nve(bgp
, rfd
);
1387 /* moved from rfapi_register */
1388 int rfapi_init_and_open(struct bgp
*bgp
, struct rfapi_descriptor
*rfd
,
1389 struct rfapi_nve_group_cfg
*rfg
)
1391 struct rfapi
*h
= bgp
->rfapi
;
1392 char buf_vn
[BUFSIZ
];
1393 char buf_un
[BUFSIZ
];
1394 afi_t afi_vn
, afi_un
;
1395 struct prefix pfx_un
;
1396 struct route_node
*rn
;
1399 rfapi_time(&rfd
->open_time
);
1401 if (rfg
->type
== RFAPI_GROUP_CFG_VRF
)
1402 SET_FLAG(rfd
->flags
, RFAPI_HD_FLAG_IS_VRF
);
1404 rfapiRfapiIpAddr2Str(&rfd
->vn_addr
, buf_vn
, BUFSIZ
);
1405 rfapiRfapiIpAddr2Str(&rfd
->un_addr
, buf_un
, BUFSIZ
);
1407 vnc_zlog_debug_verbose("%s: new RFD with VN=%s UN=%s cookie=%p",
1408 __func__
, buf_vn
, buf_un
, rfd
->cookie
);
1410 if (rfg
->type
!= RFAPI_GROUP_CFG_VRF
) /* unclear if needed for VRF */
1412 listnode_add(&h
->descriptors
, rfd
);
1413 if (h
->descriptors
.count
> h
->stat
.max_descriptors
) {
1414 h
->stat
.max_descriptors
= h
->descriptors
.count
;
1418 * attach to UN radix tree
1420 afi_vn
= family2afi(rfd
->vn_addr
.addr_family
);
1421 afi_un
= family2afi(rfd
->un_addr
.addr_family
);
1422 assert(afi_vn
&& afi_un
);
1423 assert(!rfapiRaddr2Qprefix(&rfd
->un_addr
, &pfx_un
));
1425 rn
= route_node_get(h
->un
[afi_un
], &pfx_un
);
1427 rfd
->next
= rn
->info
;
1431 return rfapi_open_inner(rfd
, bgp
, h
, rfg
);
1434 struct rfapi_vn_option
*rfapiVnOptionsDup(struct rfapi_vn_option
*orig
)
1436 struct rfapi_vn_option
*head
= NULL
;
1437 struct rfapi_vn_option
*tail
= NULL
;
1438 struct rfapi_vn_option
*vo
= NULL
;
1440 for (vo
= orig
; vo
; vo
= vo
->next
) {
1441 struct rfapi_vn_option
*new;
1443 new = XCALLOC(MTYPE_RFAPI_VN_OPTION
,
1444 sizeof(struct rfapi_vn_option
));
1445 memcpy(new, vo
, sizeof(struct rfapi_vn_option
));
1457 struct rfapi_un_option
*rfapiUnOptionsDup(struct rfapi_un_option
*orig
)
1459 struct rfapi_un_option
*head
= NULL
;
1460 struct rfapi_un_option
*tail
= NULL
;
1461 struct rfapi_un_option
*uo
= NULL
;
1463 for (uo
= orig
; uo
; uo
= uo
->next
) {
1464 struct rfapi_un_option
*new;
1466 new = XCALLOC(MTYPE_RFAPI_UN_OPTION
,
1467 sizeof(struct rfapi_un_option
));
1468 memcpy(new, uo
, sizeof(struct rfapi_un_option
));
1480 struct bgp_tea_options
*rfapiOptionsDup(struct bgp_tea_options
*orig
)
1482 struct bgp_tea_options
*head
= NULL
;
1483 struct bgp_tea_options
*tail
= NULL
;
1484 struct bgp_tea_options
*hop
= NULL
;
1486 for (hop
= orig
; hop
; hop
= hop
->next
) {
1487 struct bgp_tea_options
*new;
1489 new = XCALLOC(MTYPE_BGP_TEA_OPTIONS
,
1490 sizeof(struct bgp_tea_options
));
1491 memcpy(new, hop
, sizeof(struct bgp_tea_options
));
1494 new->value
= XCALLOC(MTYPE_BGP_TEA_OPTIONS_VALUE
,
1496 memcpy(new->value
, hop
->value
, hop
->length
);
1507 void rfapiFreeBgpTeaOptionChain(struct bgp_tea_options
*p
)
1509 struct bgp_tea_options
*next
;
1515 XFREE(MTYPE_BGP_TEA_OPTIONS_VALUE
, p
->value
);
1518 XFREE(MTYPE_BGP_TEA_OPTIONS
, p
);
1524 void rfapiAdbFree(struct rfapi_adb
*adb
)
1526 XFREE(MTYPE_RFAPI_ADB
, adb
);
1530 rfapi_query_inner(void *handle
, struct rfapi_ip_addr
*target
,
1531 struct rfapi_l2address_option
*l2o
, /* may be NULL */
1532 struct rfapi_next_hop_entry
**ppNextHopEntry
)
1536 struct prefix p_original
;
1537 struct route_node
*rn
;
1538 struct rfapi_descriptor
*rfd
= (struct rfapi_descriptor
*)handle
;
1539 struct bgp
*bgp
= rfd
->bgp
;
1540 struct rfapi_next_hop_entry
*pNHE
= NULL
;
1541 struct rfapi_ip_addr
*self_vn_addr
= NULL
;
1543 int use_eth_resolution
= 0;
1544 struct rfapi_next_hop_entry
*i_nhe
;
1548 vnc_zlog_debug_verbose("%s: No BGP instance, returning ENXIO",
1553 vnc_zlog_debug_verbose("%s: No RFAPI instance, returning ENXIO",
1557 if (bgp
->rfapi
->flags
& RFAPI_INCALLBACK
) {
1558 vnc_zlog_debug_verbose(
1559 "%s: Called during calback, returning EDEADLK",
1564 if (!is_valid_rfd(rfd
)) {
1565 vnc_zlog_debug_verbose("%s: invalid handle, returning EBADF",
1570 rfd
->rsp_counter
++; /* dedup: identify this generation */
1571 rfd
->rsp_time
= rfapi_time(NULL
); /* response content dedup */
1572 rfd
->ftd_last_allowed_time
=
1574 - bgp
->rfapi_cfg
->rfp_cfg
.ftd_advertisement_interval
;
1577 if (!memcmp(l2o
->macaddr
.octet
, rfapi_ethaddr0
.octet
,
1581 /* per t/c Paul/Lou 151022 */
1582 if (!eth_is_0
|| l2o
->logical_net_id
) {
1583 use_eth_resolution
= 1;
1588 *ppNextHopEntry
= NULL
;
1591 * Save original target in prefix form. In case of L2-based queries,
1592 * p_original will be modified to reflect the L2 target
1594 assert(!rfapiRaddr2Qprefix(target
, &p_original
));
1596 if (bgp
->rfapi_cfg
->rfp_cfg
.download_type
== RFAPI_RFP_DOWNLOAD_FULL
) {
1597 /* convert query to 0/0 when full-table download is enabled */
1598 memset((char *)&p
, 0, sizeof(p
));
1599 p
.family
= target
->addr_family
;
1605 char buf
[PREFIX_STRLEN
];
1608 prefix2str(&p
, buf
, sizeof(buf
));
1609 vnc_zlog_debug_verbose("%s(rfd=%p, target=%s, ppNextHop=%p)",
1610 __func__
, rfd
, buf
, ppNextHopEntry
);
1612 s
= ecommunity_ecom2str(rfd
->import_table
->rt_import_list
,
1613 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1614 vnc_zlog_debug_verbose(
1615 "%s rfd->import_table=%p, rfd->import_table->rt_import_list: %s",
1616 __func__
, rfd
->import_table
, s
);
1617 XFREE(MTYPE_ECOMMUNITY_STR
, s
);
1620 afi
= family2afi(p
.family
);
1623 if (CHECK_FLAG(bgp
->rfapi_cfg
->flags
,
1624 BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP
)) {
1625 self_vn_addr
= &rfd
->vn_addr
;
1628 if (use_eth_resolution
) {
1629 uint32_t logical_net_id
= l2o
->logical_net_id
;
1630 struct ecommunity
*l2com
;
1633 * fix up p_original to contain L2 address
1635 rfapiL2o2Qprefix(l2o
, &p_original
);
1637 l2com
= bgp_rfapi_get_ecommunity_by_lni_label(
1638 bgp
, 1, logical_net_id
, l2o
->label
);
1640 uint8_t *v
= l2com
->val
;
1641 logical_net_id
= (v
[5] << 16) + (v
[6] << 8) + (v
[7]);
1644 * Ethernet/L2-based lookup
1646 * Always returns IT node corresponding to route
1649 if (RFAPI_RFP_DOWNLOAD_FULL
1650 == bgp
->rfapi_cfg
->rfp_cfg
.download_type
) {
1654 rn
= rfapiMonitorEthAdd(
1655 bgp
, rfd
, (eth_is_0
? &rfapi_ethaddr0
: &l2o
->macaddr
),
1659 struct rfapi_ip_prefix rprefix
;
1661 memset(&rprefix
, 0, sizeof(rprefix
));
1662 rprefix
.prefix
.addr_family
= target
->addr_family
;
1663 if (target
->addr_family
== AF_INET
) {
1664 rprefix
.length
= 32;
1666 rprefix
.length
= 128;
1669 pNHE
= rfapiEthRouteTable2NextHopList(
1670 logical_net_id
, &rprefix
,
1671 rfd
->response_lifetime
, self_vn_addr
,
1672 rfd
->rib
[afi
], &p_original
);
1682 rn
= rfapiMonitorAdd(bgp
, rfd
, &p
);
1685 * If target address is 0, this request is special: means to
1686 * return ALL routes in the table
1688 * Monitors for All-Routes queries get put on a special list,
1689 * not in the VPN tree
1691 if (RFAPI_0_PREFIX(&p
)) {
1693 vnc_zlog_debug_verbose("%s: 0-prefix", __func__
);
1696 * Generate nexthop list for caller
1698 pNHE
= rfapiRouteTable2NextHopList(
1699 rfd
->import_table
->imported_vpn
[afi
],
1700 rfd
->response_lifetime
, self_vn_addr
,
1701 rfd
->rib
[afi
], &p_original
);
1706 route_lock_node(rn
); /* so we can unlock below */
1709 * returns locked node. Don't unlock yet because the
1711 * might free it before we're done with it. This
1713 * could occur when rfapiMonitorGetAttachNode() returns
1715 * newly-created default node.
1717 rn
= rfapiMonitorGetAttachNode(rfd
, &p
);
1723 route_unlock_node(rn
);
1724 vnc_zlog_debug_verbose(
1725 "%s: VPN route not found, returning ENOENT", __func__
);
1729 if (VNC_DEBUG(RFAPI_QUERY
)) {
1730 rfapiShowImportTable(NULL
, "query",
1731 rfd
->import_table
->imported_vpn
[afi
], 1);
1734 if (use_eth_resolution
) {
1736 struct rfapi_ip_prefix rprefix
;
1738 memset(&rprefix
, 0, sizeof(rprefix
));
1739 rprefix
.prefix
.addr_family
= target
->addr_family
;
1740 if (target
->addr_family
== AF_INET
) {
1741 rprefix
.length
= 32;
1743 rprefix
.length
= 128;
1746 pNHE
= rfapiEthRouteNode2NextHopList(
1747 rn
, &rprefix
, rfd
->response_lifetime
, self_vn_addr
,
1748 rfd
->rib
[afi
], &p_original
);
1753 * Generate answer to query
1755 pNHE
= rfapiRouteNode2NextHopList(rn
, rfd
->response_lifetime
,
1756 self_vn_addr
, rfd
->rib
[afi
],
1760 route_unlock_node(rn
);
1763 if (ppNextHopEntry
) {
1764 /* only count if caller gets it */
1765 ++bgp
->rfapi
->response_immediate_count
;
1769 vnc_zlog_debug_verbose("%s: NO NHEs, returning ENOENT",
1775 * count nexthops for statistics
1777 for (i_nhe
= pNHE
; i_nhe
; i_nhe
= i_nhe
->next
) {
1778 ++rfd
->stat_count_nh_reachable
;
1781 if (ppNextHopEntry
) {
1782 *ppNextHopEntry
= pNHE
;
1784 rfapi_free_next_hop_list(pNHE
);
1787 vnc_zlog_debug_verbose("%s: success", __func__
);
1792 * support on-the-fly reassignment of an already-open nve to a new
1793 * nve-group in the event that its original nve-group is
1794 * administratively deleted.
1796 static int rfapi_open_rfd(struct rfapi_descriptor
*rfd
, struct bgp
*bgp
)
1798 struct prefix pfx_vn
;
1799 struct prefix pfx_un
;
1800 struct rfapi_nve_group_cfg
*rfg
;
1802 struct rfapi_cfg
*hc
;
1809 hc
= bgp
->rfapi_cfg
;
1813 rc
= rfapiRaddr2Qprefix(&rfd
->vn_addr
, &pfx_vn
);
1816 rc
= rfapiRaddr2Qprefix(&rfd
->un_addr
, &pfx_un
);
1820 * Find the matching nve group config block
1822 rfg
= bgp_rfapi_cfg_match_group(hc
, &pfx_vn
, &pfx_un
);
1828 * check nve group config block for required values
1830 if (!rfg
->rt_export_list
|| !rfg
->rfapi_import_table
) {
1835 rc
= rfapi_open_inner(rfd
, bgp
, h
, rfg
);
1841 * re-advertise registered routes, this time as part of new NVE-group
1843 rfapiApReadvertiseAll(bgp
, rfd
);
1846 * re-attach callbacks to import table
1848 if (!(bgp
->rfapi_cfg
->flags
& BGP_VNC_CONFIG_CALLBACK_DISABLE
)) {
1849 rfapiMonitorAttachImportHd(rfd
);
1855 /*------------------------------------------
1858 * This function initializes a NVE record and associates it with
1859 * the specified VN and underlay network addresses
1862 * rfp_start_val value returned by rfp_start
1863 * vn NVE virtual network address
1865 * un NVE underlay network address
1867 * default_options Default options to use on registrations.
1868 * For now only tunnel type is supported.
1869 * May be overridden per-prefix in rfapi_register().
1870 * Caller owns (rfapi_open() does not free)
1872 * response_cb Pointer to next hop list update callback function or
1873 * NULL when no callbacks are desired.
1875 * userdata Passed to subsequent response_cb invocations.
1878 * response_lifetime The length of time that responses sent to this
1881 * pHandle pointer to location to store rfapi handle. The
1882 * handle must be passed on subsequent rfapi_ calls.
1887 * EEXIST NVE with this {vn,un} already open
1888 * ENOENT No matching nve group config
1889 * ENOMSG Matched nve group config was incomplete
1890 * ENXIO BGP or VNC not configured
1891 * EAFNOSUPPORT Matched nve group specifies auto-assignment of RD,
1892 * but underlay network address is not IPv4
1893 * EDEADLK Called from within a callback procedure
1894 *------------------------------------------*/
1895 int rfapi_open(void *rfp_start_val
, struct rfapi_ip_addr
*vn
,
1896 struct rfapi_ip_addr
*un
,
1897 struct rfapi_un_option
*default_options
,
1898 uint32_t *response_lifetime
,
1899 void *userdata
, /* callback cookie */
1900 rfapi_handle
*pHandle
)
1904 struct rfapi_descriptor
*rfd
;
1905 struct rfapi_cfg
*hc
;
1906 struct rfapi_nve_group_cfg
*rfg
;
1908 struct prefix pfx_vn
;
1909 struct prefix pfx_un
;
1912 rfapi_handle hh
= NULL
;
1913 int reusing_provisional
= 0;
1916 char buf
[2][INET_ADDRSTRLEN
];
1917 vnc_zlog_debug_verbose(
1918 "%s: VN=%s UN=%s", __func__
,
1919 rfapiRfapiIpAddr2Str(vn
, buf
[0], INET_ADDRSTRLEN
),
1920 rfapiRfapiIpAddr2Str(un
, buf
[1], INET_ADDRSTRLEN
));
1926 bgp
= rfapi_bgp_lookup_by_rfp(rfp_start_val
);
1934 hc
= bgp
->rfapi_cfg
;
1938 if (h
->flags
& RFAPI_INCALLBACK
)
1941 rc
= rfapiRaddr2Qprefix(vn
, &pfx_vn
);
1944 rc
= rfapiRaddr2Qprefix(un
, &pfx_un
);
1948 * already have a descriptor with VN and UN?
1950 if (!rfapi_find_handle(bgp
, vn
, un
, &hh
)) {
1952 * we might have set up a handle for static routes before
1953 * this NVE was opened. In that case, reuse the handle
1956 if (!CHECK_FLAG(rfd
->flags
, RFAPI_HD_FLAG_PROVISIONAL
)) {
1961 * reuse provisional descriptor
1964 reusing_provisional
= 1;
1968 * Find the matching nve group config block
1970 rfg
= bgp_rfapi_cfg_match_group(hc
, &pfx_vn
, &pfx_un
);
1972 ++h
->stat
.count_unknown_nves
;
1974 char buf
[2][INET_ADDRSTRLEN
];
1975 zlog_notice("%s: no matching group VN=%s UN=%s",
1977 rfapiRfapiIpAddr2Str(vn
, buf
[0],
1979 rfapiRfapiIpAddr2Str(un
, buf
[1],
1986 * check nve group config block for required values
1988 if (!rfg
->rt_export_list
|| !rfg
->rfapi_import_table
) {
1990 ++h
->stat
.count_unknown_nves
;
1995 * If group config specifies auto-rd assignment, check that
1996 * VN address is IPv4|v6 so we don't fail in rfapi_open_inner().
1997 * Check here so we don't need to unwind memory allocations, &c.
1999 if ((rfg
->rd
.family
== AF_UNIX
) && (vn
->addr_family
!= AF_INET
)
2000 && (vn
->addr_family
!= AF_INET6
)) {
2001 return EAFNOSUPPORT
;
2006 * reusing provisional rfd
2010 rfd
= XCALLOC(MTYPE_RFAPI_DESC
,
2011 sizeof(struct rfapi_descriptor
));
2016 if (default_options
) {
2017 struct rfapi_un_option
*p
;
2019 for (p
= default_options
; p
; p
= p
->next
) {
2020 if ((RFAPI_UN_OPTION_TYPE_PROVISIONAL
== p
->type
)) {
2021 rfd
->flags
|= RFAPI_HD_FLAG_PROVISIONAL
;
2023 if ((RFAPI_UN_OPTION_TYPE_TUNNELTYPE
== p
->type
)) {
2024 rfd
->default_tunneltype_option
= p
->v
.tunnel
;
2030 * Fill in caller fields
2034 rfd
->cookie
= userdata
;
2036 if (!reusing_provisional
) {
2037 rc
= rfapi_init_and_open(bgp
, rfd
, rfg
);
2039 * This can fail only if the VN address is IPv6 and the group
2040 * specified auto-assignment of RDs, which only works for v4,
2041 * and the check above should catch it.
2043 * Another failure possibility is that we were called
2044 * during an rfapi callback. Also checked above.
2049 if (response_lifetime
)
2050 *response_lifetime
= rfd
->response_lifetime
;
2056 * For use with debug functions
2058 static int rfapi_set_response_cb(struct rfapi_descriptor
*rfd
,
2059 rfapi_response_cb_t
*response_cb
)
2061 if (!is_valid_rfd(rfd
))
2063 rfd
->response_cb
= response_cb
;
2070 * Does almost all the work of rfapi_close, except:
2071 * 1. preserves the descriptor (doesn't free it)
2072 * 2. preserves the prefix query list (i.e., rfd->mon list)
2073 * 3. preserves the advertised prefix list (rfd->advertised)
2074 * 4. preserves the rib and rib_pending tables
2076 * The purpose of organizing it this way is to support on-the-fly
2077 * reassignment of an already-open nve to a new nve-group in the
2078 * event that its original nve-group is administratively deleted.
2080 static int rfapi_close_inner(struct rfapi_descriptor
*rfd
, struct bgp
*bgp
)
2083 struct prefix pfx_vn
;
2084 struct prefix_rd prd
; /* currently always 0 for VN->UN */
2086 if (!is_valid_rfd(rfd
))
2089 rc
= rfapiRaddr2Qprefix(&rfd
->vn_addr
, &pfx_vn
);
2090 assert(!rc
); /* should never have bad AF in stored vn address */
2093 * update exported routes to reflect disappearance of this NVE as
2096 vnc_direct_bgp_del_nve(bgp
, rfd
);
2097 vnc_zebra_del_nve(bgp
, rfd
);
2100 * unlink this HD's monitors from import table
2102 rfapiMonitorDetachImportHd(rfd
);
2105 * Unlink from Import Table
2106 * NB rfd->import_table will be NULL if we are closing a stale
2109 if (rfd
->import_table
)
2110 rfapiImportTableRefDelByIt(bgp
, rfd
->import_table
);
2111 rfd
->import_table
= NULL
;
2114 * Construct route distinguisher
2116 memset(&prd
, 0, sizeof(prd
));
2118 prd
.family
= AF_UNSPEC
;
2124 del_vnc_route(rfd
, rfd
->peer
, bgp
, SAFI_ENCAP
,
2125 &pfx_vn
, /* prefix being advertised */
2126 &prd
, /* route distinguisher to use (0 for ENCAP) */
2127 ZEBRA_ROUTE_BGP
, BGP_ROUTE_RFP
, NULL
, 0); /* no kill */
2130 * Construct route distinguisher for VPN routes
2133 prd
.family
= AF_UNSPEC
;
2137 * find all VPN routes associated with this rfd and delete them, too
2139 rfapiApWithdrawAll(bgp
, rfd
);
2142 * remove this nve descriptor from the list of nves
2143 * associated with the nve group
2146 listnode_delete(rfd
->rfg
->nves
, rfd
);
2147 rfd
->rfg
= NULL
; /* XXX mark as orphaned/stale */
2150 if (rfd
->rt_export_list
)
2151 ecommunity_free(&rfd
->rt_export_list
);
2152 rfd
->rt_export_list
= NULL
;
2155 * free peer structure (possibly delayed until its
2156 * refcount reaches zero)
2159 vnc_zlog_debug_verbose("%s: calling peer_delete(%p), #%d",
2160 __func__
, rfd
->peer
, rfd
->peer
->lock
);
2161 peer_delete(rfd
->peer
);
2168 int rfapi_close(void *handle
)
2170 struct rfapi_descriptor
*rfd
= (struct rfapi_descriptor
*)handle
;
2172 struct route_node
*node
;
2176 vnc_zlog_debug_verbose("%s: rfd=%p", __func__
, rfd
);
2178 #if RFAPI_WHO_IS_CALLING_ME
2179 #ifdef HAVE_GLIBC_BACKTRACE
2180 #define RFAPI_DEBUG_BACKTRACE_NENTRIES 5
2182 void *buf
[RFAPI_DEBUG_BACKTRACE_NENTRIES
];
2187 size
= backtrace(buf
, RFAPI_DEBUG_BACKTRACE_NENTRIES
);
2188 syms
= backtrace_symbols(buf
, size
);
2189 for (i
= 0; i
< size
&& i
< RFAPI_DEBUG_BACKTRACE_NENTRIES
;
2191 vnc_zlog_debug_verbose("backtrace[%2d]: %s", i
,
2207 if (!is_valid_rfd(rfd
))
2210 if (h
->flags
& RFAPI_INCALLBACK
) {
2212 * Queue these close requests for processing after callback
2215 if (!CHECK_FLAG(rfd
->flags
,
2216 RFAPI_HD_FLAG_CLOSING_ADMINISTRATIVELY
)) {
2217 work_queue_add(h
->deferred_close_q
, handle
);
2218 vnc_zlog_debug_verbose(
2219 "%s: added handle %p to deferred close queue",
2225 if (CHECK_FLAG(rfd
->flags
, RFAPI_HD_FLAG_CLOSING_ADMINISTRATIVELY
)) {
2227 vnc_zlog_debug_verbose("%s administrative close rfd=%p",
2230 if (h
&& h
->rfp_methods
.close_cb
) {
2231 vnc_zlog_debug_verbose(
2232 "%s calling close callback rfd=%p", __func__
,
2236 * call the callback fairly early so that it can still
2240 * NB RFAPI_INCALLBACK is tested above, so if we reach
2242 * we are not already in the context of a callback.
2244 h
->flags
|= RFAPI_INCALLBACK
;
2245 (*h
->rfp_methods
.close_cb
)(handle
, EIDRM
);
2246 h
->flags
&= ~RFAPI_INCALLBACK
;
2252 * Orphaned descriptors have already done this part, so do
2253 * only for non-orphaned descriptors.
2255 if ((rc
= rfapi_close_inner(rfd
, bgp
)))
2260 * Remove descriptor from UN index
2261 * (remove from chain at node)
2263 rc
= rfapi_find_node(bgp
, &rfd
->vn_addr
, &rfd
->un_addr
, &node
);
2265 struct rfapi_descriptor
*hh
;
2267 if (node
->info
== rfd
) {
2268 node
->info
= rfd
->next
;
2271 for (hh
= node
->info
; hh
; hh
= hh
->next
) {
2272 if (hh
->next
== rfd
) {
2273 hh
->next
= rfd
->next
;
2278 route_unlock_node(node
);
2282 * remove from descriptor list
2284 listnode_delete(&h
->descriptors
, rfd
);
2287 * Delete monitor list items and free monitor structures
2289 (void)rfapiMonitorDelHd(rfd
);
2292 * release advertised prefix data
2294 rfapiApRelease(&rfd
->advertised
);
2297 * Release RFP callback RIB
2304 memset(rfd
, 0, sizeof(struct rfapi_descriptor
));
2305 XFREE(MTYPE_RFAPI_DESC
, rfd
);
2311 * Reopen a nve descriptor. If the descriptor's NVE-group
2312 * does not exist (e.g., if it has been administratively removed),
2313 * reassignment to a new NVE-group is attempted.
2315 * If NVE-group reassignment fails, the descriptor becomes "stale"
2316 * (rfd->rfg == NULL implies "stale:). The only permissible API operation
2317 * on a stale descriptor is rfapi_close(). Any other rfapi_* API operation
2318 * on the descriptor will return ESTALE.
2320 * Reopening a descriptor is a potentially expensive operation, because
2321 * it involves withdrawing any routes advertised by the NVE, withdrawing
2322 * the NVE's route queries, and then re-adding them all after a new
2323 * NVE-group is assigned. There are also possible route-export affects
2324 * caused by deleting and then adding the NVE: advertised prefixes
2325 * and nexthop lists for exported routes can turn over.
2327 int rfapi_reopen(struct rfapi_descriptor
*rfd
, struct bgp
*bgp
)
2332 if ((rc
= rfapi_close_inner(rfd
, bgp
))) {
2335 if ((rc
= rfapi_open_rfd(rfd
, bgp
))) {
2339 assert(h
!= NULL
&& !CHECK_FLAG(h
->flags
, RFAPI_INCALLBACK
));
2341 if (CHECK_FLAG(rfd
->flags
,
2342 RFAPI_HD_FLAG_CLOSING_ADMINISTRATIVELY
)
2343 && h
&& h
->rfp_methods
.close_cb
) {
2346 * NB RFAPI_INCALLBACK is tested above, so if we reach
2348 * we are not already in the context of a callback.
2350 h
->flags
|= RFAPI_INCALLBACK
;
2351 (*h
->rfp_methods
.close_cb
)((rfapi_handle
)rfd
, ESTALE
);
2352 h
->flags
&= ~RFAPI_INCALLBACK
;
2359 /***********************************************************************
2361 ***********************************************************************/
2363 * Announce reachability to this prefix via the NVE
2365 int rfapi_register(void *handle
, struct rfapi_ip_prefix
*prefix
,
2366 uint32_t lifetime
, /* host byte order */
2367 struct rfapi_un_option
*options_un
,
2368 struct rfapi_vn_option
*options_vn
,
2369 rfapi_register_action action
)
2371 struct rfapi_descriptor
*rfd
= (struct rfapi_descriptor
*)handle
;
2374 struct prefix
*pfx_ip
= NULL
;
2375 struct prefix_rd prd
;
2377 struct prefix pfx_mac_buf
;
2378 struct prefix
*pfx_mac
= NULL
;
2379 struct prefix pfx_vn_buf
;
2380 const char *action_str
= NULL
;
2381 uint32_t *label
= NULL
;
2382 struct rfapi_vn_option
*vo
;
2383 struct rfapi_l2address_option
*l2o
= NULL
;
2384 struct prefix_rd
*prd_override
= NULL
;
2387 case RFAPI_REGISTER_ADD
:
2390 case RFAPI_REGISTER_WITHDRAW
:
2391 action_str
= "withdraw";
2393 case RFAPI_REGISTER_KILL
:
2394 action_str
= "kill";
2402 * Inspect VN options
2404 for (vo
= options_vn
; vo
; vo
= vo
->next
) {
2405 if (RFAPI_VN_OPTION_TYPE_L2ADDR
== vo
->type
) {
2406 l2o
= &vo
->v
.l2addr
;
2408 if (RFAPI_VN_OPTION_TYPE_INTERNAL_RD
== vo
->type
) {
2409 prd_override
= &vo
->v
.internal_rd
;
2413 /*********************************************************************
2415 *********************************************************************/
2418 * set <p> based on <prefix>
2420 assert(!rfapiRprefix2Qprefix(prefix
, &p
));
2422 afi
= family2afi(prefix
->prefix
.addr_family
);
2427 char buf
[PREFIX_STRLEN
];
2429 prefix2str(&p
, buf
, sizeof(buf
));
2430 vnc_zlog_debug_verbose(
2431 "%s(rfd=%p, pfx=%s, lifetime=%d, opts_un=%p, opts_vn=%p, action=%s)",
2432 __func__
, rfd
, buf
, lifetime
, options_un
, options_vn
,
2437 * These tests come after the prefix conversion so that we can
2438 * print the prefix in a debug message before failing
2443 vnc_zlog_debug_verbose("%s: no BGP instance: returning ENXIO",
2448 vnc_zlog_debug_verbose("%s: no RFAPI instance: returning ENXIO",
2453 if (RFAPI_REGISTER_ADD
== action
) {
2454 ++bgp
->rfapi
->stat
.count_registrations_failed
;
2456 vnc_zlog_debug_verbose(
2457 "%s: rfd=%p, no RF GRP instance: returning ESTALE",
2462 if (bgp
->rfapi
->flags
& RFAPI_INCALLBACK
) {
2463 if (RFAPI_REGISTER_ADD
== action
) {
2464 ++bgp
->rfapi
->stat
.count_registrations_failed
;
2466 vnc_zlog_debug_verbose("%s: in callback: returning EDEADLK",
2471 if (!is_valid_rfd(rfd
)) {
2472 if (RFAPI_REGISTER_ADD
== action
) {
2473 ++bgp
->rfapi
->stat
.count_registrations_failed
;
2475 vnc_zlog_debug_verbose("%s: invalid handle: returning EBADF",
2481 * Is there a MAC address in this registration?
2483 if (l2o
&& !RFAPI_0_ETHERADDR(&l2o
->macaddr
)) {
2484 rfapiL2o2Qprefix(l2o
, &pfx_mac_buf
);
2485 pfx_mac
= &pfx_mac_buf
;
2489 * Is there an IP prefix in this registration?
2491 if (!(RFAPI_0_PREFIX(&p
) && RFAPI_HOST_PREFIX(&p
))) {
2495 vnc_zlog_debug_verbose(
2496 "%s: missing mac addr that is required for host 0 pfx",
2498 if (RFAPI_REGISTER_ADD
== action
) {
2499 ++bgp
->rfapi
->stat
.count_registrations_failed
;
2503 if (rfapiRaddr2Qprefix(&rfd
->vn_addr
, &pfx_vn_buf
)) {
2504 vnc_zlog_debug_verbose(
2505 "%s: handle has bad vn_addr: returning EBADF",
2507 if (RFAPI_REGISTER_ADD
== action
) {
2508 ++bgp
->rfapi
->stat
.count_registrations_failed
;
2514 if (RFAPI_REGISTER_ADD
== action
) {
2515 ++bgp
->rfapi
->stat
.count_registrations
;
2519 * Figure out if this registration is missing an IP address
2523 * In RFAPI, we use prefixes in family AF_LINK to store
2524 * the MAC addresses. These prefixes are used for the
2525 * list of advertised prefixes and in the RFAPI import
2528 * In BGP proper, we use the prefix matching the NVE's
2529 * VN address with a host prefix-length (i.e., 32 or 128).
2532 if (l2o
&& l2o
->logical_net_id
&& RFAPI_0_PREFIX(&p
)
2533 && RFAPI_HOST_PREFIX(&p
)) {
2535 rfapiL2o2Qprefix(l2o
, &pfx_mac_buf
);
2536 pfx_mac
= &pfx_mac_buf
;
2540 * Construct route distinguisher
2543 prd
= *prd_override
;
2545 memset(&prd
, 0, sizeof(prd
));
2547 prd
.family
= AF_UNSPEC
;
2549 encode_rd_type(RD_TYPE_VNC_ETH
, prd
.val
);
2550 if (l2o
->local_nve_id
2551 || !(rfd
->rfg
->flags
& RFAPI_RFG_L2RD
)) {
2553 * If Local NVE ID is specified in message, use
2555 * (if no local default configured, also use it
2558 prd
.val
[1] = l2o
->local_nve_id
;
2560 if (rfd
->rfg
->l2rd
) {
2562 * locally-configured literal value
2564 prd
.val
[1] = rfd
->rfg
->l2rd
;
2567 * 0 means auto:vn, which means use LSB
2570 if (rfd
->vn_addr
.addr_family
2573 *(((char *)&rfd
->vn_addr
2579 *(((char *)&rfd
->vn_addr
2586 memcpy(prd
.val
+ 2, pfx_mac
->u
.prefix_eth
.octet
, 6);
2589 prd
.family
= AF_UNSPEC
;
2595 if (action
== RFAPI_REGISTER_WITHDRAW
2596 || action
== RFAPI_REGISTER_KILL
) {
2601 * withdraw previous advertisement
2604 rfd
, rfd
->peer
, bgp
, SAFI_MPLS_VPN
,
2606 : &pfx_vn_buf
, /* prefix being advertised */
2607 &prd
, /* route distinguisher (0 for ENCAP) */
2608 ZEBRA_ROUTE_BGP
, BGP_ROUTE_RFP
, NULL
,
2609 action
== RFAPI_REGISTER_KILL
);
2611 if (0 == rfapiApDelete(bgp
, rfd
, &p
, pfx_mac
, &prd
,
2614 rfapiTunnelRouteAnnounce(
2615 bgp
, rfd
, &rfd
->max_prefix_lifetime
);
2621 uint32_t local_pref
;
2622 struct ecommunity
*rtlist
= NULL
;
2623 struct ecommunity_val ecom_value
;
2625 if (!rfapiApCount(rfd
)) {
2627 * make sure we advertise tunnel route upon adding the
2633 if (rfapiApAdd(bgp
, rfd
, &p
, pfx_mac
, &prd
, lifetime
,
2634 prefix
->cost
, l2o
)) {
2638 vnc_zlog_debug_verbose("%s: adv_tunnel = %d", __func__
,
2641 vnc_zlog_debug_verbose("%s: announcing tunnel route",
2643 rfapiTunnelRouteAnnounce(bgp
, rfd
,
2644 &rfd
->max_prefix_lifetime
);
2647 vnc_zlog_debug_verbose("%s: calling add_vnc_route", __func__
);
2649 local_pref
= rfp_cost_to_localpref(prefix
->cost
);
2651 if (l2o
&& l2o
->label
)
2652 label
= &l2o
->label
;
2655 struct ecommunity
*l2com
= NULL
;
2658 l2com
= bgp_rfapi_get_ecommunity_by_lni_label(
2659 bgp
, 1, l2o
->logical_net_id
, *label
);
2662 rtlist
= ecommunity_dup(l2com
);
2665 * If mac address is set, add an RT based on the
2668 memset((char *)&ecom_value
, 0,
2669 sizeof(ecom_value
));
2670 ecom_value
.val
[1] = ECOMMUNITY_ROUTE_TARGET
;
2672 (l2o
->logical_net_id
>> 16) & 0xff;
2674 (l2o
->logical_net_id
>> 8) & 0xff;
2676 (l2o
->logical_net_id
>> 0) & 0xff;
2677 rtlist
= ecommunity_new();
2678 ecommunity_add_val(rtlist
, &ecom_value
);
2682 uint16_t val
= l2o
->tag_id
;
2683 memset((char *)&ecom_value
, 0,
2684 sizeof(ecom_value
));
2685 ecom_value
.val
[1] = ECOMMUNITY_ROUTE_TARGET
;
2686 if (as
> BGP_AS_MAX
) {
2688 ECOMMUNITY_ENCODE_AS4
;
2689 ecom_value
.val
[2] = (as
>> 24) & 0xff;
2690 ecom_value
.val
[3] = (as
>> 16) & 0xff;
2691 ecom_value
.val
[4] = (as
>> 8) & 0xff;
2692 ecom_value
.val
[5] = as
& 0xff;
2695 ECOMMUNITY_ENCODE_AS
;
2696 ecom_value
.val
[2] = (as
>> 8) & 0xff;
2697 ecom_value
.val
[3] = as
& 0xff;
2699 ecom_value
.val
[6] = (val
>> 8) & 0xff;
2700 ecom_value
.val
[7] = val
& 0xff;
2702 rtlist
= ecommunity_new();
2703 ecommunity_add_val(rtlist
, &ecom_value
);
2708 * advertise prefix via tunnel endpoint
2711 rfd
, /* rfapi descr, for export list & backref */
2712 bgp
, /* which bgp instance */
2713 SAFI_MPLS_VPN
, /* which SAFI */
2715 : &pfx_vn_buf
), /* prefix being advertised */
2716 &prd
, /* route distinguisher to use (0 for ENCAP) */
2717 &rfd
->vn_addr
, /* nexthop */
2719 &lifetime
, /* prefix lifetime -> Tunnel Encap attr */
2720 NULL
, options_un
, /* rfapi un options */
2721 options_vn
, /* rfapi vn options */
2722 (rtlist
? rtlist
: rfd
->rt_export_list
), NULL
, /* med */
2723 label
, /* label: default */
2724 ZEBRA_ROUTE_BGP
, BGP_ROUTE_RFP
, 0);
2727 ecommunity_free(&rtlist
); /* sets rtlist = NULL */
2730 vnc_zlog_debug_verbose("%s: success", __func__
);
2734 int rfapi_query(void *handle
, struct rfapi_ip_addr
*target
,
2735 struct rfapi_l2address_option
*l2o
, /* may be NULL */
2736 struct rfapi_next_hop_entry
**ppNextHopEntry
)
2738 struct rfapi_descriptor
*rfd
= (struct rfapi_descriptor
*)handle
;
2739 struct bgp
*bgp
= rfd
->bgp
;
2742 assert(ppNextHopEntry
);
2743 *ppNextHopEntry
= NULL
;
2745 if (bgp
&& bgp
->rfapi
) {
2746 bgp
->rfapi
->stat
.count_queries
++;
2750 if (bgp
&& bgp
->rfapi
)
2751 ++bgp
->rfapi
->stat
.count_queries_failed
;
2755 if ((rc
= rfapi_query_inner(handle
, target
, l2o
, ppNextHopEntry
))) {
2756 if (bgp
&& bgp
->rfapi
)
2757 ++bgp
->rfapi
->stat
.count_queries_failed
;
2762 int rfapi_query_done(rfapi_handle handle
, struct rfapi_ip_addr
*target
)
2766 struct rfapi_descriptor
*rfd
= (struct rfapi_descriptor
*)handle
;
2767 struct bgp
*bgp
= rfd
->bgp
;
2773 rc
= rfapiRaddr2Qprefix(target
, &p
);
2776 if (!is_valid_rfd(rfd
))
2780 if (!bgp
|| !bgp
->rfapi
)
2783 if (bgp
->rfapi
->flags
& RFAPI_INCALLBACK
)
2786 rfapiMonitorDel(bgp
, rfd
, &p
);
2791 int rfapi_query_done_all(rfapi_handle handle
, int *count
)
2793 struct rfapi_descriptor
*rfd
= (struct rfapi_descriptor
*)handle
;
2794 struct bgp
*bgp
= rfd
->bgp
;
2801 if (!is_valid_rfd(rfd
))
2805 if (!bgp
|| !bgp
->rfapi
)
2808 if (bgp
->rfapi
->flags
& RFAPI_INCALLBACK
)
2811 num
= rfapiMonitorDelHd(rfd
);
2819 void rfapi_free_next_hop_list(struct rfapi_next_hop_entry
*list
)
2821 struct rfapi_next_hop_entry
*nh
;
2822 struct rfapi_next_hop_entry
*next
;
2824 for (nh
= list
; nh
; nh
= next
) {
2826 rfapi_un_options_free(nh
->un_options
);
2827 nh
->un_options
= NULL
;
2828 rfapi_vn_options_free(nh
->vn_options
);
2829 nh
->vn_options
= NULL
;
2830 XFREE(MTYPE_RFAPI_NEXTHOP
, nh
);
2835 * NULL handle => return total count across all nves
2837 uint32_t rfapi_monitor_count(void *handle
)
2839 struct bgp
*bgp
= bgp_get_default();
2843 struct rfapi_descriptor
*rfd
=
2844 (struct rfapi_descriptor
*)handle
;
2845 count
= rfd
->monitor_count
;
2848 if (!bgp
|| !bgp
->rfapi
)
2851 count
= bgp
->rfapi
->monitor_count
;
2857 /***********************************************************************
2859 ***********************************************************************/
2861 DEFUN (debug_rfapi_show_nves
,
2862 debug_rfapi_show_nves_cmd
,
2863 "debug rfapi-dev show nves",
2867 "NVE Information\n")
2869 rfapiPrintMatchingDescriptors(vty
, NULL
, NULL
);
2874 debug_rfapi_show_nves_vn_un
,
2875 debug_rfapi_show_nves_vn_un_cmd
,
2876 "debug rfapi-dev show nves <vn|un> <A.B.C.D|X:X::X:X>", /* prefix also ok */
2881 "Specify virtual network\n"
2882 "Specify underlay network interface\n"
2888 if (!str2prefix(argv
[5]->arg
, &pfx
)) {
2889 vty_out(vty
, "Malformed address \"%s\"\n", argv
[5]->arg
);
2890 return CMD_WARNING_CONFIG_FAILED
;
2892 if (pfx
.family
!= AF_INET
&& pfx
.family
!= AF_INET6
) {
2893 vty_out(vty
, "Invalid address \"%s\"\n", argv
[5]->arg
);
2894 return CMD_WARNING_CONFIG_FAILED
;
2897 if (argv
[4]->arg
[0] == 'u') {
2898 rfapiPrintMatchingDescriptors(vty
, NULL
, &pfx
);
2900 rfapiPrintMatchingDescriptors(vty
, &pfx
, NULL
);
2906 * Note: this function does not flush vty output, so if it is called
2907 * with a stream pointing to a vty, the user will have to type something
2908 * before the callback output shows up
2910 static void test_nexthops_callback(
2911 // struct rfapi_ip_addr *target,
2912 struct rfapi_next_hop_entry
*next_hops
, void *userdata
)
2914 void *stream
= userdata
;
2916 int (*fp
)(void *, const char *, ...);
2919 const char *vty_newline
;
2921 if (rfapiStream2Vty(stream
, &fp
, &vty
, &out
, &vty_newline
) == 0)
2924 fp(out
, "Nexthops Callback, Target=(");
2925 // rfapiPrintRfapiIpAddr(stream, target);
2928 rfapiPrintNhl(stream
, next_hops
);
2930 rfapi_free_next_hop_list(next_hops
);
2933 DEFUN (debug_rfapi_open
,
2934 debug_rfapi_open_cmd
,
2935 "debug rfapi-dev open vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X>",
2939 "indicate vn addr follows\n"
2940 "virtual network interface IPv4 address\n"
2941 "virtual network interface IPv6 address\n"
2942 "indicate xt addr follows\n"
2943 "underlay network interface IPv4 address\n"
2944 "underlay network interface IPv6 address\n")
2946 struct rfapi_ip_addr vn
;
2947 struct rfapi_ip_addr un
;
2950 rfapi_handle handle
;
2955 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[4]->arg
, &vn
)))
2961 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[6]->arg
, &un
)))
2964 rc
= rfapi_open(rfapi_get_rfp_start_val_by_bgp(bgp_get_default()), &vn
,
2965 &un
, /*&uo */ NULL
, &lifetime
, NULL
, &handle
);
2967 vty_out(vty
, "rfapi_open: status %d, handle %p, lifetime %d\n", rc
,
2970 rc
= rfapi_set_response_cb(handle
, test_nexthops_callback
);
2972 vty_out(vty
, "rfapi_set_response_cb: status %d\n", rc
);
2978 DEFUN (debug_rfapi_close_vn_un
,
2979 debug_rfapi_close_vn_un_cmd
,
2980 "debug rfapi-dev close vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X>",
2984 "indicate vn addr follows\n"
2985 "virtual network interface IPv4 address\n"
2986 "virtual network interface IPv6 address\n"
2987 "indicate xt addr follows\n"
2988 "underlay network interface IPv4 address\n"
2989 "underlay network interface IPv6 address\n")
2991 struct rfapi_ip_addr vn
;
2992 struct rfapi_ip_addr un
;
2993 rfapi_handle handle
;
2999 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[4]->arg
, &vn
)))
3006 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[6]->arg
, &un
)))
3010 if (rfapi_find_handle_vty(vty
, &vn
, &un
, &handle
)) {
3011 vty_out(vty
, "can't locate handle matching vn=%s, un=%s\n",
3012 argv
[4]->arg
, argv
[6]->arg
);
3013 return CMD_WARNING_CONFIG_FAILED
;
3016 rc
= rfapi_close(handle
);
3018 vty_out(vty
, "rfapi_close(handle=%p): status %d\n", handle
, rc
);
3023 DEFUN (debug_rfapi_close_rfd
,
3024 debug_rfapi_close_rfd_cmd
,
3025 "debug rfapi-dev close rfd HANDLE",
3029 "indicate handle follows\n" "rfapi handle in hexadecimal\n")
3031 rfapi_handle handle
;
3033 char *endptr
= NULL
;
3035 handle
= (rfapi_handle
)(uintptr_t)(strtoull(argv
[4]->arg
, &endptr
, 16));
3037 if (*endptr
!= '\0' || (uintptr_t)handle
== UINTPTR_MAX
) {
3038 vty_out(vty
, "Invalid value: %s\n", argv
[4]->arg
);
3039 return CMD_WARNING_CONFIG_FAILED
;
3042 rc
= rfapi_close(handle
);
3044 vty_out(vty
, "rfapi_close(handle=%p): status %d\n", handle
, rc
);
3049 DEFUN (debug_rfapi_register_vn_un
,
3050 debug_rfapi_register_vn_un_cmd
,
3051 "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",
3055 "indicate vn addr follows\n"
3056 "virtual network IPv4 interface address\n"
3057 "virtual network IPv6 interface address\n"
3058 "indicate un addr follows\n"
3059 "underlay network IPv4 interface address\n"
3060 "underlay network IPv6 interface address\n"
3061 "indicate prefix follows\n"
3064 "indicate lifetime follows\n"
3067 struct rfapi_ip_addr vn
;
3068 struct rfapi_ip_addr un
;
3069 rfapi_handle handle
;
3072 struct rfapi_ip_prefix hpfx
;
3078 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[4]->arg
, &vn
)))
3085 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[6]->arg
, &un
)))
3089 if (rfapi_find_handle_vty(vty
, &vn
, &un
, &handle
)) {
3090 vty_out(vty
, "can't locate handle matching vn=%s, un=%s\n",
3091 argv
[4]->arg
, argv
[6]->arg
);
3092 return CMD_WARNING_CONFIG_FAILED
;
3096 * Get prefix to advertise
3098 if (!str2prefix(argv
[8]->arg
, &pfx
)) {
3099 vty_out(vty
, "Malformed prefix \"%s\"\n", argv
[8]->arg
);
3100 return CMD_WARNING_CONFIG_FAILED
;
3102 if (pfx
.family
!= AF_INET
&& pfx
.family
!= AF_INET6
) {
3103 vty_out(vty
, "Bad family for prefix \"%s\"\n", argv
[8]->arg
);
3104 return CMD_WARNING_CONFIG_FAILED
;
3106 rfapiQprefix2Rprefix(&pfx
, &hpfx
);
3108 if (strmatch(argv
[10]->text
, "infinite")) {
3109 lifetime
= RFAPI_INFINITE_LIFETIME
;
3111 lifetime
= strtoul(argv
[10]->arg
, NULL
, 10);
3115 rc
= rfapi_register(handle
, &hpfx
, lifetime
, NULL
, NULL
, 0);
3117 vty_out(vty
, "rfapi_register failed with rc=%d (%s)\n", rc
,
3124 DEFUN (debug_rfapi_register_vn_un_l2o
,
3125 debug_rfapi_register_vn_un_l2o_cmd
,
3126 "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)",
3130 "indicate vn addr follows\n"
3131 "virtual network IPv4 interface address\n"
3132 "virtual network IPv6 interface address\n"
3133 "indicate un addr follows\n"
3134 "underlay network IPv4 interface address\n"
3135 "underlay network IPv6 interface address\n"
3136 "indicate prefix follows\n"
3139 "indicate lifetime follows\n"
3140 "Seconds of lifetime\n"
3141 "indicate MAC address follows\n"
3143 "indicate lni follows\n"
3144 "lni value range\n")
3146 struct rfapi_ip_addr vn
;
3147 struct rfapi_ip_addr un
;
3148 rfapi_handle handle
;
3151 struct rfapi_ip_prefix hpfx
;
3153 struct rfapi_vn_option optary
[10]; /* XXX must be big enough */
3154 struct rfapi_vn_option
*opt
= NULL
;
3160 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[4]->arg
, &vn
)))
3167 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[6]->arg
, &un
)))
3171 if (rfapi_find_handle_vty(vty
, &vn
, &un
, &handle
)) {
3172 vty_out(vty
, "can't locate handle matching vn=%s, un=%s\n",
3173 argv
[4]->arg
, argv
[6]->arg
);
3174 return CMD_WARNING_CONFIG_FAILED
;
3178 * Get prefix to advertise
3180 if (!str2prefix(argv
[8]->arg
, &pfx
)) {
3181 vty_out(vty
, "Malformed prefix \"%s\"\n", argv
[8]->arg
);
3182 return CMD_WARNING_CONFIG_FAILED
;
3184 if (pfx
.family
!= AF_INET
&& pfx
.family
!= AF_INET6
) {
3185 vty_out(vty
, "Bad family for prefix \"%s\"\n", argv
[8]->arg
);
3186 return CMD_WARNING_CONFIG_FAILED
;
3188 rfapiQprefix2Rprefix(&pfx
, &hpfx
);
3190 if (strmatch(argv
[10]->text
, "infinite")) {
3191 lifetime
= RFAPI_INFINITE_LIFETIME
;
3193 lifetime
= strtoul(argv
[10]->arg
, NULL
, 10);
3196 /* L2 option parsing START */
3197 memset(optary
, 0, sizeof(optary
));
3198 optary
[opt_next
].v
.l2addr
.logical_net_id
=
3199 strtoul(argv
[14]->arg
, NULL
, 10);
3200 if ((rc
= rfapiStr2EthAddr(argv
[12]->arg
,
3201 &optary
[opt_next
].v
.l2addr
.macaddr
))) {
3202 vty_out(vty
, "Bad mac address \"%s\"\n", argv
[12]->arg
);
3203 return CMD_WARNING_CONFIG_FAILED
;
3205 optary
[opt_next
].type
= RFAPI_VN_OPTION_TYPE_L2ADDR
;
3207 optary
[opt_next
- 1].next
= optary
+ opt_next
;
3212 /* L2 option parsing END */
3215 rc
= rfapi_register(handle
, &hpfx
, lifetime
, NULL
/* &uo */, opt
, 0);
3217 vty_out(vty
, "rfapi_register failed with rc=%d (%s)\n", rc
,
3225 DEFUN (debug_rfapi_unregister_vn_un
,
3226 debug_rfapi_unregister_vn_un_cmd
,
3227 "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>",
3231 "indicate vn addr follows\n"
3232 "virtual network interface address\n"
3233 "indicate xt addr follows\n"
3234 "underlay network interface address\n"
3235 "indicate prefix follows\n" "prefix")
3237 struct rfapi_ip_addr vn
;
3238 struct rfapi_ip_addr un
;
3239 rfapi_handle handle
;
3241 struct rfapi_ip_prefix hpfx
;
3247 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[4]->arg
, &vn
)))
3254 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[6]->arg
, &un
)))
3258 if (rfapi_find_handle_vty(vty
, &vn
, &un
, &handle
)) {
3259 vty_out(vty
, "can't locate handle matching vn=%s, un=%s\n",
3260 argv
[4]->arg
, argv
[6]->arg
);
3261 return CMD_WARNING_CONFIG_FAILED
;
3265 * Get prefix to advertise
3267 if (!str2prefix(argv
[8]->arg
, &pfx
)) {
3268 vty_out(vty
, "Malformed prefix \"%s\"\n", argv
[8]->arg
);
3269 return CMD_WARNING_CONFIG_FAILED
;
3271 if (pfx
.family
!= AF_INET
&& pfx
.family
!= AF_INET6
) {
3272 vty_out(vty
, "Bad family for prefix \"%s\"\n", argv
[8]->arg
);
3273 return CMD_WARNING_CONFIG_FAILED
;
3275 rfapiQprefix2Rprefix(&pfx
, &hpfx
);
3277 rfapi_register(handle
, &hpfx
, 0, NULL
, NULL
, 1);
3282 DEFUN (debug_rfapi_query_vn_un
,
3283 debug_rfapi_query_vn_un_cmd
,
3284 "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>",
3288 "indicate vn addr follows\n"
3289 "virtual network interface IPv4 address\n"
3290 "virtual network interface IPv6 address\n"
3291 "indicate un addr follows\n"
3294 "indicate target follows\n"
3295 "target IPv4 address\n"
3296 "target IPv6 address\n")
3298 struct rfapi_ip_addr vn
;
3299 struct rfapi_ip_addr un
;
3300 struct rfapi_ip_addr target
;
3301 rfapi_handle handle
;
3303 struct rfapi_next_hop_entry
*pNextHopEntry
;
3308 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[4]->arg
, &vn
)))
3315 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[6]->arg
, &un
)))
3322 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[8]->arg
, &target
)))
3326 if (rfapi_find_handle_vty(vty
, &vn
, &un
, &handle
)) {
3327 vty_out(vty
, "can't locate handle matching vn=%s, un=%s\n",
3328 argv
[4]->arg
, argv
[6]->arg
);
3329 return CMD_WARNING_CONFIG_FAILED
;
3333 * options parameter not used? Set to NULL for now
3335 rc
= rfapi_query(handle
, &target
, NULL
, &pNextHopEntry
);
3338 vty_out(vty
, "rfapi_query failed with rc=%d (%s)\n", rc
,
3342 * print nexthop list
3344 test_nexthops_callback(/*&target, */ pNextHopEntry
,
3345 vty
); /* frees nh list! */
3352 DEFUN (debug_rfapi_query_vn_un_l2o
,
3353 debug_rfapi_query_vn_un_l2o_cmd
,
3354 "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",
3358 "indicate vn addr follows\n"
3359 "virtual network interface IPv4 address\n"
3360 "virtual network interface IPv6 address\n"
3361 "indicate xt addr follows\n"
3362 "underlay network interface IPv4 address\n"
3363 "underlay network interface IPv6 address\n"
3364 "logical network ID follows\n"
3365 "logical network ID\n"
3366 "indicate target MAC addr follows\n"
3367 "target MAC addr\n")
3369 struct rfapi_ip_addr vn
;
3370 struct rfapi_ip_addr un
;
3376 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[4]->arg
, &vn
)))
3383 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[6]->arg
, &un
)))
3386 vty_out(vty
, "%% This command is broken.\n");
3387 return CMD_WARNING_CONFIG_FAILED
;
3391 DEFUN (debug_rfapi_query_done_vn_un
,
3392 debug_rfapi_query_vn_un_done_cmd
,
3393 "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>",
3396 "rfapi_query_done\n"
3397 "rfapi_query_done\n"
3398 "indicate vn addr follows\n"
3399 "virtual network interface IPv4 address\n"
3400 "virtual network interface IPv6 address\n"
3401 "indicate xt addr follows\n"
3402 "underlay network interface IPv4 address\n"
3403 "underlay network interface IPv6 address\n"
3404 "indicate target follows\n"
3405 "Target IPv4 address\n"
3406 "Target IPv6 address\n")
3408 struct rfapi_ip_addr vn
;
3409 struct rfapi_ip_addr un
;
3410 struct rfapi_ip_addr target
;
3411 rfapi_handle handle
;
3417 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[5]->arg
, &vn
)))
3424 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[7]->arg
, &un
)))
3431 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[9]->arg
, &target
)))
3435 if (rfapi_find_handle_vty(vty
, &vn
, &un
, &handle
)) {
3436 vty_out(vty
, "can't locate handle matching vn=%s, un=%s\n",
3437 argv
[5]->arg
, argv
[7]->arg
);
3438 return CMD_WARNING_CONFIG_FAILED
;
3442 * options parameter not used? Set to NULL for now
3444 rc
= rfapi_query_done(handle
, &target
);
3446 vty_out(vty
, "rfapi_query_done returned %d\n", rc
);
3451 DEFUN (debug_rfapi_show_import
,
3452 debug_rfapi_show_import_cmd
,
3453 "debug rfapi-dev show import",
3461 struct rfapi_import_table
*it
;
3466 * Show all import tables
3469 bgp
= bgp_get_default(); /* assume 1 instance for now */
3471 vty_out(vty
, "No BGP instance\n");
3472 return CMD_WARNING_CONFIG_FAILED
;
3477 vty_out(vty
, "No RFAPI instance\n");
3478 return CMD_WARNING_CONFIG_FAILED
;
3482 * Iterate over all import tables; do a filtered import
3483 * for the afi/safi combination
3487 for (it
= h
->imports
; it
; it
= it
->next
) {
3488 s
= ecommunity_ecom2str(it
->rt_import_list
,
3489 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3490 vty_out(vty
, "Import Table %p, RTs: %s\n", it
, s
);
3491 XFREE(MTYPE_ECOMMUNITY_STR
, s
);
3493 rfapiShowImportTable(vty
, "IP VPN", it
->imported_vpn
[AFI_IP
],
3495 rfapiShowImportTable(vty
, "IP ENCAP",
3496 it
->imported_encap
[AFI_IP
], 0);
3497 rfapiShowImportTable(vty
, "IP6 VPN", it
->imported_vpn
[AFI_IP6
],
3499 rfapiShowImportTable(vty
, "IP6 ENCAP",
3500 it
->imported_encap
[AFI_IP6
], 0);
3503 if (h
->import_mac
) {
3504 void *cursor
= NULL
;
3506 uintptr_t lni_as_ptr
;
3510 for (rc
= skiplist_next(h
->import_mac
, (void **)&lni_as_ptr
,
3511 (void **)&it
, &cursor
);
3513 rc
= skiplist_next(h
->import_mac
, (void **)&lni_as_ptr
,
3514 (void **)&it
, &cursor
)) {
3516 if (it
->imported_vpn
[AFI_L2VPN
]) {
3520 "\nLNI-based Ethernet Tables:\n");
3523 snprintf(buf
, BUFSIZ
, "L2VPN LNI=%u", lni
);
3524 rfapiShowImportTable(
3525 vty
, buf
, it
->imported_vpn
[AFI_L2VPN
],
3531 rfapiShowImportTable(vty
, "CE IT - IP VPN",
3532 h
->it_ce
->imported_vpn
[AFI_IP
], 1);
3537 DEFUN (debug_rfapi_show_import_vn_un
,
3538 debug_rfapi_show_import_vn_un_cmd
,
3539 "debug rfapi-dev show import vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X>",
3544 "indicate vn addr follows\n"
3545 "virtual network interface IPv4 address\n"
3546 "virtual network interface IPv6 address\n"
3547 "indicate xt addr follows\n"
3548 "underlay network interface IPv4 address\n"
3549 "underlay network interface IPv6 address\n")
3551 struct rfapi_ip_addr vn
;
3552 struct rfapi_ip_addr un
;
3553 rfapi_handle handle
;
3555 struct rfapi_descriptor
*rfd
;
3560 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[5]->arg
, &vn
)))
3567 if ((rc
= rfapiCliGetRfapiIpAddr(vty
, argv
[7]->arg
, &un
)))
3571 if (rfapi_find_handle_vty(vty
, &vn
, &un
, &handle
)) {
3572 vty_out(vty
, "can't locate handle matching vn=%s, un=%s\n",
3573 argv
[5]->arg
, argv
[7]->arg
);
3574 return CMD_WARNING_CONFIG_FAILED
;
3577 rfd
= (struct rfapi_descriptor
*)handle
;
3579 rfapiShowImportTable(vty
, "IP VPN",
3580 rfd
->import_table
->imported_vpn
[AFI_IP
], 1);
3581 rfapiShowImportTable(vty
, "IP ENCAP",
3582 rfd
->import_table
->imported_encap
[AFI_IP
], 0);
3583 rfapiShowImportTable(vty
, "IP6 VPN",
3584 rfd
->import_table
->imported_vpn
[AFI_IP6
], 1);
3585 rfapiShowImportTable(vty
, "IP6 ENCAP",
3586 rfd
->import_table
->imported_encap
[AFI_IP6
], 0);
3591 DEFUN (debug_rfapi_response_omit_self
,
3592 debug_rfapi_response_omit_self_cmd
,
3593 "debug rfapi-dev response-omit-self <on|off>",
3596 "Omit self in RFP responses\n"
3597 "filter out self from responses\n" "leave self in responses\n")
3599 struct bgp
*bgp
= bgp_get_default();
3602 vty_out(vty
, "No BGP process is configured\n");
3603 return CMD_WARNING_CONFIG_FAILED
;
3605 if (!bgp
->rfapi_cfg
) {
3606 vty_out(vty
, "VNC not configured\n");
3607 return CMD_WARNING_CONFIG_FAILED
;
3610 if (strmatch(argv
[3]->text
, "on"))
3611 SET_FLAG(bgp
->rfapi_cfg
->flags
,
3612 BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP
);
3614 UNSET_FLAG(bgp
->rfapi_cfg
->flags
,
3615 BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP
);
3621 #ifdef RFAPI_DEBUG_SKIPLIST_CLI
3623 #include "lib/skiplist.h"
3624 DEFUN (skiplist_test_cli
,
3625 skiplist_test_cli_cmd
,
3627 "skiplist command\n"
3635 DEFUN (skiplist_debug_cli
,
3636 skiplist_debug_cli_cmd
,
3638 "skiplist command\n"
3641 skiplist_debug(vty
, NULL
);
3645 #endif /* RFAPI_DEBUG_SKIPLIST_CLI */
3647 void rfapi_init(void)
3649 bgp_rfapi_cfg_init();
3652 install_element(ENABLE_NODE
, &debug_rfapi_show_import_cmd
);
3653 install_element(ENABLE_NODE
, &debug_rfapi_show_import_vn_un_cmd
);
3655 install_element(ENABLE_NODE
, &debug_rfapi_open_cmd
);
3656 install_element(ENABLE_NODE
, &debug_rfapi_close_vn_un_cmd
);
3657 install_element(ENABLE_NODE
, &debug_rfapi_close_rfd_cmd
);
3658 install_element(ENABLE_NODE
, &debug_rfapi_register_vn_un_cmd
);
3659 install_element(ENABLE_NODE
, &debug_rfapi_unregister_vn_un_cmd
);
3660 install_element(ENABLE_NODE
, &debug_rfapi_query_vn_un_cmd
);
3661 install_element(ENABLE_NODE
, &debug_rfapi_query_vn_un_done_cmd
);
3662 install_element(ENABLE_NODE
, &debug_rfapi_query_vn_un_l2o_cmd
);
3664 install_element(ENABLE_NODE
, &debug_rfapi_response_omit_self_cmd
);
3666 /* Need the following show commands for gpz test scripts */
3667 install_element(ENABLE_NODE
, &debug_rfapi_show_nves_cmd
);
3668 install_element(ENABLE_NODE
, &debug_rfapi_show_nves_vn_un_cmd
);
3669 install_element(ENABLE_NODE
, &debug_rfapi_register_vn_un_l2o_cmd
);
3671 #ifdef RFAPI_DEBUG_SKIPLIST_CLI
3672 install_element(ENABLE_NODE
, &skiplist_test_cli_cmd
);
3673 install_element(ENABLE_NODE
, &skiplist_debug_cli_cmd
);
3680 static void rfapi_print_exported(struct bgp
*bgp
)
3682 struct bgp_node
*rdn
;
3683 struct bgp_node
*rn
;
3684 struct bgp_info
*bi
;
3689 for (rdn
= bgp_table_top(bgp
->rib
[AFI_IP
][SAFI_MPLS_VPN
]); rdn
;
3690 rdn
= bgp_route_next(rdn
)) {
3693 fprintf(stderr
, "%s: vpn rdn=%p\n", __func__
, rdn
);
3694 for (rn
= bgp_table_top(rdn
->info
); rn
;
3695 rn
= bgp_route_next(rn
)) {
3698 fprintf(stderr
, "%s: rn=%p\n", __func__
, rn
);
3699 for (bi
= rn
->info
; bi
; bi
= bi
->next
) {
3700 rfapiPrintBi((void *)2, bi
); /* 2 => stderr */
3704 for (rdn
= bgp_table_top(bgp
->rib
[AFI_IP
][SAFI_ENCAP
]); rdn
;
3705 rdn
= bgp_route_next(rdn
)) {
3708 fprintf(stderr
, "%s: encap rdn=%p\n", __func__
, rdn
);
3709 for (rn
= bgp_table_top(rdn
->info
); rn
;
3710 rn
= bgp_route_next(rn
)) {
3713 fprintf(stderr
, "%s: rn=%p\n", __func__
, rn
);
3714 for (bi
= rn
->info
; bi
; bi
= bi
->next
) {
3715 rfapiPrintBi((void *)2, bi
); /* 2 => stderr */
3720 #endif /* defined(DEBUG_RFAPI) */
3723 * Free all memory to prepare for clean exit as seen by valgrind memcheck
3725 void rfapi_delete(struct bgp
*bgp
)
3727 extern void rfp_clear_vnc_nve_all(void); /* can't fix correctly yet */
3730 * This clears queries and registered routes, and closes nves
3733 rfp_clear_vnc_nve_all();
3734 bgp_rfapi_cfg_destroy(bgp
, bgp
->rfapi_cfg
);
3735 bgp
->rfapi_cfg
= NULL
;
3736 bgp_rfapi_destroy(bgp
, bgp
->rfapi
);
3740 * show what's left in the BGP MPLSVPN RIB
3742 rfapi_print_exported(bgp
);
3746 int rfapi_set_autord_from_vn(struct prefix_rd
*rd
, struct rfapi_ip_addr
*vn
)
3748 vnc_zlog_debug_verbose("%s: auto-assigning RD", __func__
);
3749 if (vn
->addr_family
!= AF_INET
&& vn
->addr_family
!= AF_INET6
) {
3750 vnc_zlog_debug_verbose(
3751 "%s: can't auto-assign RD, VN addr family is not IPv4"
3754 return EAFNOSUPPORT
;
3756 rd
->family
= AF_UNSPEC
;
3758 rd
->val
[1] = RD_TYPE_IP
;
3759 if (vn
->addr_family
== AF_INET
) {
3760 memcpy(rd
->val
+ 2, &vn
->addr
.v4
.s_addr
, 4);
3761 } else { /* is v6 */
3762 memcpy(rd
->val
+ 2, &vn
->addr
.v6
.s6_addr32
[3],
3763 4); /* low order 4 bytes */
3766 char buf
[RD_ADDRSTRLEN
];
3768 vnc_zlog_debug_verbose("%s: auto-RD is set to %s", __func__
,
3769 prefix_rd2str(rd
, buf
, sizeof(buf
)));
3774 /*------------------------------------------
3775 * rfapi_bgp_lookup_by_rfp
3777 * Find bgp instance pointer based on value returned by rfp_start
3780 * rfp_start_val value returned by rfp_startor
3781 * NULL (=get default instance)
3787 * bgp bgp instance pointer
3790 --------------------------------------------*/
3791 struct bgp
*rfapi_bgp_lookup_by_rfp(void *rfp_start_val
)
3793 struct bgp
*bgp
= NULL
;
3794 struct listnode
*node
, *nnode
;
3796 if (rfp_start_val
== NULL
)
3797 bgp
= bgp_get_default();
3799 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
3800 if (bgp
->rfapi
!= NULL
3801 && bgp
->rfapi
->rfp
== rfp_start_val
)
3806 /*------------------------------------------
3807 * rfapi_get_rfp_start_val_by_bgp
3809 * Find bgp instance pointer based on value returned by rfp_start
3812 * bgp bgp instance pointer
3821 --------------------------------------------*/
3822 void *rfapi_get_rfp_start_val_by_bgp(struct bgp
*bgp
)
3824 if (!bgp
|| !bgp
->rfapi
)
3826 return bgp
->rfapi
->rfp
;
3829 /***********************************************************************
3830 * RFP group specific configuration
3831 ***********************************************************************/
3832 static void *rfapi_rfp_get_or_init_group_config_default(struct rfapi_cfg
*rfc
,
3836 if (rfc
->default_rfp_cfg
== NULL
&& size
> 0) {
3837 rfc
->default_rfp_cfg
= XCALLOC(MTYPE_RFAPI_RFP_GROUP_CFG
, size
);
3838 vnc_zlog_debug_verbose("%s: allocated, size=%d", __func__
,
3841 return rfc
->default_rfp_cfg
;
3844 static void *rfapi_rfp_get_or_init_group_config_nve(struct rfapi_cfg
*rfc
,
3848 struct rfapi_nve_group_cfg
*rfg
=
3849 VTY_GET_CONTEXT_SUB(rfapi_nve_group_cfg
);
3851 /* make sure group is still in list */
3852 if (!rfg
|| !listnode_lookup(rfc
->nve_groups_sequential
, rfg
)) {
3853 /* Not in list anymore */
3854 vty_out(vty
, "Current NVE group no longer exists\n");
3858 if (rfg
->rfp_cfg
== NULL
&& size
> 0) {
3859 rfg
->rfp_cfg
= XCALLOC(MTYPE_RFAPI_RFP_GROUP_CFG
, size
);
3860 vnc_zlog_debug_verbose("%s: allocated, size=%d", __func__
,
3863 return rfg
->rfp_cfg
;
3866 static void *rfapi_rfp_get_or_init_group_config_l2(struct rfapi_cfg
*rfc
,
3870 struct rfapi_l2_group_cfg
*rfg
=
3871 VTY_GET_CONTEXT_SUB(rfapi_l2_group_cfg
);
3873 /* make sure group is still in list */
3874 if (!rfg
|| !listnode_lookup(rfc
->l2_groups
, rfg
)) {
3875 /* Not in list anymore */
3876 vty_out(vty
, "Current L2 group no longer exists\n");
3879 if (rfg
->rfp_cfg
== NULL
&& size
> 0) {
3880 rfg
->rfp_cfg
= XCALLOC(MTYPE_RFAPI_RFP_GROUP_CFG
, size
);
3881 vnc_zlog_debug_verbose("%s: allocated, size=%d", __func__
,
3884 return rfg
->rfp_cfg
;
3887 /*------------------------------------------
3888 * rfapi_rfp_init_group_config_ptr_vty
3890 * This is used to init or return a previously init'ed group specific
3891 * configuration pointer. Group is identified by vty context.
3892 * NOTE: size is ignored when a previously init'ed value is returned.
3893 * RFAPI frees rfp_cfg_group when group is deleted during reconfig,
3894 * bgp restart or shutdown.
3897 * rfp_start_val value returned by rfp_start
3899 * vty quagga vty context
3900 * size number of bytes to allocation
3906 * rfp_cfg_group NULL or Pointer to configuration structure
3907 --------------------------------------------*/
3908 void *rfapi_rfp_init_group_config_ptr_vty(void *rfp_start_val
,
3909 rfapi_rfp_cfg_group_type type
,
3910 struct vty
*vty
, uint32_t size
)
3915 if (rfp_start_val
== NULL
|| vty
== NULL
)
3918 bgp
= rfapi_bgp_lookup_by_rfp(rfp_start_val
);
3919 if (!bgp
|| !bgp
->rfapi_cfg
)
3923 case RFAPI_RFP_CFG_GROUP_DEFAULT
:
3924 ret
= rfapi_rfp_get_or_init_group_config_default(bgp
->rfapi_cfg
,
3927 case RFAPI_RFP_CFG_GROUP_NVE
:
3928 ret
= rfapi_rfp_get_or_init_group_config_nve(bgp
->rfapi_cfg
,
3931 case RFAPI_RFP_CFG_GROUP_L2
:
3932 ret
= rfapi_rfp_get_or_init_group_config_l2(bgp
->rfapi_cfg
, vty
,
3936 zlog_err("%s: Unknown group type=%d", __func__
, type
);
3937 /* should never happen */
3938 assert("Unknown type" == NULL
);
3944 /*------------------------------------------
3945 * rfapi_rfp_get_group_config_ptr_vty
3947 * This is used to get group specific configuration pointer.
3948 * Group is identified by type and vty context.
3949 * RFAPI frees rfp_cfg_group when group is deleted during reconfig,
3950 * bgp restart or shutdown.
3953 * rfp_start_val value returned by rfp_start
3955 * vty quagga vty context
3961 * rfp_cfg_group Pointer to configuration structure
3962 --------------------------------------------*/
3963 void *rfapi_rfp_get_group_config_ptr_vty(void *rfp_start_val
,
3964 rfapi_rfp_cfg_group_type type
,
3967 return rfapi_rfp_init_group_config_ptr_vty(rfp_start_val
, type
, vty
, 0);
3971 rfapi_rfp_get_group_config_name_nve(struct rfapi_cfg
*rfc
, const char *name
,
3973 rfp_group_config_search_cb_t
*search_cb
)
3975 struct rfapi_nve_group_cfg
*rfg
;
3976 struct listnode
*node
;
3978 for (ALL_LIST_ELEMENTS_RO(rfc
->nve_groups_sequential
, node
, rfg
)) {
3979 if (!strcmp(rfg
->name
, name
) && /* name match */
3980 (search_cb
== NULL
|| !search_cb(criteria
, rfg
->rfp_cfg
)))
3981 return rfg
->rfp_cfg
;
3987 rfapi_rfp_get_group_config_name_l2(struct rfapi_cfg
*rfc
, const char *name
,
3989 rfp_group_config_search_cb_t
*search_cb
)
3991 struct rfapi_l2_group_cfg
*rfg
;
3992 struct listnode
*node
;
3994 for (ALL_LIST_ELEMENTS_RO(rfc
->l2_groups
, node
, rfg
)) {
3995 if (!strcmp(rfg
->name
, name
) && /* name match */
3996 (search_cb
== NULL
|| !search_cb(criteria
, rfg
->rfp_cfg
)))
3997 return rfg
->rfp_cfg
;
4002 /*------------------------------------------
4003 * rfapi_rfp_get_group_config_ptr_name
4005 * This is used to get group specific configuration pointer.
4006 * Group is identified by type and name context.
4007 * RFAPI frees rfp_cfg_group when group is deleted during reconfig,
4008 * bgp restart or shutdown.
4011 * rfp_start_val value returned by rfp_start
4014 * criteria RFAPI caller provided serach criteria
4015 * search_cb optional rfp_group_config_search_cb_t
4021 * rfp_cfg_group Pointer to configuration structure
4022 --------------------------------------------*/
4023 void *rfapi_rfp_get_group_config_ptr_name(
4024 void *rfp_start_val
, rfapi_rfp_cfg_group_type type
, const char *name
,
4025 void *criteria
, rfp_group_config_search_cb_t
*search_cb
)
4030 if (rfp_start_val
== NULL
|| name
== NULL
)
4033 bgp
= rfapi_bgp_lookup_by_rfp(rfp_start_val
);
4034 if (!bgp
|| !bgp
->rfapi_cfg
)
4038 case RFAPI_RFP_CFG_GROUP_DEFAULT
:
4039 ret
= bgp
->rfapi_cfg
->default_rfp_cfg
;
4041 case RFAPI_RFP_CFG_GROUP_NVE
:
4042 ret
= rfapi_rfp_get_group_config_name_nve(bgp
->rfapi_cfg
, name
,
4043 criteria
, search_cb
);
4045 case RFAPI_RFP_CFG_GROUP_L2
:
4046 ret
= rfapi_rfp_get_group_config_name_l2(bgp
->rfapi_cfg
, name
,
4047 criteria
, search_cb
);
4050 zlog_err("%s: Unknown group type=%d", __func__
, type
);
4051 /* should never happen */
4052 assert("Unknown type" == NULL
);
4058 /*------------------------------------------
4059 * rfapi_rfp_get_l2_group_config_ptr_lni
4061 * This is used to get group specific configuration pointer.
4062 * Group is identified by type and logical network identifier.
4063 * RFAPI frees rfp_cfg_group when group is deleted during reconfig,
4064 * bgp restart or shutdown.
4067 * rfp_start_val value returned by rfp_start
4069 * logical_net_id group logical network identifier
4070 * criteria RFAPI caller provided serach criteria
4071 * search_cb optional rfp_group_config_search_cb_t
4077 * rfp_cfg_group Pointer to configuration structure
4078 --------------------------------------------*/
4080 rfapi_rfp_get_l2_group_config_ptr_lni(void *rfp_start_val
,
4081 uint32_t logical_net_id
, void *criteria
,
4082 rfp_group_config_search_cb_t
*search_cb
)
4085 struct rfapi_l2_group_cfg
*rfg
;
4086 struct listnode
*node
;
4088 if (rfp_start_val
== NULL
)
4091 bgp
= rfapi_bgp_lookup_by_rfp(rfp_start_val
);
4092 if (!bgp
|| !bgp
->rfapi_cfg
)
4095 for (ALL_LIST_ELEMENTS_RO(bgp
->rfapi_cfg
->l2_groups
, node
, rfg
)) {
4096 if (rfg
->logical_net_id
== logical_net_id
4097 && (search_cb
== NULL
4098 || !search_cb(criteria
, rfg
->rfp_cfg
))) {
4099 if (rfg
->rfp_cfg
== NULL
)
4100 vnc_zlog_debug_verbose(
4101 "%s: returning rfp group config for lni=0",
4103 return rfg
->rfp_cfg
;