summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/command.c41
-rw-r--r--lib/command.h3
-rw-r--r--lib/ferr.c8
-rw-r--r--lib/filter.c56
-rw-r--r--lib/if.c23
-rw-r--r--lib/if.h41
-rw-r--r--lib/json.c24
-rw-r--r--lib/json.h48
-rw-r--r--lib/link_state.c12
-rw-r--r--lib/log_vty.c23
-rw-r--r--lib/nexthop_group.c17
-rw-r--r--lib/northbound.c3
-rw-r--r--lib/northbound_confd.c91
-rw-r--r--lib/plist.c21
-rw-r--r--lib/routemap.c122
-rw-r--r--lib/routemap.h86
-rw-r--r--lib/routemap_cli.c21
-rw-r--r--lib/routemap_northbound.c20
-rw-r--r--lib/srv6.c8
-rw-r--r--lib/vrf.c7
-rw-r--r--lib/vrf.h2
-rw-r--r--lib/vty.c16
-rw-r--r--lib/vty.h8
-rw-r--r--lib/zclient.c15
24 files changed, 442 insertions, 274 deletions
diff --git a/lib/command.c b/lib/command.c
index ea66a17bb0..9cf93ea192 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -145,31 +145,6 @@ static struct cmd_node config_node = {
.node_exit = vty_config_node_exit,
};
-static bool vty_check_node_for_xpath_decrement(enum node_type target_node,
- enum node_type node)
-{
- /* bgp afi-safi (`address-family <afi> <safi>`) node
- * does not increment xpath_index.
- * In order to use (`router bgp`) BGP_NODE's xpath as a base,
- * retain xpath_index as 1 upon exiting from
- * afi-safi node.
- */
-
- if (target_node == BGP_NODE
- && (node == BGP_IPV4_NODE || node == BGP_IPV6_NODE
- || node == BGP_IPV4M_NODE || node == BGP_IPV6M_NODE
- || node == BGP_VPNV4_NODE || node == BGP_VPNV6_NODE
- || node == BGP_EVPN_NODE || node == BGP_IPV4L_NODE
- || node == BGP_IPV6L_NODE || node == BGP_FLOWSPECV4_NODE
- || node == BGP_FLOWSPECV6_NODE))
- return false;
-
- if (target_node == INTERFACE_NODE && node == LINK_PARAMS_NODE)
- return false;
-
- return true;
-}
-
/* This is called from main when a daemon is invoked with -v or --version. */
void print_version(const char *progname)
{
@@ -922,13 +897,15 @@ static int cmd_execute_command_real(vector vline, enum cmd_filter_type filter,
* a match before calling node_exit handlers below
*/
for (i = 0; i < up_level; i++) {
+ struct cmd_node *cnode;
+
if (node <= CONFIG_NODE)
return CMD_NO_LEVEL_UP;
+ cnode = vector_slot(cmdvec, node);
node = node_parent(node);
- if (xpath_index > 0
- && vty_check_node_for_xpath_decrement(node, vty->node))
+ if (xpath_index > 0 && !cnode->no_xpath)
xpath_index--;
}
@@ -1062,12 +1039,13 @@ int cmd_execute_command(vector vline, struct vty *vty,
/* This assumes all nodes above CONFIG_NODE are childs of
* CONFIG_NODE */
while (vty->node > CONFIG_NODE) {
+ struct cmd_node *cnode = vector_slot(cmdvec, try_node);
+
try_node = node_parent(try_node);
vty->node = try_node;
- if (vty->xpath_index > 0
- && vty_check_node_for_xpath_decrement(try_node,
- onode))
+ if (vty->xpath_index > 0 && !cnode->no_xpath)
vty->xpath_index--;
+
ret = cmd_execute_command_real(vline, FILTER_RELAXED,
vty, cmd, 0);
if (ret == CMD_SUCCESS || ret == CMD_WARNING
@@ -1386,8 +1364,7 @@ void cmd_exit(struct vty *vty)
}
if (cnode->parent_node)
vty->node = cnode->parent_node;
- if (vty->xpath_index > 0
- && vty_check_node_for_xpath_decrement(vty->node, cnode->node))
+ if (vty->xpath_index > 0 && !cnode->no_xpath)
vty->xpath_index--;
}
diff --git a/lib/command.h b/lib/command.h
index e2086701ad..c888356d61 100644
--- a/lib/command.h
+++ b/lib/command.h
@@ -213,6 +213,9 @@ struct cmd_node {
/* set as soon as any command is in cmdgraph */
bool graph_built;
+
+ /* don't decrement vty->xpath_index on leaving this node */
+ bool no_xpath;
};
/* Return value of the commands. */
diff --git a/lib/ferr.c b/lib/ferr.c
index 513ef5ebec..e5b6d7552d 100644
--- a/lib/ferr.c
+++ b/lib/ferr.c
@@ -157,13 +157,7 @@ void log_ref_display(struct vty *vty, uint32_t code, bool json)
}
}
- if (json) {
- const char *str = json_object_to_json_string_ext(
- top, JSON_C_TO_STRING_PRETTY);
- vty_out(vty, "%s\n", str);
- json_object_free(top);
- }
-
+ vty_json(vty, top);
list_delete(&errlist);
}
diff --git a/lib/filter.c b/lib/filter.c
index 9c80808fe8..fc4b578e77 100644
--- a/lib/filter.c
+++ b/lib/filter.c
@@ -558,18 +558,12 @@ static int filter_show(struct vty *vty, const char *name, afi_t afi,
json_rule);
else {
if (json) {
- char buf[BUFSIZ];
-
- json_object_string_add(
- json_rule, "address",
- inet_ntop(AF_INET,
- &filter->addr, buf,
- sizeof(buf)));
- json_object_string_add(
- json_rule, "mask",
- inet_ntop(AF_INET,
- &filter->addr_mask,
- buf, sizeof(buf)));
+ json_object_string_addf(
+ json_rule, "address", "%pI4",
+ &filter->addr);
+ json_object_string_addf(
+ json_rule, "mask", "%pI4",
+ &filter->addr_mask);
} else {
if (filter->addr_mask.s_addr
== 0xffffffff)
@@ -589,14 +583,7 @@ static int filter_show(struct vty *vty, const char *name, afi_t afi,
}
}
- if (json) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
-
- return CMD_SUCCESS;
+ return vty_json(vty, json);
}
/* show MAC access list - this only has MAC filters for now*/
@@ -681,21 +668,15 @@ static void config_write_access_cisco(struct vty *vty, struct filter *mfilter,
filter = &mfilter->u.cfilter;
if (json) {
- char buf[BUFSIZ];
-
json_object_boolean_add(json, "extended", !!filter->extended);
- json_object_string_add(
- json, "sourceAddress",
- inet_ntop(AF_INET, &filter->addr, buf, sizeof(buf)));
- json_object_string_add(json, "sourceMask",
- inet_ntop(AF_INET, &filter->addr_mask,
- buf, sizeof(buf)));
- json_object_string_add(
- json, "destinationAddress",
- inet_ntop(AF_INET, &filter->mask, buf, sizeof(buf)));
- json_object_string_add(json, "destinationMask",
- inet_ntop(AF_INET, &filter->mask_mask,
- buf, sizeof(buf)));
+ json_object_string_addf(json, "sourceAddress", "%pI4",
+ &filter->addr);
+ json_object_string_addf(json, "sourceMask", "%pI4",
+ &filter->addr_mask);
+ json_object_string_addf(json, "destinationAddress", "%pI4",
+ &filter->mask);
+ json_object_string_addf(json, "destinationMask", "%pI4",
+ &filter->mask_mask);
} else {
vty_out(vty, " ip");
if (filter->addr_mask.s_addr == 0xffffffff)
@@ -730,16 +711,13 @@ static void config_write_access_zebra(struct vty *vty, struct filter *mfilter,
p = &filter->prefix;
if (json) {
- json_object_string_add(json, "prefix",
- prefix2str(p, buf, sizeof(buf)));
+ json_object_string_addf(json, "prefix", "%pFX", p);
json_object_boolean_add(json, "exact-match", !!filter->exact);
} else {
if (p->prefixlen == 0 && !filter->exact)
vty_out(vty, " any");
else if (p->family == AF_INET6 || p->family == AF_INET)
- vty_out(vty, " %s/%d%s",
- inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
- p->prefixlen,
+ vty_out(vty, " %pFX%s", p,
filter->exact ? " exact-match" : "");
else if (p->family == AF_ETHERNET) {
if (p->prefixlen == 0)
diff --git a/lib/if.c b/lib/if.c
index 6bfbdf9147..fe1d3ebb4a 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -167,7 +167,6 @@ static struct interface *if_new(struct vrf *vrf)
ifp->name[0] = '\0';
ifp->vrf = vrf;
- ifp->vrf_id = vrf->vrf_id;
ifp->connected = list_new();
ifp->connected->del = ifp_connected_free;
@@ -238,8 +237,7 @@ void if_update_to_new_vrf(struct interface *ifp, vrf_id_t vrf_id)
if (ifp->ifindex != IFINDEX_INTERNAL)
IFINDEX_RB_REMOVE(old_vrf, ifp);
- ifp->vrf_id = vrf_id;
- vrf = vrf_get(ifp->vrf_id, NULL);
+ vrf = vrf_get(vrf_id, NULL);
ifp->vrf = vrf;
if (ifp->name[0] != '\0')
@@ -604,7 +602,7 @@ struct interface *if_get_by_name(const char *name, vrf_id_t vrf_id,
/* If it came from the kernel or by way of zclient,
* believe it and update the ifp accordingly.
*/
- if (ifp->vrf_id != vrf_id && vrf_id != VRF_UNKNOWN)
+ if (ifp->vrf->vrf_id != vrf_id && vrf_id != VRF_UNKNOWN)
if_update_to_new_vrf(ifp, vrf_id);
return ifp;
@@ -617,7 +615,7 @@ struct interface *if_get_by_name(const char *name, vrf_id_t vrf_id,
/* If it came from the kernel or by way of zclient,
* believe it and update the ifp accordingly.
*/
- if (ifp->vrf_id != vrf_id && vrf_id != VRF_UNKNOWN)
+ if (ifp->vrf->vrf_id != vrf_id && vrf_id != VRF_UNKNOWN)
if_update_to_new_vrf(ifp, vrf_id);
return ifp;
@@ -643,7 +641,7 @@ int if_set_index(struct interface *ifp, ifindex_t ifindex)
* If there is already an interface with this ifindex, we will collide
* on insertion, so don't even try.
*/
- if (if_lookup_by_ifindex(ifindex, ifp->vrf_id))
+ if (if_lookup_by_ifindex(ifindex, ifp->vrf->vrf_id))
return -1;
if (ifp->ifindex != IFINDEX_INTERNAL)
@@ -713,7 +711,7 @@ int if_is_no_ptm_operative(const struct interface *ifp)
}
/* Is this loopback interface ? */
-int if_is_loopback(const struct interface *ifp)
+int if_is_loopback_exact(const struct interface *ifp)
{
/* XXX: Do this better, eg what if IFF_WHATEVER means X on platform M
* but Y on platform N?
@@ -727,9 +725,10 @@ int if_is_vrf(const struct interface *ifp)
return CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK);
}
-bool if_is_loopback_or_vrf(const struct interface *ifp)
+/* Should this interface be treated as a loopback? */
+bool if_is_loopback(const struct interface *ifp)
{
- if (if_is_loopback(ifp) || if_is_vrf(ifp))
+ if (if_is_loopback_exact(ifp) || if_is_vrf(ifp))
return true;
return false;
@@ -806,8 +805,8 @@ static void if_dump(const struct interface *ifp)
for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, c))
zlog_info(
"Interface %s vrf %s(%u) index %d metric %d mtu %d mtu6 %d %s",
- ifp->name, ifp->vrf->name, ifp->vrf_id, ifp->ifindex,
- ifp->metric, ifp->mtu, ifp->mtu6,
+ ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
+ ifp->ifindex, ifp->metric, ifp->mtu, ifp->mtu6,
if_flag_dump(ifp->flags));
}
@@ -884,7 +883,7 @@ connected_log(struct connected *connected, char *str)
p = connected->address;
snprintf(logbuf, sizeof(logbuf), "%s interface %s vrf %s(%u) %s %pFX ",
- str, ifp->name, ifp->vrf->name, ifp->vrf_id,
+ str, ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
prefix_family_str(p), p);
p = connected->destination;
diff --git a/lib/if.h b/lib/if.h
index 5f0dc27555..c8f4d9ab9d 100644
--- a/lib/if.h
+++ b/lib/if.h
@@ -295,7 +295,6 @@ struct interface {
struct route_node *node;
struct vrf *vrf;
- vrf_id_t vrf_id;
/*
* Has the end users entered `interface XXXX` from the cli in some
@@ -312,56 +311,56 @@ RB_HEAD(if_index_head, interface);
RB_PROTOTYPE(if_index_head, interface, index_entry, if_cmp_index_func)
DECLARE_QOBJ_TYPE(interface);
-#define IFNAME_RB_INSERT(vrf, ifp) \
+#define IFNAME_RB_INSERT(v, ifp) \
({ \
struct interface *_iz = \
- RB_INSERT(if_name_head, &vrf->ifaces_by_name, (ifp)); \
+ RB_INSERT(if_name_head, &v->ifaces_by_name, (ifp)); \
if (_iz) \
flog_err( \
EC_LIB_INTERFACE, \
"%s(%s): corruption detected -- interface with this " \
- "name exists already in VRF %u!", \
- __func__, (ifp)->name, (ifp)->vrf_id); \
+ "name exists already in VRF %s!", \
+ __func__, (ifp)->name, (ifp)->vrf->name); \
_iz; \
})
-#define IFNAME_RB_REMOVE(vrf, ifp) \
+#define IFNAME_RB_REMOVE(v, ifp) \
({ \
struct interface *_iz = \
- RB_REMOVE(if_name_head, &vrf->ifaces_by_name, (ifp)); \
+ RB_REMOVE(if_name_head, &v->ifaces_by_name, (ifp)); \
if (_iz == NULL) \
flog_err( \
EC_LIB_INTERFACE, \
"%s(%s): corruption detected -- interface with this " \
- "name doesn't exist in VRF %u!", \
- __func__, (ifp)->name, (ifp)->vrf_id); \
+ "name doesn't exist in VRF %s!", \
+ __func__, (ifp)->name, (ifp)->vrf->name); \
_iz; \
})
-#define IFINDEX_RB_INSERT(vrf, ifp) \
+#define IFINDEX_RB_INSERT(v, ifp) \
({ \
- struct interface *_iz = RB_INSERT( \
- if_index_head, &vrf->ifaces_by_index, (ifp)); \
+ struct interface *_iz = \
+ RB_INSERT(if_index_head, &v->ifaces_by_index, (ifp)); \
if (_iz) \
flog_err( \
EC_LIB_INTERFACE, \
"%s(%u): corruption detected -- interface with this " \
- "ifindex exists already in VRF %u!", \
- __func__, (ifp)->ifindex, (ifp)->vrf_id); \
+ "ifindex exists already in VRF %s!", \
+ __func__, (ifp)->ifindex, (ifp)->vrf->name); \
_iz; \
})
-#define IFINDEX_RB_REMOVE(vrf, ifp) \
+#define IFINDEX_RB_REMOVE(v, ifp) \
({ \
- struct interface *_iz = RB_REMOVE( \
- if_index_head, &vrf->ifaces_by_index, (ifp)); \
+ struct interface *_iz = \
+ RB_REMOVE(if_index_head, &v->ifaces_by_index, (ifp)); \
if (_iz == NULL) \
flog_err( \
EC_LIB_INTERFACE, \
"%s(%u): corruption detected -- interface with this " \
- "ifindex doesn't exist in VRF %u!", \
- __func__, (ifp)->ifindex, (ifp)->vrf_id); \
+ "ifindex doesn't exist in VRF %s!", \
+ __func__, (ifp)->ifindex, (ifp)->vrf->name); \
_iz; \
})
@@ -548,9 +547,9 @@ extern int if_is_up(const struct interface *ifp);
extern int if_is_running(const struct interface *ifp);
extern int if_is_operative(const struct interface *ifp);
extern int if_is_no_ptm_operative(const struct interface *ifp);
-extern int if_is_loopback(const struct interface *ifp);
+extern int if_is_loopback_exact(const struct interface *ifp);
extern int if_is_vrf(const struct interface *ifp);
-extern bool if_is_loopback_or_vrf(const struct interface *ifp);
+extern bool if_is_loopback(const struct interface *ifp);
extern int if_is_broadcast(const struct interface *ifp);
extern int if_is_pointopoint(const struct interface *ifp);
extern int if_is_multicast(const struct interface *ifp);
diff --git a/lib/json.c b/lib/json.c
index cfba6ea3b6..854a3d59d1 100644
--- a/lib/json.c
+++ b/lib/json.c
@@ -39,17 +39,41 @@ bool use_json(const int argc, struct cmd_token *argv[])
return false;
}
+struct json_object *json_object_new_stringv(const char *fmt, va_list args)
+{
+ struct json_object *ret;
+ char *text, buf[256];
+
+ text = vasnprintfrr(MTYPE_TMP, buf, sizeof(buf), fmt, args);
+ ret = json_object_new_string(text);
+
+ if (text != buf)
+ XFREE(MTYPE_TMP, text);
+ return ret;
+}
+
void json_array_string_add(json_object *json, const char *str)
{
json_object_array_add(json, json_object_new_string(str));
}
+void json_array_string_addv(json_object *json, const char *fmt, va_list args)
+{
+ json_object_array_add(json, json_object_new_stringv(fmt, args));
+}
+
void json_object_string_add(struct json_object *obj, const char *key,
const char *s)
{
json_object_object_add(obj, key, json_object_new_string(s));
}
+void json_object_string_addv(struct json_object *obj, const char *key,
+ const char *fmt, va_list args)
+{
+ json_object_object_add(obj, key, json_object_new_stringv(fmt, args));
+}
+
void json_object_int_add(struct json_object *obj, const char *key, int64_t i)
{
json_object_object_add(obj, key, json_object_new_int64(i));
diff --git a/lib/json.h b/lib/json.h
index fe208f4fa9..9d33ac7ae3 100644
--- a/lib/json.h
+++ b/lib/json.h
@@ -26,6 +26,7 @@ extern "C" {
#endif
#include "command.h"
+#include "printfrr.h"
#include <json-c/json.h>
/*
@@ -59,6 +60,53 @@ extern struct json_object *json_object_lock(struct json_object *obj);
extern void json_object_free(struct json_object *obj);
extern void json_array_string_add(json_object *json, const char *str);
+/* printfrr => json helpers */
+
+PRINTFRR(3, 0)
+extern void json_object_string_addv(struct json_object *obj, const char *key,
+ const char *fmt, va_list args);
+PRINTFRR(3, 4)
+static inline void json_object_string_addf(struct json_object *obj,
+ const char *key, const char *fmt,
+ ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ json_object_string_addv(obj, key, fmt, args);
+ va_end(args);
+}
+
+PRINTFRR(2, 0)
+extern void json_array_string_addv(json_object *json, const char *fmt,
+ va_list args);
+PRINTFRR(2, 3)
+static inline void json_array_string_addf(struct json_object *obj,
+ const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ json_array_string_addv(obj, fmt, args);
+ va_end(args);
+}
+
+PRINTFRR(1, 0)
+extern struct json_object *json_object_new_stringv(const char *fmt,
+ va_list args);
+PRINTFRR(1, 2)
+static inline struct json_object *json_object_new_stringf(const char *fmt, ...)
+{
+ struct json_object *ret;
+ va_list args;
+
+ va_start(args, fmt);
+ ret = json_object_new_stringv(fmt, args);
+ va_end(args);
+
+ return ret;
+}
+
#define JSON_STR "JavaScript Object Notation\n"
/* NOTE: json-c lib has following commit 316da85 which
diff --git a/lib/link_state.c b/lib/link_state.c
index 7d2e6f6422..b0bc386b79 100644
--- a/lib/link_state.c
+++ b/lib/link_state.c
@@ -1010,11 +1010,11 @@ void ls_ted_del_all(struct ls_ted *ted)
return;
/* First remove Vertices, Edges and Subnets and associated Link State */
- frr_each (vertices, &ted->vertices, vertex)
+ frr_each_safe (vertices, &ted->vertices, vertex)
ls_vertex_del_all(ted, vertex);
- frr_each (edges, &ted->edges, edge)
+ frr_each_safe (edges, &ted->edges, edge)
ls_edge_del_all(ted, edge);
- frr_each (subnets, &ted->subnets, subnet)
+ frr_each_safe (subnets, &ted->subnets, subnet)
ls_subnet_del_all(ted, subnet);
/* then remove TED itself */
@@ -1031,17 +1031,17 @@ void ls_ted_clean(struct ls_ted *ted)
return;
/* First, start with Vertices */
- frr_each (vertices, &ted->vertices, vertex)
+ frr_each_safe (vertices, &ted->vertices, vertex)
if (vertex->status == ORPHAN)
ls_vertex_del_all(ted, vertex);
/* Then Edges */
- frr_each (edges, &ted->edges, edge)
+ frr_each_safe (edges, &ted->edges, edge)
if (edge->status == ORPHAN)
ls_edge_del_all(ted, edge);
/* and Subnets */
- frr_each (subnets, &ted->subnets, subnet)
+ frr_each_safe (subnets, &ted->subnets, subnet)
if (subnet->status == ORPHAN)
ls_subnet_del_all(ted, subnet);
diff --git a/lib/log_vty.c b/lib/log_vty.c
index 9911323553..621949ab57 100644
--- a/lib/log_vty.c
+++ b/lib/log_vty.c
@@ -269,14 +269,14 @@ DEFUN_HIDDEN (no_config_log_monitor,
return CMD_SUCCESS;
}
-DEFPY (debug_uid_backtrace,
- debug_uid_backtrace_cmd,
- "[no] debug unique-id UID backtrace",
- NO_STR
- DEBUG_STR
- "Options per individual log message, by unique ID\n"
- "Log message unique ID (XXXXX-XXXXX)\n"
- "Add backtrace to log when message is printed\n")
+DEFPY_NOSH (debug_uid_backtrace,
+ debug_uid_backtrace_cmd,
+ "[no] debug unique-id UID backtrace",
+ NO_STR
+ DEBUG_STR
+ "Options per individual log message, by unique ID\n"
+ "Log message unique ID (XXXXX-XXXXX)\n"
+ "Add backtrace to log when message is printed\n")
{
struct xrefdata search, *xrd;
struct xrefdata_logmsg *xrdl;
@@ -285,10 +285,9 @@ DEFPY (debug_uid_backtrace,
strlcpy(search.uid, uid, sizeof(search.uid));
xrd = xrefdata_uid_find(&xrefdata_uid, &search);
- if (!xrd) {
- vty_out(vty, "%% no log message with ID \"%s\" found\n", uid);
- return CMD_WARNING;
- }
+ if (!xrd)
+ return CMD_ERR_NOTHING_TODO;
+
if (xrd->xref->type != XREFT_LOGMSG) {
vty_out(vty, "%% ID \"%s\" is not a log message\n", uid);
return CMD_WARNING;
diff --git a/lib/nexthop_group.c b/lib/nexthop_group.c
index af9cd2d79a..e8c678ad71 100644
--- a/lib/nexthop_group.c
+++ b/lib/nexthop_group.c
@@ -1035,7 +1035,6 @@ void nexthop_group_write_nexthop(struct vty *vty, const struct nexthop *nh)
void nexthop_group_json_nexthop(json_object *j, const struct nexthop *nh)
{
- char buf[100];
struct vrf *vrf;
json_object *json_backups = NULL;
int i;
@@ -1046,26 +1045,18 @@ void nexthop_group_json_nexthop(json_object *j, const struct nexthop *nh)
ifindex2ifname(nh->ifindex, nh->vrf_id));
break;
case NEXTHOP_TYPE_IPV4:
- json_object_string_add(
- j, "nexthop",
- inet_ntop(AF_INET, &nh->gate.ipv4, buf, sizeof(buf)));
+ json_object_string_addf(j, "nexthop", "%pI4", &nh->gate.ipv4);
break;
case NEXTHOP_TYPE_IPV4_IFINDEX:
- json_object_string_add(
- j, "nexthop",
- inet_ntop(AF_INET, &nh->gate.ipv4, buf, sizeof(buf)));
+ json_object_string_addf(j, "nexthop", "%pI4", &nh->gate.ipv4);
json_object_string_add(j, "vrfId",
ifindex2ifname(nh->ifindex, nh->vrf_id));
break;
case NEXTHOP_TYPE_IPV6:
- json_object_string_add(
- j, "nexthop",
- inet_ntop(AF_INET6, &nh->gate.ipv6, buf, sizeof(buf)));
+ json_object_string_addf(j, "nexthop", "%pI6", &nh->gate.ipv6);
break;
case NEXTHOP_TYPE_IPV6_IFINDEX:
- json_object_string_add(
- j, "nexthop",
- inet_ntop(AF_INET6, &nh->gate.ipv6, buf, sizeof(buf)));
+ json_object_string_addf(j, "nexthop", "%pI6", &nh->gate.ipv6);
json_object_string_add(j, "vrfId",
ifindex2ifname(nh->ifindex, nh->vrf_id));
break;
diff --git a/lib/northbound.c b/lib/northbound.c
index 6edd5184ef..49adea6d53 100644
--- a/lib/northbound.c
+++ b/lib/northbound.c
@@ -830,8 +830,7 @@ int nb_candidate_validate(struct nb_context *context,
struct nb_config_cbs changes;
int ret;
- if (nb_candidate_validate_yang(candidate, errmsg, sizeof(errmsg_len))
- != NB_OK)
+ if (nb_candidate_validate_yang(candidate, errmsg, errmsg_len) != NB_OK)
return NB_ERR_VALIDATION;
RB_INIT(nb_config_cbs, &changes);
diff --git a/lib/northbound_confd.c b/lib/northbound_confd.c
index e62a83cee2..e1c8983fca 100644
--- a/lib/northbound_confd.c
+++ b/lib/northbound_confd.c
@@ -491,6 +491,47 @@ static void *thread_cdb_trigger_subscriptions(void *data)
return NULL;
}
+static int frr_confd_subscribe(const struct lysc_node *snode, void *arg)
+{
+ struct yang_module *module = arg;
+ struct nb_node *nb_node;
+ int *spoint;
+ int ret;
+
+ switch (snode->nodetype) {
+ case LYS_CONTAINER:
+ case LYS_LEAF:
+ case LYS_LEAFLIST:
+ case LYS_LIST:
+ break;
+ default:
+ return YANG_ITER_CONTINUE;
+ }
+
+ if (CHECK_FLAG(snode->flags, LYS_CONFIG_R))
+ return YANG_ITER_CONTINUE;
+
+ nb_node = snode->priv;
+ if (!nb_node)
+ return YANG_ITER_CONTINUE;
+
+ DEBUGD(&nb_dbg_client_confd, "%s: subscribing to '%s'", __func__,
+ nb_node->xpath);
+
+ spoint = XMALLOC(MTYPE_CONFD, sizeof(*spoint));
+ ret = cdb_subscribe2(cdb_sub_sock, CDB_SUB_RUNNING_TWOPHASE,
+ CDB_SUB_WANT_ABORT_ON_ABORT, 3, spoint,
+ module->confd_hash, nb_node->xpath);
+ if (ret != CONFD_OK) {
+ flog_err_confd("cdb_subscribe2");
+ XFREE(MTYPE_CONFD, spoint);
+ return YANG_ITER_CONTINUE;
+ }
+
+ listnode_add(confd_spoints, spoint);
+ return YANG_ITER_CONTINUE;
+}
+
static int frr_confd_init_cdb(void)
{
struct yang_module *module;
@@ -514,8 +555,6 @@ static int frr_confd_init_cdb(void)
/* Subscribe to all loaded YANG data modules. */
confd_spoints = list_new();
RB_FOREACH (module, yang_modules, &yang_modules) {
- struct lysc_node *snode;
-
module->confd_hash = confd_str2hash(module->info->ns);
if (module->confd_hash == 0) {
flog_err(
@@ -530,42 +569,8 @@ static int frr_confd_init_cdb(void)
* entire YANG module. So we have to find the top level
* nodes ourselves and subscribe to their paths.
*/
- LY_LIST_FOR (module->info->data, snode) {
- struct nb_node *nb_node;
- int *spoint;
- int ret;
-
- switch (snode->nodetype) {
- case LYS_CONTAINER:
- case LYS_LEAF:
- case LYS_LEAFLIST:
- case LYS_LIST:
- break;
- default:
- continue;
- }
-
- if (CHECK_FLAG(snode->flags, LYS_CONFIG_R))
- continue;
-
- nb_node = snode->priv;
- if (!nb_node)
- continue;
-
- DEBUGD(&nb_dbg_client_confd, "%s: subscribing to '%s'",
- __func__, nb_node->xpath);
-
- spoint = XMALLOC(MTYPE_CONFD, sizeof(*spoint));
- ret = cdb_subscribe2(
- cdb_sub_sock, CDB_SUB_RUNNING_TWOPHASE,
- CDB_SUB_WANT_ABORT_ON_ABORT, 3, spoint,
- module->confd_hash, nb_node->xpath);
- if (ret != CONFD_OK) {
- flog_err_confd("cdb_subscribe2");
- XFREE(MTYPE_CONFD, spoint);
- }
- listnode_add(confd_spoints, spoint);
- }
+ yang_snodes_iterate(module->info, frr_confd_subscribe, 0,
+ module);
}
if (cdb_subscribe_done(cdb_sub_sock) != CONFD_OK) {
@@ -705,7 +710,7 @@ static int frr_confd_data_get_next(struct confd_trans_ctx *tctx,
confd_data_reply_next_key(tctx, v, keys.num,
(long)nb_next);
} else {
- char pointer_str[16];
+ char pointer_str[32];
/*
* ConfD 6.6 user guide, chapter 6.11 (Operational data
@@ -843,7 +848,7 @@ static int frr_confd_data_get_next_object(struct confd_trans_ctx *tctx,
const void *nb_next;
#define CONFD_OBJECTS_PER_TIME 100
struct confd_next_object objects[CONFD_OBJECTS_PER_TIME + 1];
- char pseudo_keys[CONFD_OBJECTS_PER_TIME][16];
+ char pseudo_keys[CONFD_OBJECTS_PER_TIME][32];
int nobjects = 0;
frr_confd_get_xpath(kp, xpath, sizeof(xpath));
@@ -868,7 +873,7 @@ static int frr_confd_data_get_next_object(struct confd_trans_ctx *tctx,
memset(objects, 0, sizeof(objects));
for (int j = 0; j < CONFD_OBJECTS_PER_TIME; j++) {
struct confd_next_object *object;
- struct lysc_node *child;
+ const struct lysc_node *child;
struct yang_data *data;
size_t nvalues = 0;
@@ -1189,6 +1194,8 @@ static int frr_confd_dp_ctl_read(struct thread *thread)
thread_add_read(master, frr_confd_dp_ctl_read, dctx, fd, &t_dp_ctl);
frr_confd_dp_read(dctx, fd);
+
+ return 0;
}
static int frr_confd_dp_worker_read(struct thread *thread)
@@ -1199,6 +1206,8 @@ static int frr_confd_dp_worker_read(struct thread *thread)
thread_add_read(master, frr_confd_dp_worker_read, dctx, fd, &t_dp_worker);
frr_confd_dp_read(dctx, fd);
+
+ return 0;
}
static int frr_confd_subscribe_state(const struct lysc_node *snode, void *arg)
diff --git a/lib/plist.c b/lib/plist.c
index a53b087a46..046ccadc09 100644
--- a/lib/plist.c
+++ b/lib/plist.c
@@ -1010,7 +1010,6 @@ static void vty_show_prefix_entry(struct vty *vty, json_object *json, afi_t afi,
if (json) {
json_object *json_entry;
- char buf[BUFSIZ];
json_entry = json_object_new_object();
json_object_array_add(json_entries, json_entry);
@@ -1021,10 +1020,9 @@ static void vty_show_prefix_entry(struct vty *vty, json_object *json, afi_t afi,
json_object_string_add(
json_entry, "type",
prefix_list_type_str(pentry));
- json_object_string_add(
- json_entry, "prefix",
- prefix2str(&pentry->prefix, buf,
- sizeof(buf)));
+ json_object_string_addf(json_entry, "prefix",
+ "%pFX",
+ &pentry->prefix);
if (pentry->ge)
json_object_int_add(
@@ -1127,14 +1125,7 @@ static int vty_show_prefix_list(struct vty *vty, afi_t afi, const char *name,
master, dtype, seqnum);
}
- if (uj) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
-
- return CMD_SUCCESS;
+ return vty_json(vty, json);
}
static int vty_show_prefix_list_prefix(struct vty *vty, afi_t afi,
@@ -1592,9 +1583,7 @@ int prefix_bgp_show_prefix_list(struct vty *vty, afi_t afi, char *name,
json_object_object_add(json, "ipv6PrefixList",
json_prefix);
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
+ vty_json(vty, json);
} else {
vty_out(vty, "ip%s prefix-list %s: %d entries\n",
afi == AFI_IP ? "" : "v6", plist->name, plist->count);
diff --git a/lib/routemap.c b/lib/routemap.c
index 6227ebf158..7f733c8114 100644
--- a/lib/routemap.c
+++ b/lib/routemap.c
@@ -34,6 +34,7 @@
#include "lib_errors.h"
#include "table.h"
#include "json.h"
+#include "jhash.h"
DEFINE_MTYPE_STATIC(LIB, ROUTE_MAP, "Route map");
DEFINE_MTYPE(LIB, ROUTE_MAP_NAME, "Route map name");
@@ -47,6 +48,27 @@ DEFINE_MTYPE_STATIC(LIB, ROUTE_MAP_DEP_DATA, "Route map dependency data");
DEFINE_QOBJ_TYPE(route_map_index);
DEFINE_QOBJ_TYPE(route_map);
+static int rmap_cmd_name_cmp(const struct route_map_rule_cmd_proxy *a,
+ const struct route_map_rule_cmd_proxy *b)
+{
+ return strcmp(a->cmd->str, b->cmd->str);
+}
+
+static uint32_t rmap_cmd_name_hash(const struct route_map_rule_cmd_proxy *item)
+{
+ return jhash(item->cmd->str, strlen(item->cmd->str), 0xbfd69320);
+}
+
+DECLARE_HASH(rmap_cmd_name, struct route_map_rule_cmd_proxy, itm,
+ rmap_cmd_name_cmp, rmap_cmd_name_hash);
+
+static struct rmap_cmd_name_head rmap_match_cmds[1] = {
+ INIT_HASH(rmap_match_cmds[0]),
+};
+static struct rmap_cmd_name_head rmap_set_cmds[1] = {
+ INIT_HASH(rmap_set_cmds[0]),
+};
+
#define IPv4_PREFIX_LIST "ip address prefix-list"
#define IPv6_PREFIX_LIST "ipv6 address prefix-list"
@@ -61,12 +83,6 @@ struct route_map_pentry_dep {
route_map_event_t event;
};
-/* Vector for route match rules. */
-static vector route_match_vec;
-
-/* Vector for route set rules. */
-static vector route_set_vec;
-
static void route_map_pfx_tbl_update(route_map_event_t event,
struct route_map_index *index, afi_t afi,
const char *plist_name);
@@ -159,6 +175,22 @@ void route_map_no_match_ip_next_hop_hook(int (*func)(
rmap_match_set_hook.no_match_ip_next_hop = func;
}
+/* match ipv6 next-hop */
+void route_map_match_ipv6_next_hop_hook(int (*func)(
+ struct route_map_index *index, const char *command, const char *arg,
+ route_map_event_t type, char *errmsg, size_t errmsg_len))
+{
+ rmap_match_set_hook.match_ipv6_next_hop = func;
+}
+
+/* no match ipv6 next-hop */
+void route_map_no_match_ipv6_next_hop_hook(int (*func)(
+ struct route_map_index *index, const char *command, const char *arg,
+ route_map_event_t type, char *errmsg, size_t errmsg_len))
+{
+ rmap_match_set_hook.no_match_ipv6_next_hop = func;
+}
+
/* match ip next hop prefix list */
void route_map_match_ip_next_hop_prefix_list_hook(int (*func)(
struct route_map_index *index, const char *command,
@@ -250,6 +282,22 @@ void route_map_no_match_ipv6_next_hop_type_hook(int (*func)(
rmap_match_set_hook.no_match_ipv6_next_hop_type = func;
}
+/* match ipv6 next-hop prefix-list */
+void route_map_match_ipv6_next_hop_prefix_list_hook(int (*func)(
+ struct route_map_index *index, const char *command, const char *arg,
+ route_map_event_t type, char *errmsg, size_t errmsg_len))
+{
+ rmap_match_set_hook.match_ipv6_next_hop_prefix_list = func;
+}
+
+/* no match ipv6 next-hop prefix-list */
+void route_map_no_match_ipv6_next_hop_prefix_list_hook(int (*func)(
+ struct route_map_index *index, const char *command, const char *arg,
+ route_map_event_t type, char *errmsg, size_t errmsg_len))
+{
+ rmap_match_set_hook.no_match_ipv6_next_hop_prefix_list = func;
+}
+
/* match metric */
void route_map_match_metric_hook(int (*func)(
struct route_map_index *index, const char *command,
@@ -1026,14 +1074,7 @@ static int vty_show_route_map(struct vty *vty, const char *name, bool use_json)
list_delete(&maplist);
}
- if (use_json) {
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- }
-
- return CMD_SUCCESS;
+ return vty_json(vty, json);
}
/* Unused route map details */
@@ -1231,40 +1272,40 @@ static struct route_map_rule *route_map_rule_new(void)
}
/* Install rule command to the match list. */
-void route_map_install_match(const struct route_map_rule_cmd *cmd)
+void _route_map_install_match(struct route_map_rule_cmd_proxy *proxy)
{
- vector_set(route_match_vec, (void *)cmd);
+ rmap_cmd_name_add(rmap_match_cmds, proxy);
}
/* Install rule command to the set list. */
-void route_map_install_set(const struct route_map_rule_cmd *cmd)
+void _route_map_install_set(struct route_map_rule_cmd_proxy *proxy)
{
- vector_set(route_set_vec, (void *)cmd);
+ rmap_cmd_name_add(rmap_set_cmds, proxy);
}
/* Lookup rule command from match list. */
static const struct route_map_rule_cmd *route_map_lookup_match(const char *name)
{
- unsigned int i;
- const struct route_map_rule_cmd *rule;
+ struct route_map_rule_cmd refcmd = {.str = name};
+ struct route_map_rule_cmd_proxy ref = {.cmd = &refcmd};
+ struct route_map_rule_cmd_proxy *res;
- for (i = 0; i < vector_active(route_match_vec); i++)
- if ((rule = vector_slot(route_match_vec, i)) != NULL)
- if (strcmp(rule->str, name) == 0)
- return rule;
+ res = rmap_cmd_name_find(rmap_match_cmds, &ref);
+ if (res)
+ return res->cmd;
return NULL;
}
/* Lookup rule command from set list. */
static const struct route_map_rule_cmd *route_map_lookup_set(const char *name)
{
- unsigned int i;
- const struct route_map_rule_cmd *rule;
+ struct route_map_rule_cmd refcmd = {.str = name};
+ struct route_map_rule_cmd_proxy ref = {.cmd = &refcmd};
+ struct route_map_rule_cmd_proxy *res;
- for (i = 0; i < vector_active(route_set_vec); i++)
- if ((rule = vector_slot(route_set_vec, i)) != NULL)
- if (strcmp(rule->str, name) == 0)
- return rule;
+ res = rmap_cmd_name_find(rmap_set_cmds, &ref);
+ if (res)
+ return res->cmd;
return NULL;
}
@@ -3161,11 +3202,21 @@ void route_map_rule_tag_free(void *rule)
void route_map_finish(void)
{
int i;
+ struct route_map_rule_cmd_proxy *proxy;
+
+ /* these 2 hash tables have INIT_HASH initializers, so the "default"
+ * state is "initialized & empty" => fini() followed by init() to
+ * return to that same state
+ */
+ while ((proxy = rmap_cmd_name_pop(rmap_match_cmds)))
+ (void)proxy;
+ rmap_cmd_name_fini(rmap_match_cmds);
+ rmap_cmd_name_init(rmap_match_cmds);
- vector_free(route_match_vec);
- route_match_vec = NULL;
- vector_free(route_set_vec);
- route_set_vec = NULL;
+ while ((proxy = rmap_cmd_name_pop(rmap_set_cmds)))
+ (void)proxy;
+ rmap_cmd_name_fini(rmap_set_cmds);
+ rmap_cmd_name_init(rmap_set_cmds);
/*
* All protocols are setting these to NULL
@@ -3309,9 +3360,6 @@ void route_map_init(void)
{
int i;
- /* Make vector for match and set. */
- route_match_vec = vector_init(1);
- route_set_vec = vector_init(1);
route_map_master_hash =
hash_create_size(8, route_map_hash_key_make, route_map_hash_cmp,
"Route Map Master Hash");
diff --git a/lib/routemap.h b/lib/routemap.h
index f8fdc67d57..6c4916898a 100644
--- a/lib/routemap.h
+++ b/lib/routemap.h
@@ -21,6 +21,7 @@
#ifndef _ZEBRA_ROUTEMAP_H
#define _ZEBRA_ROUTEMAP_H
+#include "typesafe.h"
#include "prefix.h"
#include "memory.h"
#include "qobj.h"
@@ -243,12 +244,16 @@ DECLARE_QOBJ_TYPE(route_map);
(strmatch(C, "frr-route-map:ipv6-address-list"))
#define IS_MATCH_IPv4_NEXTHOP_LIST(C) \
(strmatch(C, "frr-route-map:ipv4-next-hop-list"))
+#define IS_MATCH_IPv6_NEXTHOP_LIST(C) \
+ (strmatch(C, "frr-route-map:ipv6-next-hop-list"))
#define IS_MATCH_IPv4_PREFIX_LIST(C) \
(strmatch(C, "frr-route-map:ipv4-prefix-list"))
#define IS_MATCH_IPv6_PREFIX_LIST(C) \
(strmatch(C, "frr-route-map:ipv6-prefix-list"))
#define IS_MATCH_IPv4_NEXTHOP_PREFIX_LIST(C) \
(strmatch(C, "frr-route-map:ipv4-next-hop-prefix-list"))
+#define IS_MATCH_IPv6_NEXTHOP_PREFIX_LIST(C) \
+ (strmatch(C, "frr-route-map:ipv6-next-hop-prefix-list"))
#define IS_MATCH_IPv4_NEXTHOP_TYPE(C) \
(strmatch(C, "frr-route-map:ipv4-next-hop-type"))
#define IS_MATCH_IPv6_NEXTHOP_TYPE(C) \
@@ -422,8 +427,37 @@ extern enum rmap_compile_rets
route_map_delete_set(struct route_map_index *index,
const char *set_name, const char *set_arg);
+/* struct route_map_rule_cmd is kept const in order to not have writable
+ * function pointers (which is a security benefit.) Hence, below struct is
+ * used as proxy for hashing these for by-name lookup.
+ */
+
+PREDECL_HASH(rmap_cmd_name);
+
+struct route_map_rule_cmd_proxy {
+ struct rmap_cmd_name_item itm;
+ const struct route_map_rule_cmd *cmd;
+};
+
+/* ... and just automatically create a proxy struct for each call location
+ * to route_map_install_{match,set} to avoid unnecessarily added boilerplate
+ * for each route-map user
+ */
+
+#define route_map_install_match(c) \
+ do { \
+ static struct route_map_rule_cmd_proxy proxy = {.cmd = c}; \
+ _route_map_install_match(&proxy); \
+ } while (0)
+
+#define route_map_install_set(c) \
+ do { \
+ static struct route_map_rule_cmd_proxy proxy = {.cmd = c}; \
+ _route_map_install_set(&proxy); \
+ } while (0)
+
/* Install rule command to the match list. */
-extern void route_map_install_match(const struct route_map_rule_cmd *cmd);
+extern void _route_map_install_match(struct route_map_rule_cmd_proxy *proxy);
/*
* Install rule command to the set list.
@@ -434,7 +468,7 @@ extern void route_map_install_match(const struct route_map_rule_cmd *cmd);
* in the apply command). See 'set metric' command
* as it is handled in ripd/ripngd and ospfd.
*/
-extern void route_map_install_set(const struct route_map_rule_cmd *cmd);
+extern void _route_map_install_set(struct route_map_rule_cmd_proxy *proxy);
/* Lookup route map by name. */
extern struct route_map *route_map_lookup_by_name(const char *name);
@@ -525,9 +559,16 @@ extern void route_map_match_ip_next_hop_hook(int (*func)(
char *errmsg, size_t errmsg_len));
/* no match ip next hop */
extern void route_map_no_match_ip_next_hop_hook(int (*func)(
- struct route_map_index *index, const char *command,
- const char *arg, route_map_event_t type,
- char *errmsg, size_t errmsg_len));
+ struct route_map_index *index, const char *command, const char *arg,
+ route_map_event_t type, char *errmsg, size_t errmsg_len));
+/* match ipv6 next hop */
+extern void route_map_match_ipv6_next_hop_hook(int (*func)(
+ struct route_map_index *index, const char *command, const char *arg,
+ route_map_event_t type, char *errmsg, size_t errmsg_len));
+/* no match ipv6 next hop */
+extern void route_map_no_match_ipv6_next_hop_hook(int (*func)(
+ struct route_map_index *index, const char *command, const char *arg,
+ route_map_event_t type, char *errmsg, size_t errmsg_len));
/* match ip next hop prefix list */
extern void route_map_match_ip_next_hop_prefix_list_hook(int (*func)(
struct route_map_index *index, const char *command,
@@ -578,6 +619,14 @@ extern void route_map_no_match_ipv6_next_hop_type_hook(int (*func)(
struct route_map_index *index, const char *command,
const char *arg, route_map_event_t type,
char *errmsg, size_t errmsg_len));
+/* match ipv6 next-hop prefix-list */
+extern void route_map_match_ipv6_next_hop_prefix_list_hook(int (*func)(
+ struct route_map_index *index, const char *command, const char *arg,
+ route_map_event_t type, char *errmsg, size_t errmsg_len));
+/* no match ipv6 next-hop prefix-list */
+extern void route_map_no_match_ipv6_next_hop_prefix_list_hook(int (*func)(
+ struct route_map_index *index, const char *command, const char *arg,
+ route_map_event_t type, char *errmsg, size_t errmsg_len));
/* match metric */
extern void route_map_match_metric_hook(int (*func)(
struct route_map_index *index, const char *command,
@@ -713,6 +762,33 @@ struct route_map_match_set_hooks {
route_map_event_t type,
char *errmsg, size_t errmsg_len);
+ /* match ipv6 next hop */
+ int (*match_ipv6_next_hop)(struct route_map_index *index,
+ const char *command, const char *arg,
+ route_map_event_t type, char *errmsg,
+ size_t errmsg_len);
+
+ /* no match ipv6 next hop */
+ int (*no_match_ipv6_next_hop)(struct route_map_index *index,
+ const char *command, const char *arg,
+ route_map_event_t type, char *errmsg,
+ size_t errmsg_len);
+
+ /* match ipv6 next hop prefix-list */
+ int (*match_ipv6_next_hop_prefix_list)(struct route_map_index *index,
+ const char *command,
+ const char *arg,
+ route_map_event_t type,
+ char *errmsg, size_t errmsg_len);
+
+ /* no match ipv6 next-hop prefix-list */
+ int (*no_match_ipv6_next_hop_prefix_list)(struct route_map_index *index,
+ const char *command,
+ const char *arg,
+ route_map_event_t type,
+ char *errmsg,
+ size_t errmsg_len);
+
/* match ip next hop prefix list */
int (*match_ip_next_hop_prefix_list)(struct route_map_index *index,
const char *command,
diff --git a/lib/routemap_cli.c b/lib/routemap_cli.c
index d7d4a9a81f..52fcaaba53 100644
--- a/lib/routemap_cli.c
+++ b/lib/routemap_cli.c
@@ -41,7 +41,7 @@
DEFPY_YANG_NOSH(
route_map, route_map_cmd,
- "route-map WORD$name <deny|permit>$action (1-65535)$sequence",
+ "route-map RMAP_NAME$name <deny|permit>$action (1-65535)$sequence",
ROUTE_MAP_CMD_STR
ROUTE_MAP_OP_CMD_STR
ROUTE_MAP_SEQUENCE_CMD_STR)
@@ -71,7 +71,7 @@ DEFPY_YANG_NOSH(
DEFPY_YANG(
no_route_map_all, no_route_map_all_cmd,
- "no route-map WORD$name",
+ "no route-map RMAP_NAME$name",
NO_STR
ROUTE_MAP_CMD_STR)
{
@@ -86,7 +86,7 @@ DEFPY_YANG(
DEFPY_YANG(
no_route_map, no_route_map_cmd,
- "no route-map WORD$name <deny|permit>$action (1-65535)$sequence",
+ "no route-map RMAP_NAME$name <deny|permit>$action (1-65535)$sequence",
NO_STR
ROUTE_MAP_CMD_STR
ROUTE_MAP_OP_CMD_STR
@@ -551,6 +551,7 @@ void route_map_condition_show(struct vty *vty, const struct lyd_node *dnode,
yang_dnode_get_string(
dnode, "./rmap-match-condition/interface"));
} else if (IS_MATCH_IPv4_ADDRESS_LIST(condition)
+ || IS_MATCH_IPv6_NEXTHOP_LIST(condition)
|| IS_MATCH_IPv4_NEXTHOP_LIST(condition)) {
acl = NULL;
if ((ln = yang_dnode_get(dnode,
@@ -562,8 +563,10 @@ void route_map_condition_show(struct vty *vty, const struct lyd_node *dnode,
if (IS_MATCH_IPv4_ADDRESS_LIST(condition))
vty_out(vty, " match ip address %s\n", acl);
- else
+ else if (IS_MATCH_IPv4_NEXTHOP_LIST(condition))
vty_out(vty, " match ip next-hop %s\n", acl);
+ else
+ vty_out(vty, " match ipv6 next-hop %s\n", acl);
} else if (IS_MATCH_IPv4_PREFIX_LIST(condition)) {
vty_out(vty, " match ip address prefix-list %s\n",
yang_dnode_get_string(
@@ -572,6 +575,10 @@ void route_map_condition_show(struct vty *vty, const struct lyd_node *dnode,
vty_out(vty, " match ip next-hop prefix-list %s\n",
yang_dnode_get_string(
dnode, "./rmap-match-condition/list-name"));
+ } else if (IS_MATCH_IPv6_NEXTHOP_PREFIX_LIST(condition)) {
+ vty_out(vty, " match ipv6 next-hop prefix-list %s\n",
+ yang_dnode_get_string(
+ dnode, "./rmap-match-condition/list-name"));
} else if (IS_MATCH_IPv6_ADDRESS_LIST(condition)) {
vty_out(vty, " match ipv6 address %s\n",
yang_dnode_get_string(
@@ -791,12 +798,12 @@ void route_map_condition_show(struct vty *vty, const struct lyd_node *dnode,
vty_out(vty, " match extcommunity %s\n", acl);
} else if (IS_MATCH_IPV4_NH(condition)) {
- vty_out(vty, " match ip next-hop %s\n",
+ vty_out(vty, " match ip next-hop address %s\n",
yang_dnode_get_string(
dnode,
"./rmap-match-condition/frr-bgp-route-map:ipv4-address"));
} else if (IS_MATCH_IPV6_NH(condition)) {
- vty_out(vty, " match ipv6 next-hop %s\n",
+ vty_out(vty, " match ipv6 next-hop address %s\n",
yang_dnode_get_string(
dnode,
"./rmap-match-condition/frr-bgp-route-map:ipv6-address"));
@@ -1440,7 +1447,7 @@ void route_map_description_show(struct vty *vty, const struct lyd_node *dnode,
DEFPY_YANG(
route_map_optimization, route_map_optimization_cmd,
- "[no] route-map WORD$name optimization",
+ "[no] route-map RMAP_NAME$name optimization",
NO_STR
ROUTE_MAP_CMD_STR
"Configure route-map optimization\n")
diff --git a/lib/routemap_northbound.c b/lib/routemap_northbound.c
index 3473ca2aea..51b879959f 100644
--- a/lib/routemap_northbound.c
+++ b/lib/routemap_northbound.c
@@ -601,6 +601,16 @@ static int lib_route_map_entry_match_condition_list_name_modify(
rhc->rhc_rmi, "ip next-hop", acl,
RMAP_EVENT_FILTER_ADDED,
args->errmsg, args->errmsg_len);
+ } else if (IS_MATCH_IPv6_NEXTHOP_LIST(condition)) {
+ if (rmap_match_set_hook.match_ipv6_next_hop == NULL)
+ return NB_OK;
+ rhc->rhc_mhook = rmap_match_set_hook.no_match_ipv6_next_hop;
+ rhc->rhc_rule = "ipv6 next-hop";
+ rhc->rhc_event = RMAP_EVENT_FILTER_DELETED;
+ rv = rmap_match_set_hook.match_ipv6_next_hop(
+ rhc->rhc_rmi, "ipv6 next-hop", acl,
+ RMAP_EVENT_FILTER_ADDED, args->errmsg,
+ args->errmsg_len);
} else if (IS_MATCH_IPv4_NEXTHOP_PREFIX_LIST(condition)) {
if (rmap_match_set_hook.match_ip_next_hop_prefix_list == NULL)
return NB_OK;
@@ -612,6 +622,16 @@ static int lib_route_map_entry_match_condition_list_name_modify(
rhc->rhc_rmi, "ip next-hop prefix-list", acl,
RMAP_EVENT_PLIST_ADDED,
args->errmsg, args->errmsg_len);
+ } else if (IS_MATCH_IPv6_NEXTHOP_PREFIX_LIST(condition)) {
+ if (rmap_match_set_hook.match_ipv6_next_hop_prefix_list == NULL)
+ return NB_OK;
+ rhc->rhc_mhook =
+ rmap_match_set_hook.no_match_ipv6_next_hop_prefix_list;
+ rhc->rhc_rule = "ipv6 next-hop prefix-list";
+ rhc->rhc_event = RMAP_EVENT_PLIST_DELETED;
+ rv = rmap_match_set_hook.match_ipv6_next_hop_prefix_list(
+ rhc->rhc_rmi, "ipv6 next-hop prefix-list", acl,
+ RMAP_EVENT_PLIST_ADDED, args->errmsg, args->errmsg_len);
} else if (IS_MATCH_IPv6_ADDRESS_LIST(condition)) {
if (rmap_match_set_hook.match_ipv6_address == NULL)
return NB_OK;
diff --git a/lib/srv6.c b/lib/srv6.c
index ccb94b2f76..aacd30a7af 100644
--- a/lib/srv6.c
+++ b/lib/srv6.c
@@ -161,12 +161,10 @@ void srv6_locator_chunk_free(struct srv6_locator_chunk *chunk)
json_object *srv6_locator_chunk_json(const struct srv6_locator_chunk *chunk)
{
- char str[256];
json_object *jo_root = NULL;
jo_root = json_object_new_object();
- prefix2str(&chunk->prefix, str, sizeof(str));
- json_object_string_add(jo_root, "prefix", str);
+ json_object_string_addf(jo_root, "prefix", "%pFX", &chunk->prefix);
json_object_string_add(jo_root, "proto",
zebra_route_string(chunk->proto));
@@ -175,7 +173,6 @@ json_object *srv6_locator_chunk_json(const struct srv6_locator_chunk *chunk)
json_object *srv6_locator_json(const struct srv6_locator *loc)
{
- char str[256];
struct listnode *node;
struct srv6_locator_chunk *chunk;
json_object *jo_root = NULL;
@@ -188,8 +185,7 @@ json_object *srv6_locator_json(const struct srv6_locator *loc)
json_object_string_add(jo_root, "name", loc->name);
/* set prefix */
- prefix2str(&loc->prefix, str, sizeof(str));
- json_object_string_add(jo_root, "prefix", str);
+ json_object_string_addf(jo_root, "prefix", "%pFX", &loc->prefix);
/* set function_bits_length */
json_object_int_add(jo_root, "functionBitsLength",
diff --git a/lib/vrf.c b/lib/vrf.c
index a9a5a83794..5dc4e05855 100644
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -354,13 +354,6 @@ const char *vrf_id_to_name(vrf_id_t vrf_id)
return VRF_LOGNAME(vrf);
}
-/* Get the data pointer of the specified VRF. If not found, create one. */
-void *vrf_info_get(vrf_id_t vrf_id)
-{
- struct vrf *vrf = vrf_get(vrf_id, NULL);
- return vrf->info;
-}
-
/* Look up the data pointer of the specified VRF. */
void *vrf_info_lookup(vrf_id_t vrf_id)
{
diff --git a/lib/vrf.h b/lib/vrf.h
index 0e2e601a7e..73e324c152 100644
--- a/lib/vrf.h
+++ b/lib/vrf.h
@@ -176,8 +176,6 @@ static inline uint32_t vrf_interface_count(struct vrf *vrf)
* Utilities to obtain the user data
*/
-/* Get the data pointer of the specified VRF. If not found, create one. */
-extern void *vrf_info_get(vrf_id_t);
/* Look up the data pointer of the specified VRF. */
extern void *vrf_info_lookup(vrf_id_t);
diff --git a/lib/vty.c b/lib/vty.c
index 3df623502b..8eaf13619b 100644
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -48,6 +48,7 @@
#include "lib_errors.h"
#include "northbound_cli.h"
#include "printfrr.h"
+#include "json.h"
#include <arpa/telnet.h>
#include <termios.h>
@@ -280,6 +281,21 @@ done:
return len;
}
+int vty_json(struct vty *vty, struct json_object *json)
+{
+ const char *text;
+
+ if (!json)
+ return CMD_SUCCESS;
+
+ text = json_object_to_json_string_ext(
+ json, JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_NOSLASHESCAPE);
+ vty_out(vty, "%s\n", text);
+ json_object_free(json);
+
+ return CMD_SUCCESS;
+}
+
/* Output current time to the vty. */
void vty_time_print(struct vty *vty, int cr)
{
diff --git a/lib/vty.h b/lib/vty.h
index 62e2518957..9ffbce3268 100644
--- a/lib/vty.h
+++ b/lib/vty.h
@@ -39,6 +39,8 @@
extern "C" {
#endif
+struct json_object;
+
#define VTY_BUFSIZ 4096
#define VTY_MAXHIST 20
#define VTY_MAXDEPTH 8
@@ -321,7 +323,11 @@ extern struct vty *vty_stdio(void (*atclose)(int isexit));
extern int vty_out(struct vty *, const char *, ...) PRINTFRR(2, 3);
extern void vty_frame(struct vty *, const char *, ...) PRINTFRR(2, 3);
extern void vty_endframe(struct vty *, const char *);
-bool vty_set_include(struct vty *vty, const char *regexp);
+extern bool vty_set_include(struct vty *vty, const char *regexp);
+/* returns CMD_SUCCESS so you can do a one-line "return vty_json(...)"
+ * NULL check and json_object_free() is included.
+ */
+extern int vty_json(struct vty *vty, struct json_object *json);
extern bool vty_read_config(struct nb_config *config, const char *config_file,
char *config_default_dir);
diff --git a/lib/zclient.c b/lib/zclient.c
index a6103cfee9..000dcaac8f 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -4072,11 +4072,12 @@ enum zclient_send_status zclient_interface_set_master(struct zclient *client,
s = client->obuf;
stream_reset(s);
- zclient_create_header(s, ZEBRA_INTERFACE_SET_MASTER, master->vrf_id);
+ zclient_create_header(s, ZEBRA_INTERFACE_SET_MASTER,
+ master->vrf->vrf_id);
- stream_putl(s, master->vrf_id);
+ stream_putl(s, master->vrf->vrf_id);
stream_putl(s, master->ifindex);
- stream_putl(s, slave->vrf_id);
+ stream_putl(s, slave->vrf->vrf_id);
stream_putl(s, slave->ifindex);
stream_putw_at(s, 0, stream_get_endp(s));
@@ -4163,7 +4164,7 @@ zclient_send_neigh_discovery_req(struct zclient *zclient,
s = zclient->obuf;
stream_reset(s);
- zclient_create_header(s, ZEBRA_NEIGH_DISCOVER, ifp->vrf_id);
+ zclient_create_header(s, ZEBRA_NEIGH_DISCOVER, ifp->vrf->vrf_id);
stream_putl(s, ifp->ifindex);
stream_putc(s, p->family);
@@ -4253,7 +4254,7 @@ int zclient_neigh_ip_encode(struct stream *s, uint16_t cmd, union sockunion *in,
{
int ret = 0;
- zclient_create_header(s, cmd, ifp->vrf_id);
+ zclient_create_header(s, cmd, ifp->vrf->vrf_id);
stream_putc(s, sockunion_family(in));
stream_write(s, sockunion_get_addr(in), sockunion_get_addrlen(in));
if (out && sockunion_family(out) != AF_UNSPEC) {
@@ -4297,9 +4298,7 @@ int zclient_send_zebra_gre_request(struct zclient *client,
}
s = client->obuf;
stream_reset(s);
- zclient_create_header(s,
- ZEBRA_GRE_GET,
- ifp->vrf_id);
+ zclient_create_header(s, ZEBRA_GRE_GET, ifp->vrf->vrf_id);
stream_putl(s, ifp->ifindex);
stream_putw_at(s, 0, stream_get_endp(s));
zclient_send_message(client);