diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/command.c | 41 | ||||
| -rw-r--r-- | lib/command.h | 3 | ||||
| -rw-r--r-- | lib/ferr.c | 8 | ||||
| -rw-r--r-- | lib/filter.c | 56 | ||||
| -rw-r--r-- | lib/if.c | 23 | ||||
| -rw-r--r-- | lib/if.h | 41 | ||||
| -rw-r--r-- | lib/json.c | 24 | ||||
| -rw-r--r-- | lib/json.h | 48 | ||||
| -rw-r--r-- | lib/link_state.c | 12 | ||||
| -rw-r--r-- | lib/log_vty.c | 23 | ||||
| -rw-r--r-- | lib/nexthop_group.c | 17 | ||||
| -rw-r--r-- | lib/northbound.c | 3 | ||||
| -rw-r--r-- | lib/northbound_confd.c | 91 | ||||
| -rw-r--r-- | lib/plist.c | 21 | ||||
| -rw-r--r-- | lib/routemap.c | 122 | ||||
| -rw-r--r-- | lib/routemap.h | 86 | ||||
| -rw-r--r-- | lib/routemap_cli.c | 21 | ||||
| -rw-r--r-- | lib/routemap_northbound.c | 20 | ||||
| -rw-r--r-- | lib/srv6.c | 8 | ||||
| -rw-r--r-- | lib/vrf.c | 7 | ||||
| -rw-r--r-- | lib/vrf.h | 2 | ||||
| -rw-r--r-- | lib/vty.c | 16 | ||||
| -rw-r--r-- | lib/vty.h | 8 | ||||
| -rw-r--r-- | lib/zclient.c | 15 |
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) @@ -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; @@ -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", @@ -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) { @@ -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); @@ -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) { @@ -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); |
