+// SPDX-License-Identifier: GPL-2.0-or-later
/* zebra client
* Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
- *
- * This file is part of GNU 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
*/
#include <zebra.h>
#include "sockunion.h"
#include "zclient.h"
#include "routemap.h"
-#include "thread.h"
+#include "frrevent.h"
#include "queue.h"
#include "memory.h"
#include "lib/json.h"
#include "bgpd/bgp_trace.h"
#include "bgpd/bgp_community.h"
#include "bgpd/bgp_lcommunity.h"
-#include "bgpd/bgp_orr.h"
/* All information about zebra. */
struct zclient *zclient = NULL;
-static int bgp_opaque_msg_handler(ZAPI_CALLBACK_ARGS);
-
/* hook to indicate vrf status change for SNMP */
DEFINE_HOOK(bgp_vrf_status_changed, (struct bgp *bgp, struct interface *ifp),
(bgp, ifp));
struct connected *c;
struct nbr_connected *nc;
struct listnode *node, *nnode;
- struct bgp *bgp_default = bgp_get_default();
struct bgp *bgp;
bgp = ifp->vrf->info;
hook_call(bgp_vrf_status_changed, bgp, ifp);
bgp_nht_ifp_up(ifp);
- if (bgp_default && if_is_loopback(ifp)) {
- vpn_leak_zebra_vrf_label_update(bgp, AFI_IP);
- vpn_leak_zebra_vrf_label_update(bgp, AFI_IP6);
- vpn_leak_zebra_vrf_sid_update(bgp, AFI_IP);
- vpn_leak_zebra_vrf_sid_update(bgp, AFI_IP6);
- vpn_leak_postchange_all();
- }
-
return 0;
}
struct connected *c;
struct nbr_connected *nc;
struct listnode *node, *nnode;
- struct bgp *bgp_default = bgp_get_default();
struct bgp *bgp;
struct peer *peer;
hook_call(bgp_vrf_status_changed, bgp, ifp);
bgp_nht_ifp_down(ifp);
- if (bgp_default && if_is_loopback(ifp)) {
- vpn_leak_zebra_vrf_label_update(bgp, AFI_IP);
- vpn_leak_zebra_vrf_label_update(bgp, AFI_IP6);
- vpn_leak_zebra_vrf_sid_update(bgp, AFI_IP);
- vpn_leak_zebra_vrf_sid_update(bgp, AFI_IP6);
- vpn_leak_postchange_all();
- }
-
return 0;
}
static int bgp_interface_address_delete(ZAPI_CALLBACK_ARGS)
{
struct listnode *node, *nnode;
- struct bgp_path_info *pi;
- struct bgp_table *table;
- struct bgp_dest *dest;
struct connected *ifc;
struct peer *peer;
- struct bgp *bgp, *from_bgp, *bgp_default;
- struct listnode *next;
+ struct bgp *bgp;
struct prefix *addr;
- afi_t afi;
- safi_t safi;
bgp = bgp_lookup_by_vrf_id(vrf_id);
* we do not want the peering to bounce.
*/
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
+ afi_t afi;
+ safi_t safi;
+
if (addr->family == AF_INET)
continue;
}
}
- bgp_default = bgp_get_default();
- afi = family2afi(addr->family);
- safi = SAFI_UNICAST;
-
- /* When the last IPv4 address was deleted, Linux removes all routes
- * using the interface so that bgpd needs to re-send them.
- */
- if (bgp_default && afi == AFI_IP) {
- for (ALL_LIST_ELEMENTS_RO(bm->bgp, next, from_bgp)) {
- table = from_bgp->rib[afi][safi];
- if (!table)
- continue;
-
- for (dest = bgp_table_top(table); dest;
- dest = bgp_route_next(dest)) {
- for (pi = bgp_dest_get_bgp_path_info(dest); pi;
- pi = pi->next) {
- if (pi->type == ZEBRA_ROUTE_BGP &&
- pi->attr &&
- pi->attr->nh_ifindex ==
- ifc->ifp->ifindex) {
- SET_FLAG(pi->attr->nh_flag,
- BGP_ATTR_NH_REFRESH);
- }
- }
- }
-
- if (from_bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
- continue;
-
- vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi,
- bgp_default, from_bgp);
-
- vpn_leak_postchange(BGP_VPN_POLICY_DIR_FROMVPN, afi,
- bgp_default, from_bgp);
- }
- }
-
connected_free(&ifc);
return 0;
peer->bgp->vrf_id);
}
+ /* Handle peerings via loopbacks. For instance, peer between
+ * 127.0.0.1 and 127.0.0.2. In short, allow peering with self
+ * via 127.0.0.0/8.
+ */
+ if (!ifp && cmd_allow_reserved_ranges_get())
+ ifp = if_get_vrf_loopback(peer->bgp->vrf_id);
+
if (!ifp) {
/*
* BGP views do not currently get proper data
|| path->attr->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) {
/* Check if route-map is set to prefer global over link-local */
- if (CHECK_FLAG(path->attr->nh_flag,
- BGP_ATTR_NH_MP_PREFER_GLOBAL)) {
+ if (path->attr->mp_nexthop_prefer_global) {
nexthop = &path->attr->mp_nexthop_global;
if (IN6_IS_ADDR_LINKLOCAL(nexthop))
*ifindex = path->attr->nh_ifindex;
return false;
}
-static struct thread *bgp_tm_thread_connect;
+static struct event *bgp_tm_thread_connect;
static bool bgp_tm_status_connected;
static bool bgp_tm_chunk_obtained;
#define BGP_FLOWSPEC_TABLE_CHUNK 100000
static uint32_t bgp_tm_min, bgp_tm_max, bgp_tm_chunk_size;
struct bgp *bgp_tm_bgp;
-static void bgp_zebra_tm_connect(struct thread *t)
+static void bgp_zebra_tm_connect(struct event *t)
{
struct zclient *zclient;
int delay = 10, ret = 0;
- zclient = THREAD_ARG(t);
+ zclient = EVENT_ARG(t);
if (bgp_tm_status_connected && zclient->sock > 0)
delay = 60;
else {
}
}
}
- thread_add_timer(bm->master, bgp_zebra_tm_connect, zclient, delay,
- &bgp_tm_thread_connect);
+ event_add_timer(bm->master, bgp_zebra_tm_connect, zclient, delay,
+ &bgp_tm_thread_connect);
}
bool bgp_zebra_tm_chunk_obtained(void)
bgp_tm_min = bgp_tm_max = 0;
bgp_tm_chunk_size = BGP_FLOWSPEC_TABLE_CHUNK;
bgp_tm_bgp = bgp;
- thread_add_timer(bm->master, bgp_zebra_tm_connect, zclient, delay,
- &bgp_tm_thread_connect);
+ event_add_timer(bm->master, bgp_zebra_tm_connect, zclient, delay,
+ &bgp_tm_thread_connect);
}
int bgp_zebra_get_table_range(uint32_t chunk_size,
uint8_t distance;
struct peer *peer;
struct bgp_path_info *mpinfo;
- struct bgp_path_info *bpi_ultimate;
struct bgp *bgp_orig;
uint32_t metric;
struct attr local_attr;
struct bgp_path_info local_info;
struct bgp_path_info *mpinfo_cp = &local_info;
route_tag_t tag;
- mpls_label_t label;
struct bgp_sid_info *sid_info;
+ mpls_label_t *labels;
+ uint32_t num_labels = 0;
+ mpls_label_t nh_label;
int nh_othervrf = 0;
bool nh_updated = false;
bool do_wt_ecmp;
uint32_t bos = 0;
uint32_t exp = 0;
+ /*
+ * BGP is installing this route and bgp has been configured
+ * to suppress announcements until the route has been installed
+ * let's set the fact that we expect this route to be installed
+ */
+ if (BGP_SUPPRESS_FIB_ENABLED(bgp))
+ SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
+
/* Don't try to install if we're not connected to Zebra or Zebra doesn't
* know of this instance.
*/
peer = info->peer;
- if (info->type == ZEBRA_ROUTE_BGP) {
- bpi_ultimate = bgp_get_imported_bpi_ultimate(info);
- peer = bpi_ultimate->peer;
+ if (info->type == ZEBRA_ROUTE_BGP
+ && info->sub_type == BGP_ROUTE_IMPORTED) {
+
+ /* Obtain peer from parent */
+ if (info->extra && info->extra->parent)
+ peer = ((struct bgp_path_info *)(info->extra->parent))
+ ->peer;
}
tag = info->attr->tag;
}
for (; mpinfo; mpinfo = bgp_path_info_mpath_next(mpinfo)) {
+ labels = NULL;
+ num_labels = 0;
uint32_t nh_weight;
bool is_evpn;
+ bool is_parent_evpn;
if (valid_nh_count >= multipath_num)
break;
BGP_ORIGINAL_UPDATE(bgp_orig, mpinfo, bgp);
- if (nh_family == AF_INET) {
- is_evpn = is_route_parent_evpn(mpinfo);
+ is_parent_evpn = is_route_parent_evpn(mpinfo);
+ if (nh_family == AF_INET) {
nh_updated = update_ipv4nh_for_route_install(
nh_othervrf, bgp_orig,
&mpinfo_cp->attr->nexthop, mpinfo_cp->attr,
- is_evpn, api_nh);
+ is_parent_evpn, api_nh);
} else {
ifindex_t ifindex = IFINDEX_INTERNAL;
struct in6_addr *nexthop;
nexthop = bgp_path_info_to_ipv6_nexthop(mpinfo_cp,
&ifindex);
- is_evpn = is_route_parent_evpn(mpinfo);
-
if (!nexthop)
nh_updated = update_ipv4nh_for_route_install(
nh_othervrf, bgp_orig,
&mpinfo_cp->attr->nexthop,
- mpinfo_cp->attr, is_evpn, api_nh);
+ mpinfo_cp->attr, is_parent_evpn,
+ api_nh);
else
nh_updated = update_ipv6nh_for_route_install(
nh_othervrf, bgp_orig, nexthop, ifindex,
- mpinfo, info, is_evpn, api_nh);
+ mpinfo, info, is_parent_evpn, api_nh);
}
+ is_evpn = !!CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_EVPN);
+
/* Did we get proper nexthop info to update zebra? */
if (!nh_updated)
continue;
|| mpinfo->peer->sort == BGP_PEER_CONFED))
allow_recursion = true;
- if (mpinfo->extra &&
- bgp_is_valid_label(&mpinfo->extra->label[0]) &&
- !CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_EVPN)) {
- mpls_lse_decode(mpinfo->extra->label[0], &label, &ttl,
- &exp, &bos);
+ if (mpinfo->extra) {
+ labels = mpinfo->extra->label;
+ num_labels = mpinfo->extra->num_labels;
+ }
- SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_LABEL);
+ if (labels && (num_labels > 0) &&
+ (is_evpn || bgp_is_valid_label(&labels[0]))) {
+ enum lsp_types_t nh_label_type = ZEBRA_LSP_NONE;
+ if (is_evpn) {
+ nh_label = *bgp_evpn_path_info_labels_get_l3vni(
+ labels, num_labels);
+ nh_label_type = ZEBRA_LSP_EVPN;
+ } else {
+ mpls_lse_decode(labels[0], &nh_label, &ttl,
+ &exp, &bos);
+ }
+
+ SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_LABEL);
api_nh->label_num = 1;
- api_nh->labels[0] = label;
+ api_nh->label_type = nh_label_type;
+ api_nh->labels[0] = nh_label;
}
if (is_evpn
api_nh->weight = nh_weight;
- if (mpinfo->extra &&
- bgp_is_valid_label(&mpinfo->extra->label[0]) &&
- !sid_zero(&mpinfo->extra->sid[0].sid) &&
- !CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_EVPN)) {
+ if (mpinfo->extra && !is_evpn &&
+ bgp_is_valid_label(&labels[0]) &&
+ !sid_zero(&mpinfo->extra->sid[0].sid)) {
sid_info = &mpinfo->extra->sid[0];
memcpy(&api_nh->seg6_segs, &sid_info->sid,
sizeof(api_nh->seg6_segs));
if (sid_info->transposition_len != 0) {
- mpls_lse_decode(mpinfo->extra->label[0], &label,
- &ttl, &exp, &bos);
+ mpls_lse_decode(labels[0], &nh_label, &ttl,
+ &exp, &bos);
- if (label < MPLS_LABEL_UNRESERVED_MIN) {
+ if (nh_label < MPLS_LABEL_UNRESERVED_MIN) {
if (bgp_debug_zebra(&api.prefix))
zlog_debug(
"skip invalid SRv6 routes: transposition scheme is used, but label is too small");
continue;
}
- transpose_sid(&api_nh->seg6_segs, label,
+ transpose_sid(&api_nh->seg6_segs, nh_label,
sid_info->transposition_offset,
sid_info->transposition_len);
}
struct zapi_route api;
struct peer *peer;
+ /*
+ * If we are withdrawing the route, we don't need to have this
+ * flag set. So unset it.
+ */
+ UNSET_FLAG(info->net->flags, BGP_NODE_FIB_INSTALL_PENDING);
+
/* Don't try to install if we're not connected to Zebra or Zebra doesn't
* know of this instance.
*/
}
/* Find the bgp route node */
- dest = bgp_afi_node_lookup(bgp->rib[afi][safi], afi, safi, &p,
- &bgp->vrf_prd);
+ dest = bgp_safi_node_lookup(bgp->rib[afi][safi], safi, &p,
+ &bgp->vrf_prd);
if (!dest)
return -1;
static int bgp_ifp_create(struct interface *ifp)
{
- struct bgp *bgp_default = bgp_get_default();
struct bgp *bgp;
if (BGP_DEBUG(zebra, ZEBRA))
bgp_update_interface_nbrs(bgp, ifp, ifp);
hook_call(bgp_vrf_status_changed, bgp, ifp);
-
- if (bgp_default &&
- (if_is_loopback_exact(ifp) ||
- (if_is_vrf(ifp) && ifp->vrf->vrf_id != VRF_DEFAULT))) {
- vpn_leak_zebra_vrf_label_update(bgp, AFI_IP);
- vpn_leak_zebra_vrf_label_update(bgp, AFI_IP6);
- vpn_leak_zebra_vrf_sid_update(bgp, AFI_IP);
- vpn_leak_zebra_vrf_sid_update(bgp, AFI_IP6);
- vpn_leak_postchange_all();
- }
-
return 0;
}
[ZEBRA_SRV6_LOCATOR_DELETE] = bgp_zebra_process_srv6_locator_delete,
[ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK] =
bgp_zebra_process_srv6_locator_chunk,
- [ZEBRA_OPAQUE_MESSAGE] = bgp_opaque_msg_handler,
};
static int bgp_if_new_hook(struct interface *ifp)
hook_register_prio(if_del, 0, bgp_if_delete_hook);
}
-void bgp_zebra_init(struct thread_master *master, unsigned short instance)
+void bgp_zebra_init(struct event_loop *master, unsigned short instance)
{
zclient_num_connects = 0;
struct zapi_cap api;
int ret = BGP_GR_SUCCESS;
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("%s: Sending %sable for %s", __func__,
+ disable ? "dis" : "en", bgp->name_pretty);
+
if (zclient == NULL) {
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("zclient invalid");
+ zlog_debug("%s: %s zclient invalid", __func__,
+ bgp->name_pretty);
return BGP_GR_FAILURE;
}
/* Check if the client is connected */
if ((zclient->sock < 0) || (zclient->t_connect)) {
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("client not connected");
+ zlog_debug("%s: %s client not connected", __func__,
+ bgp->name_pretty);
return BGP_GR_FAILURE;
}
if (zclient_capabilities_send(ZEBRA_CLIENT_CAPABILITIES, zclient, &api)
== ZCLIENT_SEND_FAILURE) {
- zlog_err("error sending capability");
+ zlog_err("%s: %s error sending capability", __func__,
+ bgp->name_pretty);
ret = BGP_GR_FAILURE;
} else {
if (disable)
bgp->present_zebra_gr_state = ZEBRA_GR_ENABLE;
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("send capabilty success");
+ zlog_debug("%s: %s send capabilty success", __func__,
+ bgp->name_pretty);
ret = BGP_GR_SUCCESS;
}
return ret;
/* Send route update pesding or completed status to RIB for the
* specific AFI, SAFI
*/
-int bgp_zebra_update(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type)
+int bgp_zebra_update(struct bgp *bgp, afi_t afi, safi_t safi,
+ enum zserv_client_capabilities type)
{
struct zapi_cap api = {0};
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("%s: %s afi: %u safi: %u Command %s", __func__,
+ bgp->name_pretty, afi, safi,
+ zserv_gr_client_cap_string(type));
+
if (zclient == NULL) {
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("zclient == NULL, invalid");
+ zlog_debug("%s: %s zclient == NULL, invalid", __func__,
+ bgp->name_pretty);
return BGP_GR_FAILURE;
}
/* Check if the client is connected */
if ((zclient->sock < 0) || (zclient->t_connect)) {
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("client not connected");
+ zlog_debug("%s: %s client not connected", __func__,
+ bgp->name_pretty);
return BGP_GR_FAILURE;
}
api.afi = afi;
api.safi = safi;
- api.vrf_id = vrf_id;
+ api.vrf_id = bgp->vrf_id;
api.cap = type;
if (zclient_capabilities_send(ZEBRA_CLIENT_CAPABILITIES, zclient, &api)
== ZCLIENT_SEND_FAILURE) {
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("error sending capability");
+ zlog_debug("%s: %s error sending capability", __func__,
+ bgp->name_pretty);
return BGP_GR_FAILURE;
}
return BGP_GR_SUCCESS;
{
struct zapi_cap api;
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("%s: %s Timer Update to %u", __func__,
+ bgp->name_pretty, bgp->rib_stale_time);
+
if (zclient == NULL) {
if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug("zclient invalid");
/* Check if the client is connected */
if ((zclient->sock < 0) || (zclient->t_connect)) {
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("client not connected");
+ zlog_debug("%s: %s client not connected", __func__,
+ bgp->name_pretty);
return BGP_GR_FAILURE;
}
if (zclient_capabilities_send(ZEBRA_CLIENT_CAPABILITIES, zclient, &api)
== ZCLIENT_SEND_FAILURE) {
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("error sending capability");
+ zlog_debug("%s: %s error sending capability", __func__,
+ bgp->name_pretty);
return BGP_GR_FAILURE;
}
- if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("send capabilty success");
+
return BGP_GR_SUCCESS;
}
{
return srv6_manager_release_locator_chunk(zclient, name);
}
-
-/*
- * ORR messages between processes
- */
-static int bgp_opaque_msg_handler(ZAPI_CALLBACK_ARGS)
-{
- struct stream *s;
- struct zapi_opaque_msg info;
- struct orr_igp_metric_info table;
- int ret = 0;
-
- s = zclient->ibuf;
-
- if (zclient_opaque_decode(s, &info) != 0) {
- bgp_orr_debug("%s: opaque decode failed", __func__);
- return -1;
- }
-
- switch (info.type) {
- case ORR_IGP_METRIC_UPDATE:
- STREAM_GET(&table, s, sizeof(table));
- ret = bgg_orr_message_process(BGP_ORR_IMSG_IGP_METRIC_UPDATE,
- (void *)&table);
- break;
- default:
- break;
- }
-
-stream_failure:
- return ret;
-}