From 527588aa78b293eca495208f678a33e1b772a6c3 Mon Sep 17 00:00:00 2001 From: Carmine Scarpitta Date: Sat, 23 Jul 2022 11:49:56 +0200 Subject: [PATCH] bgpd: add support for per-VRF SRv6 SID In the current implementation of bgpd, SRv6 SIDs can be configured only under the address-family. This enables bgpd to leak IPv6 routes using an SRv6 End.DT6 behavior and IPv4 routes using an SRv6 End.DT4 behavior. It is not possible to leak both IPv6 and IPv4 routes using a single SRv6 SID. This commit adds a new CLI command "sid vpn per-vrf export " that enables bgpd to leak both IPv6 and IPv4 routes using a single SRv6 SID (End.DT46 behavior). Signed-off-by: Carmine Scarpitta --- bgpd/bgp_mplsvpn.c | 211 ++++++++++++++++++++++++++++++++++++++++++++- bgpd/bgp_mplsvpn.h | 30 +++++-- bgpd/bgp_vty.c | 95 ++++++++++++++++++++ bgpd/bgp_zebra.c | 22 +++++ bgpd/bgpd.h | 8 ++ 5 files changed, 356 insertions(+), 10 deletions(-) diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index f1ffa7b840a3..33cc836dacae 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -360,7 +360,7 @@ void vpn_leak_zebra_vrf_label_withdraw(struct bgp *bgp, afi_t afi) * leaked to VPN. Zebra should install this srv6-function in the kernel with * an action of "End.DT4/6's IP FIB to route the PDU." */ -void vpn_leak_zebra_vrf_sid_update(struct bgp *bgp, afi_t afi) +void vpn_leak_zebra_vrf_sid_update_per_af(struct bgp *bgp, afi_t afi) { int debug = BGP_DEBUG(vpn, VPN_LEAK_LABEL); enum seg6local_action_t act; @@ -406,11 +406,78 @@ void vpn_leak_zebra_vrf_sid_update(struct bgp *bgp, afi_t afi) bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent = tovpn_sid_ls; } +/* + * This function informs zebra of the srv6-function this vrf sets on routes + * leaked to VPN. Zebra should install this srv6-function in the kernel with + * an action of "End.DT46's IP FIB to route the PDU." + */ +void vpn_leak_zebra_vrf_sid_update_per_vrf(struct bgp *bgp) +{ + int debug = BGP_DEBUG(vpn, VPN_LEAK_LABEL); + enum seg6local_action_t act; + struct seg6local_context ctx = {}; + struct in6_addr *tovpn_sid = NULL; + struct in6_addr *tovpn_sid_ls = NULL; + struct vrf *vrf; + + if (bgp->vrf_id == VRF_UNKNOWN) { + if (debug) + zlog_debug( + "%s: vrf %s: vrf_id not set, can't set zebra vrf label", + __func__, bgp->name_pretty); + return; + } + + tovpn_sid = bgp->tovpn_sid; + if (!tovpn_sid) { + if (debug) + zlog_debug("%s: vrf %s: sid not set", __func__, + bgp->name_pretty); + return; + } + + if (debug) + zlog_debug("%s: vrf %s: setting sid %pI6 for vrf id %d", + __func__, bgp->name_pretty, tovpn_sid, bgp->vrf_id); + + vrf = vrf_lookup_by_id(bgp->vrf_id); + if (!vrf) + return; + + ctx.table = vrf->data.l.table_id; + act = ZEBRA_SEG6_LOCAL_ACTION_END_DT46; + zclient_send_localsid(zclient, tovpn_sid, bgp->vrf_id, act, &ctx); + + tovpn_sid_ls = XCALLOC(MTYPE_BGP_SRV6_SID, sizeof(struct in6_addr)); + *tovpn_sid_ls = *tovpn_sid; + bgp->tovpn_zebra_vrf_sid_last_sent = tovpn_sid_ls; +} + +/* + * This function informs zebra of the srv6-function this vrf sets on routes + * leaked to VPN. Zebra should install this srv6-function in the kernel with + * an action of "End.DT4/6/46's IP FIB to route the PDU." + */ +void vpn_leak_zebra_vrf_sid_update(struct bgp *bgp, afi_t afi) +{ + int debug = BGP_DEBUG(vpn, VPN_LEAK_LABEL); + + if (bgp->vpn_policy[afi].tovpn_sid) + return vpn_leak_zebra_vrf_sid_update_per_af(bgp, afi); + + if (bgp->tovpn_sid) + return vpn_leak_zebra_vrf_sid_update_per_vrf(bgp); + + if (debug) + zlog_debug("%s: vrf %s: afi %s: sid not set", __func__, + bgp->name_pretty, afi2str(afi)); +} + /* * If zebra tells us vrf has become unconfigured, tell zebra not to * use this srv6-function to forward to the vrf anymore */ -void vpn_leak_zebra_vrf_sid_withdraw(struct bgp *bgp, afi_t afi) +void vpn_leak_zebra_vrf_sid_withdraw_per_af(struct bgp *bgp, afi_t afi) { int debug = BGP_DEBUG(vpn, VPN_LEAK_LABEL); @@ -432,6 +499,45 @@ void vpn_leak_zebra_vrf_sid_withdraw(struct bgp *bgp, afi_t afi) bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent); } +/* + * If zebra tells us vrf has become unconfigured, tell zebra not to + * use this srv6-function to forward to the vrf anymore + */ +void vpn_leak_zebra_vrf_sid_withdraw_per_vrf(struct bgp *bgp) +{ + int debug = BGP_DEBUG(vpn, VPN_LEAK_LABEL); + + if (bgp->vrf_id == VRF_UNKNOWN) { + if (debug) + zlog_debug( + "%s: vrf %s: vrf_id not set, can't set zebra vrf label", + __func__, bgp->name_pretty); + return; + } + + if (debug) + zlog_debug("%s: deleting sid for vrf %s (id=%d)", __func__, + bgp->name_pretty, bgp->vrf_id); + + zclient_send_localsid(zclient, bgp->tovpn_zebra_vrf_sid_last_sent, + bgp->vrf_id, ZEBRA_SEG6_LOCAL_ACTION_UNSPEC, + NULL); + XFREE(MTYPE_BGP_SRV6_SID, bgp->tovpn_zebra_vrf_sid_last_sent); +} + +/* + * If zebra tells us vrf has become unconfigured, tell zebra not to + * use this srv6-function to forward to the vrf anymore + */ +void vpn_leak_zebra_vrf_sid_withdraw(struct bgp *bgp, afi_t afi) +{ + if (bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent) + vpn_leak_zebra_vrf_sid_withdraw_per_af(bgp, afi); + + if (bgp->tovpn_zebra_vrf_sid_last_sent) + vpn_leak_zebra_vrf_sid_withdraw_per_vrf(bgp); +} + int vpn_leak_label_callback( mpls_label_t label, void *labelid, @@ -610,7 +716,8 @@ static uint32_t alloc_new_sid(struct bgp *bgp, uint32_t index, return label; } -void ensure_vrf_tovpn_sid(struct bgp *bgp_vpn, struct bgp *bgp_vrf, afi_t afi) +void ensure_vrf_tovpn_sid_per_af(struct bgp *bgp_vpn, struct bgp *bgp_vrf, + afi_t afi) { int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF); char buf[256]; @@ -678,6 +785,81 @@ void ensure_vrf_tovpn_sid(struct bgp *bgp_vpn, struct bgp *bgp_vrf, afi_t afi) tovpn_sid_transpose_label; } +void ensure_vrf_tovpn_sid_per_vrf(struct bgp *bgp_vpn, struct bgp *bgp_vrf) +{ + int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF); + struct srv6_locator_chunk *tovpn_sid_locator; + struct in6_addr *tovpn_sid; + uint32_t tovpn_sid_index = 0, tovpn_sid_transpose_label; + bool tovpn_sid_auto = false; + + if (debug) + zlog_debug("%s: try to allocate new SID for vrf %s", __func__, + bgp_vrf->name_pretty); + + /* skip when tovpn sid is already allocated on vrf instance */ + if (bgp_vrf->tovpn_sid) + return; + + /* + * skip when bgp vpn instance ins't allocated + * or srv6 locator chunk isn't allocated + */ + if (!bgp_vpn || !bgp_vpn->srv6_locator_chunks) + return; + + tovpn_sid_index = bgp_vrf->tovpn_sid_index; + tovpn_sid_auto = CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_TOVPN_SID_AUTO); + + /* skip when VPN isn't configured on vrf-instance */ + if (tovpn_sid_index == 0 && !tovpn_sid_auto) + return; + + /* check invalid case both configured index and auto */ + if (tovpn_sid_index != 0 && tovpn_sid_auto) { + zlog_err("%s: index-mode and auto-mode both selected. ignored.", + __func__); + return; + } + + tovpn_sid_locator = srv6_locator_chunk_alloc(); + tovpn_sid = XCALLOC(MTYPE_BGP_SRV6_SID, sizeof(struct in6_addr)); + + tovpn_sid_transpose_label = alloc_new_sid(bgp_vpn, tovpn_sid_index, + tovpn_sid_locator, tovpn_sid); + + if (tovpn_sid_transpose_label == 0) { + if (debug) + zlog_debug("%s: not allocated new sid for vrf %s", + __func__, bgp_vrf->name_pretty); + srv6_locator_chunk_free(tovpn_sid_locator); + XFREE(MTYPE_BGP_SRV6_SID, tovpn_sid); + return; + } + + if (debug) + zlog_debug("%s: new sid %pI6 allocated for vrf %s", __func__, + tovpn_sid, bgp_vrf->name_pretty); + + bgp_vrf->tovpn_sid = tovpn_sid; + bgp_vrf->tovpn_sid_locator = tovpn_sid_locator; + bgp_vrf->tovpn_sid_transpose_label = tovpn_sid_transpose_label; +} + +void ensure_vrf_tovpn_sid(struct bgp *bgp_vpn, struct bgp *bgp_vrf, afi_t afi) +{ + /* per-af sid */ + if (bgp_vrf->vpn_policy[afi].tovpn_sid_index != 0 || + CHECK_FLAG(bgp_vrf->vpn_policy[afi].flags, + BGP_VPN_POLICY_TOVPN_SID_AUTO)) + return ensure_vrf_tovpn_sid_per_af(bgp_vpn, bgp_vrf, afi); + + /* per-vrf sid */ + if (bgp_vrf->tovpn_sid_index != 0 || + CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_TOVPN_SID_AUTO)) + return ensure_vrf_tovpn_sid_per_vrf(bgp_vpn, bgp_vrf); +} + /* * This function embeds upper `len` bits of `label` in `sid`, * starting at offset `offset` as seen from the MSB of `sid`. @@ -1337,6 +1519,29 @@ void vpn_leak_from_vrf_update(struct bgp *to_bgp, /* to */ &from_bgp->vpn_policy[afi] .tovpn_sid_locator->prefix.prefix, sizeof(struct in6_addr)); + } else if (from_bgp->tovpn_sid_locator) { + encode_label(from_bgp->tovpn_sid_transpose_label, &label); + static_attr.srv6_l3vpn = + XCALLOC(MTYPE_BGP_SRV6_L3VPN, + sizeof(struct bgp_attr_srv6_l3vpn)); + static_attr.srv6_l3vpn->sid_flags = 0x00; + static_attr.srv6_l3vpn->endpoint_behavior = 0xffff; + static_attr.srv6_l3vpn->loc_block_len = + from_bgp->tovpn_sid_locator->block_bits_length; + static_attr.srv6_l3vpn->loc_node_len = + from_bgp->tovpn_sid_locator->node_bits_length; + static_attr.srv6_l3vpn->func_len = + from_bgp->tovpn_sid_locator->function_bits_length; + static_attr.srv6_l3vpn->arg_len = + from_bgp->tovpn_sid_locator->argument_bits_length; + static_attr.srv6_l3vpn->transposition_len = + from_bgp->tovpn_sid_locator->function_bits_length; + static_attr.srv6_l3vpn->transposition_offset = + from_bgp->tovpn_sid_locator->block_bits_length + + from_bgp->tovpn_sid_locator->node_bits_length; + memcpy(&static_attr.srv6_l3vpn->sid, + &from_bgp->tovpn_sid_locator->prefix.prefix, + sizeof(struct in6_addr)); } diff --git a/bgpd/bgp_mplsvpn.h b/bgpd/bgp_mplsvpn.h index 9af4cdf3a258..03d7a0dd2ce1 100644 --- a/bgpd/bgp_mplsvpn.h +++ b/bgpd/bgp_mplsvpn.h @@ -81,9 +81,16 @@ extern void vpn_leak_to_vrf_withdraw(struct bgp *from_bgp, 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_update_per_af(struct bgp *bgp, afi_t afi); +extern void vpn_leak_zebra_vrf_sid_update_per_vrf(struct bgp *bgp); extern void vpn_leak_zebra_vrf_sid_withdraw(struct bgp *bgp, afi_t afi); +extern void vpn_leak_zebra_vrf_sid_withdraw_per_af(struct bgp *bgp, afi_t afi); +extern void vpn_leak_zebra_vrf_sid_withdraw_per_vrf(struct bgp *bgp); 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 ensure_vrf_tovpn_sid_per_af(struct bgp *vpn, struct bgp *vrf, + afi_t afi); +extern void ensure_vrf_tovpn_sid_per_vrf(struct bgp *vpn, struct bgp *vrf); 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, @@ -251,17 +258,26 @@ static inline void vpn_leak_postchange(enum vpn_policy_direction direction, vpn_leak_zebra_vrf_label_update(bgp_vrf, afi); } - if (!bgp_vrf->vpn_policy[afi].tovpn_sid) + if (!bgp_vrf->vpn_policy[afi].tovpn_sid && !bgp_vrf->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) + if ((!bgp_vrf->vpn_policy[afi].tovpn_sid && + bgp_vrf->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent) || + (!bgp_vrf->tovpn_sid && + bgp_vrf->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); + if (bgp_vrf->vpn_policy[afi].tovpn_sid) { + 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); + } + } else if (bgp_vrf->tovpn_sid) { + if (sid_diff(bgp_vrf->tovpn_sid, + bgp_vrf->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); diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index e574ae780519..187e29f0c565 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -331,6 +331,9 @@ static int bgp_srv6_locator_unset(struct bgp *bgp) /* refresh vpnv6 tovpn_sid */ XFREE(MTYPE_BGP_SRV6_SID, bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid); + + /* refresh per-vrf tovpn_sid */ + XFREE(MTYPE_BGP_SRV6_SID, bgp_vrf->tovpn_sid); } /* update vpn bgp processes */ @@ -356,6 +359,9 @@ static int bgp_srv6_locator_unset(struct bgp *bgp) srv6_locator_chunk_free(tovpn_sid_locator); bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid_locator = NULL; } + + /* refresh per-vrf tovpn_sid_locator */ + srv6_locator_chunk_free(bgp_vrf->tovpn_sid_locator); } /* clear locator name */ @@ -8995,6 +9001,14 @@ DEFPY (af_sid_vpn_export, return CMD_WARNING_CONFIG_FAILED; } + if (bgp->tovpn_sid_index != 0 || + CHECK_FLAG(bgp->vrf_flags, BGP_VRF_TOVPN_SID_AUTO)) { + vty_out(vty, + "per-vrf sid and per-af sid are mutually exclusive\n" + "Failed: per-vrf sid is configured. Remove per-vrf sid before configuring per-af sid\n"); + return CMD_WARNING_CONFIG_FAILED; + } + /* skip when it's already configured */ if ((sid_idx != 0 && bgp->vpn_policy[afi].tovpn_sid_index != 0) || (sid_auto && CHECK_FLAG(bgp->vpn_policy[afi].flags, @@ -9036,6 +9050,86 @@ DEFPY (af_sid_vpn_export, return CMD_SUCCESS; } +DEFPY (bgp_sid_vpn_export, + bgp_sid_vpn_export_cmd, + "[no] sid vpn per-vrf export <(1-255)$sid_idx|auto$sid_auto>", + NO_STR + "sid value for VRF\n" + "Between current vrf and vpn\n" + "sid per-VRF (both IPv4 and IPv6 address families)\n" + "For routes leaked from current vrf to vpn\n" + "Sid allocation index\n" + "Automatically assign a label\n") +{ + VTY_DECLVAR_CONTEXT(bgp, bgp); + int debug; + + debug = (BGP_DEBUG(vpn, VPN_LEAK_TO_VRF) | + BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF)); + + if (no) { + /* implement me */ + vty_out(vty, "It's not implemented\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (bgp->vpn_policy[AFI_IP].tovpn_sid_index != 0 || + CHECK_FLAG(bgp->vpn_policy[AFI_IP].flags, + BGP_VPN_POLICY_TOVPN_SID_AUTO) || + bgp->vpn_policy[AFI_IP6].tovpn_sid_index != 0 || + CHECK_FLAG(bgp->vpn_policy[AFI_IP6].flags, + BGP_VPN_POLICY_TOVPN_SID_AUTO)) { + vty_out(vty, + "per-vrf sid and per-af sid are mutually exclusive\n" + "Failed: per-af sid is configured. Remove per-af sid before configuring per-vrf sid\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* skip when it's already configured */ + if ((sid_idx != 0 && bgp->tovpn_sid_index != 0) || + (sid_auto && CHECK_FLAG(bgp->vrf_flags, BGP_VRF_TOVPN_SID_AUTO))) + return CMD_SUCCESS; + + /* + * mode change between sid_idx and sid_auto isn't supported. + * user must negate sid vpn export when they want to change the mode + */ + if ((sid_auto && bgp->tovpn_sid_index != 0) || + (sid_idx != 0 && + CHECK_FLAG(bgp->vrf_flags, BGP_VRF_TOVPN_SID_AUTO))) { + vty_out(vty, "it's already configured as %s.\n", + sid_auto ? "auto-mode" : "idx-mode"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* pre-change */ + vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, AFI_IP, bgp_get_default(), + bgp); + vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, AFI_IP6, bgp_get_default(), + bgp); + + if (sid_auto) { + /* SID allocation auto-mode */ + if (debug) + zlog_debug("%s: auto per-vrf sid alloc.", __func__); + SET_FLAG(bgp->vrf_flags, BGP_VRF_TOVPN_SID_AUTO); + } else { + /* SID allocation index-mode */ + if (debug) + zlog_debug("%s: idx %ld per-vrf sid alloc.", __func__, + sid_idx); + bgp->tovpn_sid_index = sid_idx; + } + + /* post-change */ + vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, AFI_IP, bgp_get_default(), + bgp); + vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, AFI_IP6, + bgp_get_default(), bgp); + + return CMD_SUCCESS; +} + ALIAS (af_label_vpn_export, af_no_label_vpn_export_cmd, "no label vpn export", @@ -19803,6 +19897,7 @@ void bgp_vty_init(void) install_element(BGP_SRV6_NODE, &no_bgp_srv6_locator_cmd); install_element(BGP_IPV4_NODE, &af_sid_vpn_export_cmd); install_element(BGP_IPV6_NODE, &af_sid_vpn_export_cmd); + install_element(BGP_NODE, &bgp_sid_vpn_export_cmd); bgp_vty_if_init(); } diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index b5c13fddd053..f7dda74cce2b 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -3315,6 +3315,17 @@ static int bgp_zebra_process_srv6_locator_delete(ZAPI_CALLBACK_ARGS) XFREE(MTYPE_BGP_SRV6_SID, bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid); } + + /* refresh per-vrf tovpn_sid */ + tovpn_sid = bgp_vrf->tovpn_sid; + if (tovpn_sid) { + tmp_prefi.family = AF_INET6; + tmp_prefi.prefixlen = IPV6_MAX_BITLEN; + tmp_prefi.prefix = *tovpn_sid; + if (prefix_match((struct prefix *)&loc.prefix, + (struct prefix *)&tmp_prefi)) + XFREE(MTYPE_BGP_SRV6_SID, bgp_vrf->tovpn_sid); + } } vpn_leak_postchange_all(); @@ -3353,6 +3364,17 @@ static int bgp_zebra_process_srv6_locator_delete(ZAPI_CALLBACK_ARGS) NULL; } } + + /* refresh per-vrf tovpn_sid_locator */ + tovpn_sid_locator = bgp_vrf->tovpn_sid_locator; + if (tovpn_sid_locator) { + tmp_prefi.family = AF_INET6; + tmp_prefi.prefixlen = IPV6_MAX_BITLEN; + tmp_prefi.prefix = tovpn_sid_locator->prefix.prefix; + if (prefix_match((struct prefix *)&loc.prefix, + (struct prefix *)&tmp_prefi)) + srv6_locator_chunk_free(tovpn_sid_locator); + } } return 0; diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 64d87f946c69..c844f1530f5c 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -759,6 +759,8 @@ struct bgp { #define BGP_VRF_EXPORT_AUTO_RT_CFGD (1 << 4) /* retain auto when cfgd */ #define BGP_VRF_RD_CFGD (1 << 5) #define BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY (1 << 6) +/* per-VRF toVPN SID */ +#define BGP_VRF_TOVPN_SID_AUTO (1 << 7) /* unique ID for auto derivation of RD for this vrf */ uint16_t vrf_rd_id; @@ -806,6 +808,12 @@ struct bgp { char srv6_locator_name[SRV6_LOCNAME_SIZE]; struct list *srv6_locator_chunks; struct list *srv6_functions; + uint32_t tovpn_sid_index; /* unset => set to 0 */ + struct in6_addr *tovpn_sid; + struct srv6_locator_chunk *tovpn_sid_locator; + uint32_t tovpn_sid_transpose_label; + struct in6_addr *tovpn_zebra_vrf_sid_last_sent; + /* TCP keepalive parameters for BGP connection */ uint16_t tcp_keepalive_idle; uint16_t tcp_keepalive_intvl;