summaryrefslogtreecommitdiffstats
path: root/bgpd/bgp_mplsvpn.h
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 09:53:30 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 09:53:30 +0000
commit2c7cac91ed6e7db0f6937923d2b57f97dbdbc337 (patch)
treec05dc0f8e6aa3accc84e3e5cffc933ed94941383 /bgpd/bgp_mplsvpn.h
parentInitial commit. (diff)
downloadfrr-2c7cac91ed6e7db0f6937923d2b57f97dbdbc337.tar.xz
frr-2c7cac91ed6e7db0f6937923d2b57f97dbdbc337.zip
Adding upstream version 8.4.4.upstream/8.4.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'bgpd/bgp_mplsvpn.h')
-rw-r--r--bgpd/bgp_mplsvpn.h311
1 files changed, 311 insertions, 0 deletions
diff --git a/bgpd/bgp_mplsvpn.h b/bgpd/bgp_mplsvpn.h
new file mode 100644
index 0000000..c5cc7d4
--- /dev/null
+++ b/bgpd/bgp_mplsvpn.h
@@ -0,0 +1,311 @@
+/* MPLS-VPN
+ * Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
+ *
+ * This file is part of GxNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _QUAGGA_BGP_MPLSVPN_H
+#define _QUAGGA_BGP_MPLSVPN_H
+
+#include "bgpd/bgp_attr.h"
+#include "bgpd/bgp_route.h"
+#include "bgpd/bgp_rd.h"
+#include "bgpd/bgp_zebra.h"
+#include "bgpd/bgp_vty.h"
+
+#define MPLS_LABEL_IS_SPECIAL(label) ((label) <= MPLS_LABEL_EXTENSION)
+#define MPLS_LABEL_IS_NULL(label) \
+ ((label) == MPLS_LABEL_IPV4_EXPLICIT_NULL \
+ || (label) == MPLS_LABEL_IPV6_EXPLICIT_NULL \
+ || (label) == MPLS_LABEL_IMPLICIT_NULL)
+
+#define BGP_VPNVX_HELP_STR BGP_AF_STR BGP_AF_STR
+
+#define V4_HEADER \
+ " Network Next Hop Metric LocPrf Weight Path\n"
+#define V4_HEADER_TAG " Network Next Hop In tag/Out tag\n"
+#define V4_HEADER_OVERLAY \
+ " Network Next Hop EthTag Overlay Index RouterMac\n"
+
+extern void bgp_mplsvpn_init(void);
+extern int bgp_nlri_parse_vpn(struct peer *, struct attr *, struct bgp_nlri *);
+extern uint32_t decode_label(mpls_label_t *);
+extern void encode_label(mpls_label_t, mpls_label_t *);
+
+extern int argv_find_and_parse_vpnvx(struct cmd_token **argv, int argc,
+ int *index, afi_t *afi);
+extern int bgp_show_mpls_vpn(struct vty *vty, afi_t afi, struct prefix_rd *prd,
+ enum bgp_show_type type, void *output_arg,
+ int tags, bool use_json);
+
+extern void vpn_leak_from_vrf_update(struct bgp *to_bgp, struct bgp *from_bgp,
+ struct bgp_path_info *path_vrf);
+
+extern void vpn_leak_from_vrf_withdraw(struct bgp *to_bgp, struct bgp *from_bgp,
+ struct bgp_path_info *path_vrf);
+
+extern void vpn_leak_from_vrf_withdraw_all(struct bgp *to_bgp,
+ struct bgp *from_bgp, afi_t afi);
+
+extern void vpn_leak_from_vrf_update_all(struct bgp *to_bgp,
+ struct bgp *from_bgp, afi_t afi);
+
+extern void vpn_leak_to_vrf_withdraw_all(struct bgp *to_bgp, afi_t afi);
+
+extern void vpn_leak_to_vrf_update_all(struct bgp *to_bgp, struct bgp *from_bgp,
+ afi_t afi);
+
+extern bool vpn_leak_to_vrf_update(struct bgp *from_bgp,
+ struct bgp_path_info *path_vpn);
+
+extern void vpn_leak_to_vrf_withdraw(struct bgp *from_bgp,
+ struct bgp_path_info *path_vpn);
+
+extern void vpn_leak_zebra_vrf_label_update(struct bgp *bgp, afi_t afi);
+extern void vpn_leak_zebra_vrf_label_withdraw(struct bgp *bgp, afi_t afi);
+extern void vpn_leak_zebra_vrf_sid_update(struct bgp *bgp, afi_t afi);
+extern void vpn_leak_zebra_vrf_sid_withdraw(struct bgp *bgp, afi_t afi);
+extern int vpn_leak_label_callback(mpls_label_t label, void *lblid, bool alloc);
+extern void ensure_vrf_tovpn_sid(struct bgp *vpn, struct bgp *vrf, afi_t afi);
+extern void transpose_sid(struct in6_addr *sid, uint32_t label, uint8_t offset,
+ uint8_t size);
+extern void vrf_import_from_vrf(struct bgp *to_bgp, struct bgp *from_bgp,
+ afi_t afi, safi_t safi);
+void vrf_unimport_from_vrf(struct bgp *to_bgp, struct bgp *from_bgp,
+ afi_t afi, safi_t safi);
+
+static inline bool is_bgp_vrf_mplsvpn(struct bgp *bgp)
+{
+ afi_t afi;
+
+ if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
+ for (afi = 0; afi < AFI_MAX; ++afi) {
+ if (CHECK_FLAG(bgp->af_flags[afi][SAFI_UNICAST],
+ BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT)
+ || CHECK_FLAG(bgp->af_flags[afi][SAFI_UNICAST],
+ BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT))
+ return true;
+ }
+ return false;
+}
+
+static inline int vpn_leak_to_vpn_active(struct bgp *bgp_vrf, afi_t afi,
+ const char **pmsg)
+{
+ if (bgp_vrf->inst_type != BGP_INSTANCE_TYPE_VRF
+ && bgp_vrf->inst_type != BGP_INSTANCE_TYPE_DEFAULT) {
+
+ if (pmsg)
+ *pmsg = "source bgp instance neither vrf nor default";
+ return 0;
+ }
+
+ /* Is vrf configured to export to vpn? */
+ if (!CHECK_FLAG(bgp_vrf->af_flags[afi][SAFI_UNICAST],
+ BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT)
+ && !CHECK_FLAG(bgp_vrf->af_flags[afi][SAFI_UNICAST],
+ BGP_CONFIG_VRF_TO_VRF_EXPORT)) {
+ if (pmsg)
+ *pmsg = "export not set";
+ return 0;
+ }
+
+ /* Is there an RT list set? */
+ if (!bgp_vrf->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_TOVPN]) {
+ if (pmsg)
+ *pmsg = "rtlist tovpn not defined";
+ return 0;
+ }
+
+ /* Is there an RD set? */
+ if (!CHECK_FLAG(bgp_vrf->vpn_policy[afi].flags,
+ BGP_VPN_POLICY_TOVPN_RD_SET)) {
+ if (pmsg)
+ *pmsg = "rd not defined";
+ return 0;
+ }
+
+ /* Is a route-map specified, but not defined? */
+ if (bgp_vrf->vpn_policy[afi].rmap_name[BGP_VPN_POLICY_DIR_TOVPN] &&
+ !bgp_vrf->vpn_policy[afi].rmap[BGP_VPN_POLICY_DIR_TOVPN]) {
+ if (pmsg)
+ *pmsg = "route-map tovpn named but not defined";
+ return 0;
+ }
+
+ /* Is there an "auto" export label that isn't allocated yet? */
+ if (CHECK_FLAG(bgp_vrf->vpn_policy[afi].flags,
+ BGP_VPN_POLICY_TOVPN_LABEL_AUTO) &&
+ (bgp_vrf->vpn_policy[afi].tovpn_label == MPLS_LABEL_NONE)) {
+
+ if (pmsg)
+ *pmsg = "auto label not allocated";
+ return 0;
+ }
+
+ return 1;
+}
+
+static inline int vpn_leak_from_vpn_active(struct bgp *bgp_vrf, afi_t afi,
+ const char **pmsg)
+{
+ if (bgp_vrf->inst_type != BGP_INSTANCE_TYPE_VRF
+ && bgp_vrf->inst_type != BGP_INSTANCE_TYPE_DEFAULT) {
+
+ if (pmsg)
+ *pmsg = "destination bgp instance neither vrf nor default";
+ return 0;
+ }
+
+ if (bgp_vrf->vrf_id == VRF_UNKNOWN) {
+ if (pmsg)
+ *pmsg = "destination bgp instance vrf is VRF_UNKNOWN";
+ return 0;
+ }
+
+ /* Is vrf configured to import from vpn? */
+ if (!CHECK_FLAG(bgp_vrf->af_flags[afi][SAFI_UNICAST],
+ BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT)
+ && !CHECK_FLAG(bgp_vrf->af_flags[afi][SAFI_UNICAST],
+ BGP_CONFIG_VRF_TO_VRF_IMPORT)) {
+ if (pmsg)
+ *pmsg = "import not set";
+ return 0;
+ }
+
+ /* Is there an RT list set? */
+ if (!bgp_vrf->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_FROMVPN]) {
+ if (pmsg)
+ *pmsg = "rtlist fromvpn not defined";
+ return 0;
+ }
+
+ /* Is a route-map specified, but not defined? */
+ if (bgp_vrf->vpn_policy[afi].rmap_name[BGP_VPN_POLICY_DIR_FROMVPN] &&
+ !bgp_vrf->vpn_policy[afi].rmap[BGP_VPN_POLICY_DIR_FROMVPN]) {
+ if (pmsg)
+ *pmsg = "route-map fromvpn named but not defined";
+ return 0;
+ }
+ return 1;
+}
+
+static inline void vpn_leak_prechange(enum vpn_policy_direction direction,
+ afi_t afi, struct bgp *bgp_vpn,
+ struct bgp *bgp_vrf)
+{
+ /* Detect when default bgp instance is not (yet) defined by config */
+ if (!bgp_vpn)
+ return;
+
+ if ((direction == BGP_VPN_POLICY_DIR_FROMVPN) &&
+ vpn_leak_from_vpn_active(bgp_vrf, afi, NULL)) {
+
+ vpn_leak_to_vrf_withdraw_all(bgp_vrf, afi);
+ }
+ if ((direction == BGP_VPN_POLICY_DIR_TOVPN) &&
+ vpn_leak_to_vpn_active(bgp_vrf, afi, NULL)) {
+
+ vpn_leak_from_vrf_withdraw_all(bgp_vpn, bgp_vrf, afi);
+ }
+}
+
+static inline void vpn_leak_postchange(enum vpn_policy_direction direction,
+ afi_t afi, struct bgp *bgp_vpn,
+ struct bgp *bgp_vrf)
+{
+ /* Detect when default bgp instance is not (yet) defined by config */
+ if (!bgp_vpn)
+ return;
+
+ if (direction == BGP_VPN_POLICY_DIR_FROMVPN) {
+ /* trigger a flush to re-sync with ADJ-RIB-in */
+ if (!CHECK_FLAG(bgp_vpn->af_flags[afi][SAFI_MPLS_VPN],
+ BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL))
+ bgp_clear_soft_in(bgp_vpn, afi, SAFI_MPLS_VPN);
+ else
+ vpn_leak_to_vrf_update_all(bgp_vrf, bgp_vpn, afi);
+ }
+ if (direction == BGP_VPN_POLICY_DIR_TOVPN) {
+
+ if (bgp_vrf->vpn_policy[afi].tovpn_label !=
+ bgp_vrf->vpn_policy[afi]
+ .tovpn_zebra_vrf_label_last_sent) {
+ vpn_leak_zebra_vrf_label_update(bgp_vrf, afi);
+ }
+
+ if (!bgp_vrf->vpn_policy[afi].tovpn_sid)
+ ensure_vrf_tovpn_sid(bgp_vpn, bgp_vrf, afi);
+
+ if (!bgp_vrf->vpn_policy[afi].tovpn_sid
+ && bgp_vrf->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent)
+ vpn_leak_zebra_vrf_sid_withdraw(bgp_vrf, afi);
+
+ if (sid_diff(bgp_vrf->vpn_policy[afi].tovpn_sid,
+ bgp_vrf->vpn_policy[afi]
+ .tovpn_zebra_vrf_sid_last_sent)) {
+ vpn_leak_zebra_vrf_sid_update(bgp_vrf, afi);
+ }
+
+ vpn_leak_from_vrf_update_all(bgp_vpn, bgp_vrf, afi);
+ }
+}
+
+/* Flag if the route is injectable into VPN. This would be either a
+ * non-imported route or a non-VPN imported route.
+ */
+static inline bool is_route_injectable_into_vpn(struct bgp_path_info *pi)
+{
+ struct bgp_path_info *parent_pi;
+ struct bgp_table *table;
+ struct bgp_dest *dest;
+
+ if (pi->sub_type != BGP_ROUTE_IMPORTED ||
+ !pi->extra ||
+ !pi->extra->parent)
+ return true;
+
+ parent_pi = (struct bgp_path_info *)pi->extra->parent;
+ dest = parent_pi->net;
+ if (!dest)
+ return true;
+ table = bgp_dest_table(dest);
+ if (table &&
+ (table->afi == AFI_IP || table->afi == AFI_IP6) &&
+ table->safi == SAFI_MPLS_VPN)
+ return false;
+ return true;
+}
+
+/* Flag if the route path's family is VPN. */
+static inline bool is_pi_family_vpn(struct bgp_path_info *pi)
+{
+ return (is_pi_family_matching(pi, AFI_IP, SAFI_MPLS_VPN) ||
+ is_pi_family_matching(pi, AFI_IP6, SAFI_MPLS_VPN));
+}
+
+extern void vpn_policy_routemap_event(const char *rmap_name);
+
+extern vrf_id_t get_first_vrf_for_redirect_with_rt(struct ecommunity *eckey);
+
+extern void vpn_leak_postchange_all(void);
+extern void vpn_handle_router_id_update(struct bgp *bgp, bool withdraw,
+ bool is_config);
+extern void bgp_vpn_leak_unimport(struct bgp *from_bgp);
+extern void bgp_vpn_leak_export(struct bgp *from_bgp);
+
+#endif /* _QUAGGA_BGP_MPLSVPN_H */