summaryrefslogtreecommitdiff
path: root/lib/zclient.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/zclient.c')
-rw-r--r--lib/zclient.c655
1 files changed, 530 insertions, 125 deletions
diff --git a/lib/zclient.c b/lib/zclient.c
index 8ec82ab7bb..c36bcc6e2e 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -1,22 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/* Zebra's client library.
* Copyright (C) 1999 Kunihiro Ishiguro
* Copyright (C) 2005 Andrew J. Schorr
- *
- * 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>
@@ -29,7 +14,7 @@
#include "vrf_int.h"
#include "if.h"
#include "log.h"
-#include "thread.h"
+#include "frrevent.h"
#include "zclient.h"
#include "memory.h"
#include "table.h"
@@ -37,6 +22,7 @@
#include "mpls.h"
#include "sockopt.h"
#include "pbr.h"
+#include "tc.h"
#include "nexthop_group.h"
#include "lib_errors.h"
#include "srte.h"
@@ -65,7 +51,7 @@ socklen_t zclient_addr_len;
static int zclient_debug;
/* Allocate zclient structure. */
-struct zclient *zclient_new(struct thread_master *master,
+struct zclient *zclient_new(struct event_loop *master,
struct zclient_options *opt,
zclient_handler *const *handlers, size_t n_handlers)
{
@@ -174,9 +160,9 @@ void zclient_stop(struct zclient *zclient)
zlog_debug("zclient %p stopped", zclient);
/* Stop threads. */
- THREAD_OFF(zclient->t_read);
- THREAD_OFF(zclient->t_connect);
- THREAD_OFF(zclient->t_write);
+ EVENT_OFF(zclient->t_read);
+ EVENT_OFF(zclient->t_connect);
+ EVENT_OFF(zclient->t_write);
/* Reset streams. */
stream_reset(zclient->ibuf);
@@ -194,14 +180,14 @@ void zclient_stop(struct zclient *zclient)
for (afi = AFI_IP; afi < AFI_MAX; afi++) {
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
- vrf_bitmap_free(zclient->redist[afi][i]);
+ vrf_bitmap_free(&zclient->redist[afi][i]);
zclient->redist[afi][i] = VRF_BITMAP_NULL;
}
redist_del_instance(
&zclient->mi_redist[afi][zclient->redist_default],
zclient->instance);
- vrf_bitmap_free(zclient->default_information[afi]);
+ vrf_bitmap_free(&zclient->default_information[afi]);
zclient->default_information[afi] = VRF_BITMAP_NULL;
}
}
@@ -263,9 +249,9 @@ static enum zclient_send_status zclient_failed(struct zclient *zclient)
return ZCLIENT_SEND_FAILURE;
}
-static void zclient_flush_data(struct thread *thread)
+static void zclient_flush_data(struct event *thread)
{
- struct zclient *zclient = THREAD_ARG(thread);
+ struct zclient *zclient = EVENT_ARG(thread);
zclient->t_write = NULL;
if (zclient->sock < 0)
@@ -280,8 +266,8 @@ static void zclient_flush_data(struct thread *thread)
return;
case BUFFER_PENDING:
zclient->t_write = NULL;
- thread_add_write(zclient->master, zclient_flush_data, zclient,
- zclient->sock, &zclient->t_write);
+ event_add_write(zclient->master, zclient_flush_data, zclient,
+ zclient->sock, &zclient->t_write);
break;
case BUFFER_EMPTY:
if (zclient->zebra_buffer_write_ready)
@@ -309,11 +295,11 @@ enum zclient_send_status zclient_send_message(struct zclient *zclient)
__func__, zclient->sock);
return zclient_failed(zclient);
case BUFFER_EMPTY:
- THREAD_OFF(zclient->t_write);
+ EVENT_OFF(zclient->t_write);
return ZCLIENT_SEND_SUCCESS;
case BUFFER_PENDING:
- thread_add_write(zclient->master, zclient_flush_data, zclient,
- zclient->sock, &zclient->t_write);
+ event_add_write(zclient->master, zclient_flush_data, zclient,
+ zclient->sock, &zclient->t_write);
return ZCLIENT_SEND_BUFFERED;
}
@@ -441,13 +427,18 @@ enum zclient_send_status zclient_send_vrf_label(struct zclient *zclient,
}
enum zclient_send_status zclient_send_localsid(struct zclient *zclient,
- const struct in6_addr *sid, ifindex_t oif,
+ const struct in6_addr *sid, vrf_id_t vrf_id,
enum seg6local_action_t action,
const struct seg6local_context *context)
{
struct prefix_ipv6 p = {};
struct zapi_route api = {};
struct zapi_nexthop *znh;
+ struct interface *ifp;
+
+ ifp = if_get_vrf_loopback(vrf_id);
+ if (ifp == NULL)
+ return ZCLIENT_SEND_FAILURE;
p.family = AF_INET6;
p.prefixlen = IPV6_MAX_BITLEN;
@@ -470,7 +461,7 @@ enum zclient_send_status zclient_send_localsid(struct zclient *zclient,
memset(znh, 0, sizeof(*znh));
znh->type = NEXTHOP_TYPE_IFINDEX;
- znh->ifindex = oif;
+ znh->ifindex = ifp->ifindex;
SET_FLAG(znh->flags, ZAPI_NEXTHOP_FLAG_SEG6LOCAL);
znh->seg6local_action = action;
memcpy(&znh->seg6local_ctx, context, sizeof(struct seg6local_context));
@@ -503,7 +494,7 @@ void zclient_send_reg_requests(struct zclient *zclient, vrf_id_t vrf_id)
/* Set unwanted redistribute route. */
for (afi = AFI_IP; afi < AFI_MAX; afi++)
- vrf_bitmap_set(zclient->redist[afi][zclient->redist_default],
+ vrf_bitmap_set(&zclient->redist[afi][zclient->redist_default],
vrf_id);
/* Flush all redistribute request. */
@@ -533,15 +524,15 @@ void zclient_send_reg_requests(struct zclient *zclient, vrf_id_t vrf_id)
/* Resend all redistribute request. */
for (afi = AFI_IP; afi < AFI_MAX; afi++) {
for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
- if (i != zclient->redist_default
- && vrf_bitmap_check(zclient->redist[afi][i],
- vrf_id))
+ if (i != zclient->redist_default &&
+ vrf_bitmap_check(&zclient->redist[afi][i], vrf_id))
zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD,
zclient, afi, i, 0,
vrf_id);
/* If default information is needed. */
- if (vrf_bitmap_check(zclient->default_information[afi], vrf_id))
+ if (vrf_bitmap_check(&zclient->default_information[afi],
+ vrf_id))
zebra_redistribute_default_send(
ZEBRA_REDISTRIBUTE_DEFAULT_ADD, zclient, afi,
vrf_id);
@@ -570,7 +561,7 @@ void zclient_send_dereg_requests(struct zclient *zclient, vrf_id_t vrf_id)
/* Set unwanted redistribute route. */
for (afi = AFI_IP; afi < AFI_MAX; afi++)
- vrf_bitmap_unset(zclient->redist[afi][zclient->redist_default],
+ vrf_bitmap_unset(&zclient->redist[afi][zclient->redist_default],
vrf_id);
/* Flush all redistribute request. */
@@ -600,15 +591,15 @@ void zclient_send_dereg_requests(struct zclient *zclient, vrf_id_t vrf_id)
/* Flush all redistribute request. */
for (afi = AFI_IP; afi < AFI_MAX; afi++) {
for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
- if (i != zclient->redist_default
- && vrf_bitmap_check(zclient->redist[afi][i],
- vrf_id))
+ if (i != zclient->redist_default &&
+ vrf_bitmap_check(&zclient->redist[afi][i], vrf_id))
zebra_redistribute_send(
ZEBRA_REDISTRIBUTE_DELETE, zclient, afi,
i, 0, vrf_id);
/* If default information is needed. */
- if (vrf_bitmap_check(zclient->default_information[afi], vrf_id))
+ if (vrf_bitmap_check(&zclient->default_information[afi],
+ vrf_id))
zebra_redistribute_default_send(
ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, zclient, afi,
vrf_id);
@@ -735,7 +726,7 @@ void zclient_init(struct zclient *zclient, int redist_default,
/* Clear redistribution flags. */
for (afi = AFI_IP; afi < AFI_MAX; afi++)
for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
- zclient->redist[afi][i] = vrf_bitmap_init();
+ vrf_bitmap_init(&zclient->redist[afi][i]);
/* Set unwanted redistribute route. bgpd does not need BGP route
redistribution. */
@@ -747,7 +738,7 @@ void zclient_init(struct zclient *zclient, int redist_default,
instance);
/* Set default-information redistribute to zero. */
- zclient->default_information[afi] = vrf_bitmap_init();
+ vrf_bitmap_init(&zclient->default_information[afi]);
}
if (zclient_debug)
@@ -758,11 +749,11 @@ void zclient_init(struct zclient *zclient, int redist_default,
/* This function is a wrapper function for calling zclient_start from
timer or event thread. */
-static void zclient_connect(struct thread *t)
+static void zclient_connect(struct event *t)
{
struct zclient *zclient;
- zclient = THREAD_ARG(t);
+ zclient = EVENT_ARG(t);
zclient->t_connect = NULL;
if (zclient_debug)
@@ -1034,6 +1025,7 @@ int zapi_nexthop_encode(struct stream *s, const struct zapi_nexthop *api_nh,
*/
if (api_nh->label_num > 0) {
stream_putc(s, api_nh->label_num);
+ stream_putc(s, api_nh->label_type);
stream_put(s, &api_nh->labels[0],
api_nh->label_num * sizeof(mpls_label_t));
}
@@ -1088,6 +1080,7 @@ int zapi_srv6_locator_chunk_encode(struct stream *s,
stream_putc(s, c->node_bits_length);
stream_putc(s, c->function_bits_length);
stream_putc(s, c->argument_bits_length);
+ stream_putc(s, c->flags);
return 0;
}
@@ -1109,6 +1102,7 @@ int zapi_srv6_locator_chunk_decode(struct stream *s,
STREAM_GETC(s, c->node_bits_length);
STREAM_GETC(s, c->function_bits_length);
STREAM_GETC(s, c->argument_bits_length);
+ STREAM_GETC(s, c->flags);
return 0;
stream_failure:
@@ -1166,6 +1160,10 @@ static int zapi_nhg_encode(struct stream *s, int cmd, struct zapi_nhg *api_nhg)
stream_putw(s, api_nhg->proto);
stream_putl(s, api_nhg->id);
+ stream_putw(s, api_nhg->resilience.buckets);
+ stream_putl(s, api_nhg->resilience.idle_timer);
+ stream_putl(s, api_nhg->resilience.unbalanced_timer);
+
if (cmd == ZEBRA_NHG_ADD) {
/* Nexthops */
zapi_nexthop_group_sort(api_nhg->nexthops,
@@ -1390,6 +1388,7 @@ int zapi_nexthop_decode(struct stream *s, struct zapi_nexthop *api_nh,
/* MPLS labels for BGP-LU or Segment Routing */
if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_LABEL)) {
STREAM_GETC(s, api_nh->label_num);
+ STREAM_GETC(s, api_nh->label_type);
if (api_nh->label_num > MPLS_MAX_LABELS) {
flog_err(
EC_LIB_ZAPI_ENCODE,
@@ -1612,30 +1611,105 @@ static void zapi_encode_prefix(struct stream *s, struct prefix *p,
stream_put(s, &p->u.prefix, prefix_blen(p));
}
-int zapi_pbr_rule_encode(uint8_t cmd, struct stream *s, struct pbr_rule *zrule)
+static bool zapi_decode_prefix(struct stream *s, struct prefix *p)
{
- stream_reset(s);
- zclient_create_header(s, cmd, zrule->vrf_id);
+ STREAM_GETC(s, p->family);
+ STREAM_GETC(s, p->prefixlen);
+ STREAM_GET(&(p->u.prefix), s, prefix_blen(p));
+ return true;
+
+stream_failure:
+ return false;
+}
+/*
+ * Encode filter subsection of pbr_rule
+ */
+static void zapi_pbr_rule_filter_encode(struct stream *s, struct pbr_filter *f)
+{
+ assert(f->src_ip.family == f->dst_ip.family);
+ assert((f->src_ip.family == AF_INET) || (f->src_ip.family == AF_INET6));
+
+ stream_putl(s, f->filter_bm);
+ stream_putc(s, f->ip_proto);
+
+ /* addresses */
+ zapi_encode_prefix(s, &f->src_ip, f->src_ip.family);
+ zapi_encode_prefix(s, &f->dst_ip, f->dst_ip.family);
+
+ /* port numbers */
+ stream_putw(s, f->src_port);
+ stream_putw(s, f->dst_port);
+
+ /* vlan */
+ stream_putc(s, f->pcp);
+ stream_putw(s, f->vlan_id);
+ stream_putw(s, f->vlan_flags);
+
+ stream_putc(s, f->dsfield);
+ stream_putl(s, f->fwmark);
+}
+
+static bool zapi_pbr_rule_filter_decode(struct stream *s, struct pbr_filter *f)
+{
+ STREAM_GETL(s, f->filter_bm);
+ STREAM_GETC(s, f->ip_proto);
+ if (!zapi_decode_prefix(s, &(f->src_ip)))
+ goto stream_failure;
+ if (!zapi_decode_prefix(s, &(f->dst_ip)))
+ goto stream_failure;
+ STREAM_GETW(s, f->src_port);
+ STREAM_GETW(s, f->dst_port);
+ STREAM_GETC(s, f->pcp);
+ STREAM_GETW(s, f->vlan_id);
+ STREAM_GETW(s, f->vlan_flags);
+ STREAM_GETC(s, f->dsfield);
+ STREAM_GETL(s, f->fwmark);
+ return true;
+
+stream_failure:
+ return false;
+}
+
+static void zapi_pbr_rule_action_encode(struct stream *s, struct pbr_action *a)
+{
+ stream_putl(s, a->flags);
+ stream_putl(s, a->table);
+ stream_putl(s, a->queue_id);
+ stream_putc(s, a->pcp);
+ stream_putw(s, a->vlan_id);
+ stream_putw(s, a->vlan_flags);
+}
+
+static bool zapi_pbr_rule_action_decode(struct stream *s, struct pbr_action *a)
+{
+ STREAM_GETL(s, a->flags);
+ STREAM_GETL(s, a->table);
+ STREAM_GETL(s, a->queue_id);
+ STREAM_GETC(s, a->pcp);
+ STREAM_GETW(s, a->vlan_id);
+ STREAM_GETW(s, a->vlan_flags);
+ return true;
+
+stream_failure:
+ return false;
+}
+
+int zapi_pbr_rule_encode(struct stream *s, struct pbr_rule *r)
+{
/*
- * We are sending one item at a time at the moment
+ * PBR record count is always 1
*/
stream_putl(s, 1);
- stream_putl(s, zrule->seq);
- stream_putl(s, zrule->priority);
- stream_putl(s, zrule->unique);
+ stream_putl(s, r->seq);
+ stream_putl(s, r->priority);
+ stream_putl(s, r->unique);
- zapi_encode_prefix(s, &(zrule->filter.src_ip),
- zrule->filter.src_ip.family);
- stream_putw(s, zrule->filter.src_port); /* src port */
- zapi_encode_prefix(s, &(zrule->filter.dst_ip),
- zrule->filter.src_ip.family);
- stream_putw(s, zrule->filter.dst_port); /* dst port */
- stream_putw(s, zrule->filter.fwmark); /* fwmark */
+ zapi_pbr_rule_filter_encode(s, &(r->filter));
+ zapi_pbr_rule_action_encode(s, &(r->action));
- stream_putl(s, zrule->action.table);
- stream_put(s, zrule->ifname, INTERFACE_NAMSIZ);
+ stream_put(s, r->ifname, INTERFACE_NAMSIZ);
/* Put length at the first point of the stream. */
stream_putw_at(s, 0, stream_get_endp(s));
@@ -1643,6 +1717,122 @@ int zapi_pbr_rule_encode(uint8_t cmd, struct stream *s, struct pbr_rule *zrule)
return 0;
}
+bool zapi_pbr_rule_decode(struct stream *s, struct pbr_rule *r)
+{
+ /* NB caller has already read 4-byte rule count */
+
+ memset(r, 0, sizeof(*r));
+
+ STREAM_GETL(s, r->seq);
+ STREAM_GETL(s, r->priority);
+ STREAM_GETL(s, r->unique);
+
+ if (!zapi_pbr_rule_filter_decode(s, &(r->filter)))
+ goto stream_failure;
+ if (!zapi_pbr_rule_action_decode(s, &(r->action)))
+ goto stream_failure;
+
+ STREAM_GET(r->ifname, s, INTERFACE_NAMSIZ);
+ return true;
+
+stream_failure:
+ return false;
+}
+
+int zapi_tc_qdisc_encode(uint8_t cmd, struct stream *s, struct tc_qdisc *qdisc)
+{
+ stream_reset(s);
+ zclient_create_header(s, cmd, VRF_DEFAULT);
+
+
+ stream_putl(s, 1);
+
+ stream_putl(s, qdisc->ifindex);
+ stream_putl(s, qdisc->kind);
+
+ stream_putw_at(s, 0, stream_get_endp(s));
+
+ return 0;
+}
+
+int zapi_tc_class_encode(uint8_t cmd, struct stream *s, struct tc_class *class)
+{
+ stream_reset(s);
+ zclient_create_header(s, cmd, VRF_DEFAULT);
+
+ stream_putl(s, 1);
+
+ stream_putl(s, class->ifindex);
+ stream_putl(s, class->handle);
+ stream_putl(s, class->kind);
+
+ switch (class->kind) {
+ case TC_QDISC_HTB:
+ stream_putq(s, class->u.htb.rate);
+ stream_putq(s, class->u.htb.ceil);
+ break;
+ case TC_QDISC_UNSPEC:
+ case TC_QDISC_NOQUEUE:
+ /* not implemented */
+ break;
+ }
+ stream_putw_at(s, 0, stream_get_endp(s));
+
+ return 0;
+}
+
+int zapi_tc_filter_encode(uint8_t cmd, struct stream *s,
+ struct tc_filter *filter)
+{
+ stream_reset(s);
+ zclient_create_header(s, cmd, VRF_DEFAULT);
+
+ stream_putl(s, 1);
+
+ stream_putl(s, filter->ifindex);
+ stream_putl(s, filter->handle);
+ stream_putl(s, filter->priority);
+ stream_putl(s, filter->protocol);
+ stream_putl(s, filter->kind);
+
+ switch (filter->kind) {
+ case TC_FILTER_FLOWER:
+ stream_putl(s, filter->u.flower.filter_bm);
+ if (filter->u.flower.filter_bm & TC_FLOWER_IP_PROTOCOL)
+ stream_putc(s, filter->u.flower.ip_proto);
+ if (filter->u.flower.filter_bm & TC_FLOWER_SRC_IP)
+ zapi_encode_prefix(s, &filter->u.flower.src_ip,
+ filter->u.flower.src_ip.family);
+ if (filter->u.flower.filter_bm & TC_FLOWER_SRC_PORT) {
+ stream_putw(s, filter->u.flower.src_port_min);
+ stream_putw(s, filter->u.flower.src_port_max);
+ }
+ if (filter->u.flower.filter_bm & TC_FLOWER_DST_IP)
+ zapi_encode_prefix(s, &filter->u.flower.dst_ip,
+ filter->u.flower.dst_ip.family);
+ if (filter->u.flower.filter_bm & TC_FLOWER_DST_PORT) {
+ stream_putw(s, filter->u.flower.dst_port_min);
+ stream_putw(s, filter->u.flower.dst_port_max);
+ }
+ if (filter->u.flower.filter_bm & TC_FLOWER_DSFIELD) {
+ stream_putc(s, filter->u.flower.dsfield);
+ stream_putc(s, filter->u.flower.dsfield_mask);
+ }
+ stream_putl(s, filter->u.flower.classid);
+ break;
+ case TC_FILTER_UNSPEC:
+ case TC_FILTER_BPF:
+ case TC_FILTER_FLOW:
+ case TC_FILTER_U32:
+ /* not implemented */
+ break;
+ }
+
+ stream_putw_at(s, 0, stream_get_endp(s));
+
+ return 0;
+}
+
bool zapi_nhg_notify_decode(struct stream *s, uint32_t *id,
enum zapi_nhg_notify_owner *note)
{
@@ -1847,6 +2037,7 @@ int zapi_nexthop_from_nexthop(struct zapi_nexthop *znh,
znh->labels[i] = nh->nh_label->label[i];
znh->label_num = i;
+ znh->label_type = nh->nh_label_type;
SET_FLAG(znh->flags, ZAPI_NEXTHOP_FLAG_LABEL);
}
@@ -2299,13 +2490,22 @@ static int zclient_handle_error(ZAPI_CALLBACK_ARGS)
return 0;
}
-static int link_params_set_value(struct stream *s, struct if_link_params *iflp)
+static int link_params_set_value(struct stream *s, struct interface *ifp)
{
+ uint8_t link_params_enabled, nb_ext_adm_grp;
+ struct if_link_params *iflp;
+ uint32_t bwclassnum, bitmap_data;
+
+ iflp = if_link_params_get(ifp);
if (iflp == NULL)
- return -1;
+ iflp = if_link_params_init(ifp);
- uint32_t bwclassnum;
+ STREAM_GETC(s, link_params_enabled);
+ if (!link_params_enabled) {
+ if_link_params_free(ifp);
+ return 0;
+ }
STREAM_GETL(s, iflp->lp_status);
STREAM_GETL(s, iflp->te_metric);
@@ -2323,6 +2523,15 @@ static int link_params_set_value(struct stream *s, struct if_link_params *iflp)
__func__, bwclassnum, MAX_CLASS_TYPE);
}
STREAM_GETL(s, iflp->admin_grp);
+
+ /* Extended Administrative Group */
+ admin_group_clear(&iflp->ext_admin_grp);
+ STREAM_GETC(s, nb_ext_adm_grp);
+ for (size_t i = 0; i < nb_ext_adm_grp; i++) {
+ STREAM_GETL(s, bitmap_data);
+ admin_group_bulk_set(&iflp->ext_admin_grp, bitmap_data, i);
+ }
+
STREAM_GETL(s, iflp->rmt_as);
iflp->rmt_ip.s_addr = stream_get_ipv4(s);
@@ -2346,9 +2555,9 @@ struct interface *zebra_interface_link_params_read(struct stream *s,
bool *changed)
{
struct if_link_params *iflp;
- struct if_link_params iflp_copy;
+ struct if_link_params iflp_prev = {0};
ifindex_t ifindex;
- bool params_changed = false;
+ bool iflp_prev_set = false;
STREAM_GETL(s, ifindex);
@@ -2361,26 +2570,43 @@ struct interface *zebra_interface_link_params_read(struct stream *s,
return NULL;
}
- if (ifp->link_params == NULL)
- params_changed = true;
+ iflp = if_link_params_get(ifp);
- if ((iflp = if_link_params_get(ifp)) == NULL)
- return NULL;
-
- memcpy(&iflp_copy, iflp, sizeof(iflp_copy));
+ if (iflp) {
+ iflp_prev_set = true;
+ admin_group_init(&iflp_prev.ext_admin_grp);
+ if_link_params_copy(&iflp_prev, iflp);
+ }
- if (link_params_set_value(s, iflp) != 0)
+ /* read the link_params from stream
+ * Free ifp->link_params if the stream has no params
+ * to means that link-params are not enabled on links.
+ */
+ if (link_params_set_value(s, ifp) != 0)
goto stream_failure;
- if (memcmp(&iflp_copy, iflp, sizeof(iflp_copy)))
- params_changed = true;
+ if (changed != NULL) {
+ iflp = if_link_params_get(ifp);
- if (changed)
- *changed = params_changed;
+ if (iflp_prev_set && iflp) {
+ if (if_link_params_cmp(&iflp_prev, iflp))
+ *changed = false;
+ else
+ *changed = true;
+ } else if (!iflp_prev_set && !iflp)
+ *changed = false;
+ else
+ *changed = true;
+ }
+
+ if (iflp_prev_set)
+ admin_group_term(&iflp_prev.ext_admin_grp);
return ifp;
stream_failure:
+ if (iflp_prev_set)
+ admin_group_term(&iflp_prev.ext_admin_grp);
return NULL;
}
@@ -2415,10 +2641,8 @@ static void zebra_interface_if_set_value(struct stream *s,
/* Read Traffic Engineering status */
link_params_status = stream_getc(s);
/* Then, Traffic Engineering parameters if any */
- if (link_params_status) {
- struct if_link_params *iflp = if_link_params_get(ifp);
- link_params_set_value(s, iflp);
- }
+ if (link_params_status)
+ link_params_set_value(s, ifp);
nexthop_group_interface_state_change(ifp, old_ifindex);
@@ -2431,16 +2655,25 @@ stream_failure:
size_t zebra_interface_link_params_write(struct stream *s,
struct interface *ifp)
{
- size_t w;
+ size_t w, nb_ext_adm_grp;
struct if_link_params *iflp;
int i;
- if (s == NULL || ifp == NULL || ifp->link_params == NULL)
+
+ if (s == NULL || ifp == NULL)
return 0;
iflp = ifp->link_params;
w = 0;
+ /* encode if link_params is enabled */
+ if (iflp) {
+ w += stream_putc(s, true);
+ } else {
+ w += stream_putc(s, false);
+ return w;
+ }
+
w += stream_putl(s, iflp->lp_status);
w += stream_putl(s, iflp->te_metric);
@@ -2452,6 +2685,13 @@ size_t zebra_interface_link_params_write(struct stream *s,
w += stream_putf(s, iflp->unrsv_bw[i]);
w += stream_putl(s, iflp->admin_grp);
+
+ /* Extended Administrative Group */
+ nb_ext_adm_grp = admin_group_nb_words(&iflp->ext_admin_grp);
+ w += stream_putc(s, nb_ext_adm_grp);
+ for (size_t i = 0; i < nb_ext_adm_grp; i++)
+ stream_putl(s, admin_group_get_offset(&iflp->ext_admin_grp, i));
+
w += stream_putl(s, iflp->rmt_as);
w += stream_put_in_addr(s, &iflp->rmt_ip);
@@ -3681,6 +3921,53 @@ enum zclient_send_status zclient_send_mlag_data(struct zclient *client,
}
/*
+ * Init/header setup for opaque zapi messages
+ */
+enum zclient_send_status zapi_opaque_init(struct zclient *zclient,
+ uint32_t type, uint16_t flags)
+{
+ struct stream *s;
+
+ s = zclient->obuf;
+ stream_reset(s);
+
+ zclient_create_header(s, ZEBRA_OPAQUE_MESSAGE, VRF_DEFAULT);
+
+ /* Send sub-type and flags */
+ stream_putl(s, type);
+ stream_putw(s, flags);
+
+ /* Source daemon identifiers */
+ stream_putc(s, zclient->redist_default);
+ stream_putw(s, zclient->instance);
+ stream_putl(s, zclient->session_id);
+
+ return ZCLIENT_SEND_SUCCESS;
+}
+
+/*
+ * Init, header setup for opaque unicast messages.
+ */
+enum zclient_send_status
+zapi_opaque_unicast_init(struct zclient *zclient, uint32_t type, uint16_t flags,
+ uint8_t proto, uint16_t instance, uint32_t session_id)
+{
+ struct stream *s;
+
+ s = zclient->obuf;
+
+ /* Common init */
+ zapi_opaque_init(zclient, type, flags | ZAPI_OPAQUE_FLAG_UNICAST);
+
+ /* Send destination client info */
+ stream_putc(s, proto);
+ stream_putw(s, instance);
+ stream_putl(s, session_id);
+
+ return ZCLIENT_SEND_SUCCESS;
+}
+
+/*
* Send an OPAQUE message, contents opaque to zebra. The message header
* is a message subtype.
*/
@@ -3697,16 +3984,12 @@ enum zclient_send_status zclient_send_opaque(struct zclient *zclient,
return ZCLIENT_SEND_FAILURE;
s = zclient->obuf;
- stream_reset(s);
- zclient_create_header(s, ZEBRA_OPAQUE_MESSAGE, VRF_DEFAULT);
-
- /* Send sub-type and flags */
- stream_putl(s, type);
- stream_putw(s, flags);
+ zapi_opaque_init(zclient, type, flags);
/* Send opaque data */
- stream_write(s, data, datasize);
+ if (datasize > 0)
+ stream_write(s, data, datasize);
/* Put length into the header at the start of the stream. */
stream_putw_at(s, 0, stream_get_endp(s));
@@ -3733,22 +4016,14 @@ zclient_send_opaque_unicast(struct zclient *zclient, uint32_t type,
return ZCLIENT_SEND_FAILURE;
s = zclient->obuf;
- stream_reset(s);
-
- zclient_create_header(s, ZEBRA_OPAQUE_MESSAGE, VRF_DEFAULT);
-
- /* Send sub-type and flags */
- SET_FLAG(flags, ZAPI_OPAQUE_FLAG_UNICAST);
- stream_putl(s, type);
- stream_putw(s, flags);
- /* Send destination client info */
- stream_putc(s, proto);
- stream_putw(s, instance);
- stream_putl(s, session_id);
+ /* Common init */
+ zapi_opaque_unicast_init(zclient, type, flags, proto, instance,
+ session_id);
/* Send opaque data */
- stream_write(s, data, datasize);
+ if (datasize > 0)
+ stream_write(s, data, datasize);
/* Put length into the header at the start of the stream. */
stream_putw_at(s, 0, stream_get_endp(s));
@@ -3767,11 +4042,16 @@ int zclient_opaque_decode(struct stream *s, struct zapi_opaque_msg *info)
STREAM_GETL(s, info->type);
STREAM_GETW(s, info->flags);
- /* Decode unicast client info if present */
+ /* Decode sending daemon info */
+ STREAM_GETC(s, info->src_proto);
+ STREAM_GETW(s, info->src_instance);
+ STREAM_GETL(s, info->src_session_id);
+
+ /* Decode unicast destination info, if present */
if (CHECK_FLAG(info->flags, ZAPI_OPAQUE_FLAG_UNICAST)) {
- STREAM_GETC(s, info->proto);
- STREAM_GETW(s, info->instance);
- STREAM_GETL(s, info->session_id);
+ STREAM_GETC(s, info->dest_proto);
+ STREAM_GETW(s, info->dest_instance);
+ STREAM_GETL(s, info->dest_session_id);
}
info->len = STREAM_READABLE(s);
@@ -3888,7 +4168,7 @@ static zclient_handler *const lib_handlers[] = {
};
/* Zebra client message read function. */
-static void zclient_read(struct thread *thread)
+static void zclient_read(struct event *thread)
{
size_t already;
uint16_t length, command;
@@ -3897,7 +4177,7 @@ static void zclient_read(struct thread *thread)
struct zclient *zclient;
/* Get socket to zebra. */
- zclient = THREAD_ARG(thread);
+ zclient = EVENT_ARG(thread);
zclient->t_read = NULL;
/* Read zebra header (if we don't have it already). */
@@ -4025,15 +4305,15 @@ void zclient_redistribute(int command, struct zclient *zclient, afi_t afi,
} else {
if (command == ZEBRA_REDISTRIBUTE_ADD) {
- if (vrf_bitmap_check(zclient->redist[afi][type],
+ if (vrf_bitmap_check(&zclient->redist[afi][type],
vrf_id))
return;
- vrf_bitmap_set(zclient->redist[afi][type], vrf_id);
+ vrf_bitmap_set(&zclient->redist[afi][type], vrf_id);
} else {
- if (!vrf_bitmap_check(zclient->redist[afi][type],
+ if (!vrf_bitmap_check(&zclient->redist[afi][type],
vrf_id))
return;
- vrf_bitmap_unset(zclient->redist[afi][type], vrf_id);
+ vrf_bitmap_unset(&zclient->redist[afi][type], vrf_id);
}
}
@@ -4048,14 +4328,15 @@ void zclient_redistribute_default(int command, struct zclient *zclient,
{
if (command == ZEBRA_REDISTRIBUTE_DEFAULT_ADD) {
- if (vrf_bitmap_check(zclient->default_information[afi], vrf_id))
+ if (vrf_bitmap_check(&zclient->default_information[afi],
+ vrf_id))
return;
- vrf_bitmap_set(zclient->default_information[afi], vrf_id);
+ vrf_bitmap_set(&zclient->default_information[afi], vrf_id);
} else {
- if (!vrf_bitmap_check(zclient->default_information[afi],
+ if (!vrf_bitmap_check(&zclient->default_information[afi],
vrf_id))
return;
- vrf_bitmap_unset(zclient->default_information[afi], vrf_id);
+ vrf_bitmap_unset(&zclient->default_information[afi], vrf_id);
}
if (zclient->sock > 0)
@@ -4066,22 +4347,22 @@ static void zclient_event(enum zclient_event event, struct zclient *zclient)
{
switch (event) {
case ZCLIENT_SCHEDULE:
- thread_add_event(zclient->master, zclient_connect, zclient, 0,
- &zclient->t_connect);
+ event_add_event(zclient->master, zclient_connect, zclient, 0,
+ &zclient->t_connect);
break;
case ZCLIENT_CONNECT:
if (zclient_debug)
zlog_debug(
"zclient connect failures: %d schedule interval is now %d",
zclient->fail, zclient->fail < 3 ? 10 : 60);
- thread_add_timer(zclient->master, zclient_connect, zclient,
- zclient->fail < 3 ? 10 : 60,
- &zclient->t_connect);
+ event_add_timer(zclient->master, zclient_connect, zclient,
+ zclient->fail < 3 ? 10 : 60,
+ &zclient->t_connect);
break;
case ZCLIENT_READ:
zclient->t_read = NULL;
- thread_add_read(zclient->master, zclient_read, zclient,
- zclient->sock, &zclient->t_read);
+ event_add_read(zclient->master, zclient_read, zclient,
+ zclient->sock, &zclient->t_read);
break;
}
}
@@ -4156,6 +4437,8 @@ int32_t zapi_capabilities_decode(struct stream *s, struct zapi_cap *api)
memset(api, 0, sizeof(*api));
+ api->safi = SAFI_UNICAST;
+
STREAM_GETL(s, api->cap);
switch (api->cap) {
case ZEBRA_CLIENT_GR_CAPABILITIES:
@@ -4327,3 +4610,125 @@ int zclient_send_zebra_gre_request(struct zclient *client,
zclient_send_message(client);
return 0;
}
+
+
+/*
+ * Opaque notification features
+ */
+
+/*
+ * Common encode helper for opaque notifications, both registration
+ * and async notification messages.
+ */
+static int opaque_notif_encode_common(struct stream *s, uint32_t msg_type,
+ bool request, bool reg, uint8_t proto,
+ uint16_t instance, uint32_t session_id)
+{
+ int ret = 0;
+ uint8_t val = 0;
+
+ stream_reset(s);
+
+ zclient_create_header(s, ZEBRA_OPAQUE_NOTIFY, VRF_DEFAULT);
+
+ /* Notification or request */
+ if (request)
+ val = 1;
+ stream_putc(s, val);
+
+ if (reg)
+ val = 1;
+ else
+ val = 0;
+ stream_putc(s, val);
+
+ stream_putl(s, msg_type);
+
+ stream_putc(s, proto);
+ stream_putw(s, instance);
+ stream_putl(s, session_id);
+
+ /* And capture message length */
+ stream_putw_at(s, 0, stream_get_endp(s));
+
+ return ret;
+}
+
+/*
+ * Encode a zapi opaque message type notification into buffer 's'
+ */
+int zclient_opaque_notif_encode(struct stream *s, uint32_t msg_type, bool reg,
+ uint8_t proto, uint16_t instance,
+ uint32_t session_id)
+{
+ return opaque_notif_encode_common(s, msg_type, false /* !request */,
+ reg, proto, instance, session_id);
+}
+
+/*
+ * Decode an incoming zapi opaque message type notification
+ */
+int zclient_opaque_notif_decode(struct stream *s,
+ struct zapi_opaque_notif_info *info)
+{
+ uint8_t val;
+
+ memset(info, 0, sizeof(*info));
+
+ STREAM_GETC(s, val); /* Registration or notification */
+ info->request = (val != 0);
+
+ STREAM_GETC(s, val);
+ info->reg = (val != 0);
+
+ STREAM_GETL(s, info->msg_type);
+
+ STREAM_GETC(s, info->proto);
+ STREAM_GETW(s, info->instance);
+ STREAM_GETL(s, info->session_id);
+
+ return 0;
+
+stream_failure:
+ return -1;
+}
+
+/*
+ * Encode and send a zapi opaque message type notification request to zebra
+ */
+enum zclient_send_status zclient_opaque_request_notify(struct zclient *zclient,
+ uint32_t msgtype)
+{
+ struct stream *s;
+
+ if (!zclient || zclient->sock < 0)
+ return ZCLIENT_SEND_FAILURE;
+
+ s = zclient->obuf;
+
+ opaque_notif_encode_common(s, msgtype, true /* request */,
+ true /* register */, zclient->redist_default,
+ zclient->instance, zclient->session_id);
+
+ return zclient_send_message(zclient);
+}
+
+/*
+ * Encode and send a request to drop notifications for an opaque message type.
+ */
+enum zclient_send_status zclient_opaque_drop_notify(struct zclient *zclient,
+ uint32_t msgtype)
+{
+ struct stream *s;
+
+ if (!zclient || zclient->sock < 0)
+ return ZCLIENT_SEND_FAILURE;
+
+ s = zclient->obuf;
+
+ opaque_notif_encode_common(s, msgtype, true /* req */,
+ false /* unreg */, zclient->redist_default,
+ zclient->instance, zclient->session_id);
+
+ return zclient_send_message(zclient);
+}