summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/command.c1
-rw-r--r--lib/command_graph.c4
-rw-r--r--lib/command_graph.h1
-rw-r--r--lib/command_lex.l1
-rw-r--r--lib/command_match.c25
-rw-r--r--lib/command_parse.y16
-rw-r--r--lib/command_py.c39
-rw-r--r--lib/nexthop.c69
-rw-r--r--lib/nexthop.h3
-rw-r--r--lib/northbound_cli.c18
-rw-r--r--lib/prefix.h4
-rw-r--r--lib/routemap.c17
-rw-r--r--lib/routemap.h9
-rw-r--r--lib/vrf.c15
-rw-r--r--lib/vrf.h1
-rw-r--r--lib/zclient.c27
-rw-r--r--lib/zclient.h3
17 files changed, 189 insertions, 64 deletions
diff --git a/lib/command.c b/lib/command.c
index fcaf466c65..53aa064705 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -74,6 +74,7 @@ const struct message tokennames[] = {
item(JOIN_TKN),
item(START_TKN),
item(END_TKN),
+ item(NEG_ONLY_TKN),
{0},
};
/* clang-format on */
diff --git a/lib/command_graph.c b/lib/command_graph.c
index c6c3840455..15c8302e63 100644
--- a/lib/command_graph.c
+++ b/lib/command_graph.c
@@ -388,6 +388,7 @@ static void cmd_node_names(struct graph_node *gn, struct graph_node *join,
case START_TKN:
case JOIN_TKN:
+ case NEG_ONLY_TKN:
/* "<foo|bar> WORD" -> word is not "bar" or "foo" */
prevname = NULL;
break;
@@ -511,6 +512,9 @@ void cmd_graph_node_print_cb(struct graph_node *gn, struct buffer *buf)
case JOIN_TKN:
color = "#ddaaff";
break;
+ case NEG_ONLY_TKN:
+ color = "#ffddaa";
+ break;
case WORD_TKN:
color = "#ffffff";
break;
diff --git a/lib/command_graph.h b/lib/command_graph.h
index 2754dca67d..c20c9874c2 100644
--- a/lib/command_graph.h
+++ b/lib/command_graph.h
@@ -64,6 +64,7 @@ enum cmd_token_type {
JOIN_TKN, // marks subgraph end
START_TKN, // first token in line
END_TKN, // last token in line
+ NEG_ONLY_TKN, // filter token, match if "no ..." command
SPECIAL_TKN = FORK_TKN,
};
diff --git a/lib/command_lex.l b/lib/command_lex.l
index 9c096995f5..ec366ce7e1 100644
--- a/lib/command_lex.l
+++ b/lib/command_lex.l
@@ -82,6 +82,7 @@ RANGE \({NUMBER}[ ]?\-[ ]?{NUMBER}\)
{VARIABLE} {yylval->string = XSTRDUP(MTYPE_LEX, yytext); return VARIABLE;}
{WORD} {yylval->string = XSTRDUP(MTYPE_LEX, yytext); return WORD;}
{RANGE} {yylval->string = XSTRDUP(MTYPE_LEX, yytext); return RANGE;}
+!\[ {yylval->string = NULL; return EXCL_BRACKET;}
. {return yytext[0];}
%%
diff --git a/lib/command_match.c b/lib/command_match.c
index 5703510148..f221e0a02c 100644
--- a/lib/command_match.c
+++ b/lib/command_match.c
@@ -42,7 +42,7 @@ DEFINE_MTYPE_STATIC(LIB, CMD_MATCHSTACK, "Command Match Stack");
/* matcher helper prototypes */
static int add_nexthops(struct list *, struct graph_node *,
- struct graph_node **, size_t);
+ struct graph_node **, size_t, bool);
static enum matcher_rv command_match_r(struct graph_node *, vector,
unsigned int, struct graph_node **,
@@ -79,6 +79,13 @@ static enum match_type match_variable(struct cmd_token *, const char *);
static enum match_type match_mac(const char *, bool);
+static bool is_neg(vector vline, size_t idx)
+{
+ if (idx >= vector_active(vline) || !vector_slot(vline, idx))
+ return false;
+ return !strcmp(vector_slot(vline, idx), "no");
+}
+
enum matcher_rv command_match(struct graph *cmdgraph, vector vline,
struct list **argv, const struct cmd_element **el)
{
@@ -248,7 +255,7 @@ static enum matcher_rv command_match_r(struct graph_node *start, vector vline,
// get all possible nexthops
struct list *next = list_new();
- add_nexthops(next, start, NULL, 0);
+ add_nexthops(next, start, NULL, 0, is_neg(vline, 1));
// determine the best match
for (ALL_LIST_ELEMENTS_RO(next, ln, gn)) {
@@ -349,6 +356,7 @@ enum matcher_rv command_complete(struct graph *graph, vector vline,
{
// pointer to next input token to match
char *input_token;
+ bool neg = is_neg(vline, 0);
struct list *
current =
@@ -363,7 +371,7 @@ enum matcher_rv command_complete(struct graph *graph, vector vline,
// add all children of start node to list
struct graph_node *start = vector_slot(graph->nodes, 0);
- add_nexthops(next, start, &start, 0);
+ add_nexthops(next, start, &start, 0, neg);
unsigned int idx;
for (idx = 0; idx < vector_active(vline) && next->count > 0; idx++) {
@@ -428,7 +436,7 @@ enum matcher_rv command_complete(struct graph *graph, vector vline,
listnode_add(next, newstack);
} else if (matchtype >= minmatch)
add_nexthops(next, gstack[0], gstack,
- idx + 1);
+ idx + 1, neg);
break;
default:
trace_matcher("no_match\n");
@@ -478,7 +486,7 @@ enum matcher_rv command_complete(struct graph *graph, vector vline,
* output, instead of direct node pointers!
*/
static int add_nexthops(struct list *list, struct graph_node *node,
- struct graph_node **stack, size_t stackpos)
+ struct graph_node **stack, size_t stackpos, bool neg)
{
int added = 0;
struct graph_node *child;
@@ -494,8 +502,13 @@ static int add_nexthops(struct list *list, struct graph_node *node,
if (j != stackpos)
continue;
}
+
+ if (token->type == NEG_ONLY_TKN && !neg)
+ continue;
+
if (token->type >= SPECIAL_TKN && token->type != END_TKN) {
- added += add_nexthops(list, child, stack, stackpos);
+ added +=
+ add_nexthops(list, child, stack, stackpos, neg);
} else {
if (stack) {
nextstack = XMALLOC(
diff --git a/lib/command_parse.y b/lib/command_parse.y
index f5e42cc304..3e2cdc79af 100644
--- a/lib/command_parse.y
+++ b/lib/command_parse.y
@@ -105,6 +105,9 @@
%token <string> MAC
%token <string> MAC_PREFIX
+/* special syntax, value is irrelevant */
+%token <string> EXCL_BRACKET
+
/* union types for parsed rules */
%type <node> start
%type <node> literal_token
@@ -372,6 +375,19 @@ selector: '[' selector_seq_seq ']' varname_token
}
;
+/* ![option] productions */
+selector: EXCL_BRACKET selector_seq_seq ']' varname_token
+{
+ struct graph_node *neg_only = new_token_node (ctx, NEG_ONLY_TKN, NULL, NULL);
+
+ $$ = $2;
+ graph_add_edge ($$.start, neg_only);
+ graph_add_edge (neg_only, $$.end);
+ cmd_token_varname_set ($2.end->data, $4);
+ XFREE (MTYPE_LEX, $4);
+}
+;
+
%%
#undef scanner
diff --git a/lib/command_py.c b/lib/command_py.c
index 7f19008fbf..90344ae1e5 100644
--- a/lib/command_py.c
+++ b/lib/command_py.c
@@ -197,21 +197,30 @@ static PyObject *graph_to_pyobj(struct wrap_graph *wgraph,
if (gn->data) {
struct cmd_token *tok = gn->data;
switch (tok->type) {
-#define item(x) case x: wrap->type = #x; break;
- item(WORD_TKN) // words
- item(VARIABLE_TKN) // almost anything
- item(RANGE_TKN) // integer range
- item(IPV4_TKN) // IPV4 addresses
- item(IPV4_PREFIX_TKN) // IPV4 network prefixes
- item(IPV6_TKN) // IPV6 prefixes
- item(IPV6_PREFIX_TKN) // IPV6 network prefixes
- item(MAC_TKN) // MAC address
- item(MAC_PREFIX_TKN) // MAC address with mask
-
- /* plumbing types */
- item(FORK_TKN) item(JOIN_TKN) item(START_TKN)
- item(END_TKN) default
- : wrap->type = "???";
+#define item(x) \
+ case x: \
+ wrap->type = #x; \
+ break /* no semicolon */
+
+ item(WORD_TKN); // words
+ item(VARIABLE_TKN); // almost anything
+ item(RANGE_TKN); // integer range
+ item(IPV4_TKN); // IPV4 addresses
+ item(IPV4_PREFIX_TKN); // IPV4 network prefixes
+ item(IPV6_TKN); // IPV6 prefixes
+ item(IPV6_PREFIX_TKN); // IPV6 network prefixes
+ item(MAC_TKN); // MAC address
+ item(MAC_PREFIX_TKN); // MAC address with mask
+
+ /* plumbing types */
+ item(FORK_TKN);
+ item(JOIN_TKN);
+ item(START_TKN);
+ item(END_TKN);
+ item(NEG_ONLY_TKN);
+#undef item
+ default:
+ wrap->type = "???";
}
wrap->deprecated = (tok->attr == CMD_ATTR_DEPRECATED);
diff --git a/lib/nexthop.c b/lib/nexthop.c
index 23e3a2b733..2e09cb4bcc 100644
--- a/lib/nexthop.c
+++ b/lib/nexthop.c
@@ -519,12 +519,13 @@ struct nexthop *nexthop_from_ipv6_ifindex(const struct in6_addr *ipv6,
return nexthop;
}
-struct nexthop *nexthop_from_blackhole(enum blackhole_type bh_type)
+struct nexthop *nexthop_from_blackhole(enum blackhole_type bh_type,
+ vrf_id_t nh_vrf_id)
{
struct nexthop *nexthop;
nexthop = nexthop_new();
- nexthop->vrf_id = VRF_DEFAULT;
+ nexthop->vrf_id = nh_vrf_id;
nexthop->type = NEXTHOP_TYPE_BLACKHOLE;
nexthop->bh_type = bh_type;
@@ -633,9 +634,6 @@ const char *nexthop2str(const struct nexthop *nexthop, char *str, int size)
case NEXTHOP_TYPE_BLACKHOLE:
snprintf(str, size, "blackhole");
break;
- default:
- snprintf(str, size, "unknown");
- break;
}
return str;
@@ -938,6 +936,12 @@ int nexthop_str2backups(const char *str, int *num_backups,
* unreachable (blackhole)
* %pNHs
* nexthop2str()
+ * %pNHcg
+ * 1.2.3.4
+ * (0-length if no IP address present)
+ * %pNHci
+ * eth0
+ * (0-length if no interface present)
*/
printfrr_ext_autoreg_p("NH", printfrr_nh)
static ssize_t printfrr_nh(struct fbuf *buf, struct printfrr_eargs *ea,
@@ -992,12 +996,10 @@ static ssize_t printfrr_nh(struct fbuf *buf, struct printfrr_eargs *ea,
case BLACKHOLE_NULL:
ret += bputs(buf, " (blackhole)");
break;
- default:
+ case BLACKHOLE_UNSPEC:
break;
}
break;
- default:
- break;
}
if (do_ifi && nexthop->ifindex)
ret += bprintfrr(buf, ", %s%s", v_viaif,
@@ -1028,9 +1030,54 @@ static ssize_t printfrr_nh(struct fbuf *buf, struct printfrr_eargs *ea,
case NEXTHOP_TYPE_BLACKHOLE:
ret += bputs(buf, "blackhole");
break;
- default:
- ret += bputs(buf, "unknown");
- break;
+ }
+ return ret;
+ case 'c':
+ ea->fmt++;
+ if (*ea->fmt == 'g') {
+ ea->fmt++;
+ if (!nexthop)
+ return bputs(buf, "(null)");
+ switch (nexthop->type) {
+ case NEXTHOP_TYPE_IPV4:
+ case NEXTHOP_TYPE_IPV4_IFINDEX:
+ ret += bprintfrr(buf, "%pI4",
+ &nexthop->gate.ipv4);
+ break;
+ case NEXTHOP_TYPE_IPV6:
+ case NEXTHOP_TYPE_IPV6_IFINDEX:
+ ret += bprintfrr(buf, "%pI6",
+ &nexthop->gate.ipv6);
+ break;
+ case NEXTHOP_TYPE_IFINDEX:
+ case NEXTHOP_TYPE_BLACKHOLE:
+ break;
+ }
+ } else if (*ea->fmt == 'i') {
+ ea->fmt++;
+ if (!nexthop)
+ return bputs(buf, "(null)");
+ switch (nexthop->type) {
+ case NEXTHOP_TYPE_IFINDEX:
+ ret += bprintfrr(
+ buf, "%s",
+ ifindex2ifname(nexthop->ifindex,
+ nexthop->vrf_id));
+ break;
+ case NEXTHOP_TYPE_IPV4:
+ case NEXTHOP_TYPE_IPV4_IFINDEX:
+ case NEXTHOP_TYPE_IPV6:
+ case NEXTHOP_TYPE_IPV6_IFINDEX:
+ if (nexthop->ifindex)
+ ret += bprintfrr(
+ buf, "%s",
+ ifindex2ifname(
+ nexthop->ifindex,
+ nexthop->vrf_id));
+ break;
+ case NEXTHOP_TYPE_BLACKHOLE:
+ break;
+ }
}
return ret;
}
diff --git a/lib/nexthop.h b/lib/nexthop.h
index dd65509aec..320b46315e 100644
--- a/lib/nexthop.h
+++ b/lib/nexthop.h
@@ -182,7 +182,8 @@ struct nexthop *nexthop_from_ipv6(const struct in6_addr *ipv6,
vrf_id_t vrf_id);
struct nexthop *nexthop_from_ipv6_ifindex(const struct in6_addr *ipv6,
ifindex_t ifindex, vrf_id_t vrf_id);
-struct nexthop *nexthop_from_blackhole(enum blackhole_type bh_type);
+struct nexthop *nexthop_from_blackhole(enum blackhole_type bh_type,
+ vrf_id_t nh_vrf_id);
/*
* Hash a nexthop. Suitable for use with hash tables.
diff --git a/lib/northbound_cli.c b/lib/northbound_cli.c
index b74a0e6c23..6676c0b072 100644
--- a/lib/northbound_cli.c
+++ b/lib/northbound_cli.c
@@ -550,6 +550,13 @@ void nb_cli_show_config_prepare(struct nb_config *config, bool with_defaults)
LYD_VALIDATE_NO_STATE, NULL);
}
+static int lyd_node_cmp(struct lyd_node **dnode1, struct lyd_node **dnode2)
+{
+ struct nb_node *nb_node = (*dnode1)->schema->priv;
+
+ return nb_node->cbs.cli_cmp(*dnode1, *dnode2);
+}
+
static void show_dnode_children_cmds(struct vty *vty, struct lyd_node *root,
bool with_defaults)
{
@@ -567,6 +574,10 @@ static void show_dnode_children_cmds(struct vty *vty, struct lyd_node *root,
* it's time to print the config.
*/
if (sort_node && nb_node != sort_node) {
+ list_sort(sort_list,
+ (int (*)(const void **,
+ const void **))lyd_node_cmp);
+
for (ALL_LIST_ELEMENTS_RO(sort_list, listnode, data))
nb_cli_show_dnode_cmds(vty, data,
with_defaults);
@@ -584,11 +595,9 @@ static void show_dnode_children_cmds(struct vty *vty, struct lyd_node *root,
if (!sort_node) {
sort_node = nb_node;
sort_list = list_new();
- sort_list->cmp = (int (*)(void *, void *))
- nb_node->cbs.cli_cmp;
}
- listnode_add_sort(sort_list, child);
+ listnode_add(sort_list, child);
continue;
}
@@ -596,6 +605,9 @@ static void show_dnode_children_cmds(struct vty *vty, struct lyd_node *root,
}
if (sort_node) {
+ list_sort(sort_list,
+ (int (*)(const void **, const void **))lyd_node_cmp);
+
for (ALL_LIST_ELEMENTS_RO(sort_list, listnode, data))
nb_cli_show_dnode_cmds(vty, data, with_defaults);
diff --git a/lib/prefix.h b/lib/prefix.h
index 944c94f57f..c92f5cec5a 100644
--- a/lib/prefix.h
+++ b/lib/prefix.h
@@ -512,7 +512,7 @@ extern char *esi_to_str(const esi_t *esi, char *buf, int size);
extern char *evpn_es_df_alg2str(uint8_t df_alg, char *buf, int buf_len);
extern void prefix_evpn_hexdump(const struct prefix_evpn *p);
-static inline int ipv6_martian(struct in6_addr *addr)
+static inline int ipv6_martian(const struct in6_addr *addr)
{
struct in6_addr localhost_addr;
@@ -527,7 +527,7 @@ static inline int ipv6_martian(struct in6_addr *addr)
extern int macstr2prefix_evpn(const char *str, struct prefix_evpn *p);
/* NOTE: This routine expects the address argument in network byte order. */
-static inline int ipv4_martian(struct in_addr *addr)
+static inline int ipv4_martian(const struct in_addr *addr)
{
in_addr_t ip = ntohl(addr->s_addr);
diff --git a/lib/routemap.c b/lib/routemap.c
index 594dcf97cb..5c60b7d1c6 100644
--- a/lib/routemap.c
+++ b/lib/routemap.c
@@ -2488,8 +2488,9 @@ void route_map_notify_pentry_dependencies(const char *affected_name,
We need to make sure our route-map processing matches the above
*/
-route_map_result_t route_map_apply(struct route_map *map,
- const struct prefix *prefix, void *object)
+route_map_result_t route_map_apply_ext(struct route_map *map,
+ const struct prefix *prefix,
+ void *match_object, void *set_object)
{
static int recursion = 0;
enum route_map_cmd_result_t match_ret = RMAP_NOMATCH;
@@ -2516,7 +2517,7 @@ route_map_result_t route_map_apply(struct route_map *map,
if ((!map->optimization_disabled)
&& (map->ipv4_prefix_table || map->ipv6_prefix_table)) {
- index = route_map_get_index(map, prefix, object,
+ index = route_map_get_index(map, prefix, match_object,
(uint8_t *)&match_ret);
if (index) {
index->applied++;
@@ -2551,7 +2552,7 @@ route_map_result_t route_map_apply(struct route_map *map,
index->applied++;
/* Apply this index. */
match_ret = route_map_apply_match(&index->match_list,
- prefix, object);
+ prefix, match_object);
if (rmap_debug) {
zlog_debug(
"Route-map: %s, sequence: %d, prefix: %pFX, result: %s",
@@ -2610,7 +2611,7 @@ route_map_result_t route_map_apply(struct route_map *map,
* return code.
*/
(void)(*set->cmd->func_apply)(
- set->value, prefix, object);
+ set->value, prefix, set_object);
/* Call another route-map if available */
if (index->nextrm) {
@@ -2622,8 +2623,10 @@ route_map_result_t route_map_apply(struct route_map *map,
jump to it */
{
recursion++;
- ret = route_map_apply(
- nextrm, prefix, object);
+ ret = route_map_apply_ext(
+ nextrm, prefix,
+ match_object,
+ set_object);
recursion--;
}
diff --git a/lib/routemap.h b/lib/routemap.h
index b356dbf52e..2c8eb24537 100644
--- a/lib/routemap.h
+++ b/lib/routemap.h
@@ -443,9 +443,12 @@ extern struct route_map *route_map_lookup_by_name(const char *name);
struct route_map *route_map_lookup_warn_noexist(struct vty *vty, const char *name);
/* Apply route map to the object. */
-extern route_map_result_t route_map_apply(struct route_map *map,
- const struct prefix *prefix,
- void *object);
+extern route_map_result_t route_map_apply_ext(struct route_map *map,
+ const struct prefix *prefix,
+ void *match_object,
+ void *set_object);
+#define route_map_apply(map, prefix, object) \
+ route_map_apply_ext(map, prefix, object, object)
extern void route_map_add_hook(void (*func)(const char *));
extern void route_map_delete_hook(void (*func)(const char *));
diff --git a/lib/vrf.c b/lib/vrf.c
index f9307d3039..198d5253c8 100644
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -384,21 +384,6 @@ const char *vrf_id_to_name(vrf_id_t vrf_id)
return VRF_LOGNAME(vrf);
}
-vrf_id_t vrf_name_to_id(const char *name)
-{
- struct vrf *vrf;
- vrf_id_t vrf_id = VRF_DEFAULT; // Pending: need a way to return invalid
- // id/ routine not used.
-
- if (!name)
- return vrf_id;
- vrf = vrf_lookup_by_name(name);
- if (vrf)
- vrf_id = vrf->vrf_id;
-
- return vrf_id;
-}
-
/* Get the data pointer of the specified VRF. If not found, create one. */
void *vrf_info_get(vrf_id_t vrf_id)
{
diff --git a/lib/vrf.h b/lib/vrf.h
index 9949ec4112..dab83d42da 100644
--- a/lib/vrf.h
+++ b/lib/vrf.h
@@ -119,7 +119,6 @@ extern struct vrf *vrf_lookup_by_name(const char *);
extern struct vrf *vrf_get(vrf_id_t, const char *);
extern struct vrf *vrf_update(vrf_id_t new_vrf_id, const char *name);
extern const char *vrf_id_to_name(vrf_id_t vrf_id);
-extern vrf_id_t vrf_name_to_id(const char *);
#define VRF_LOGNAME(V) V ? V->name : "Unknown"
diff --git a/lib/zclient.c b/lib/zclient.c
index a1e7194890..dde60a6c90 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -1105,6 +1105,33 @@ stream_failure:
return -1;
}
+int zapi_srv6_locator_encode(struct stream *s, const struct srv6_locator *l)
+{
+ stream_putw(s, strlen(l->name));
+ stream_put(s, l->name, strlen(l->name));
+ stream_putw(s, l->prefix.prefixlen);
+ stream_put(s, &l->prefix.prefix, sizeof(l->prefix.prefix));
+ return 0;
+}
+
+int zapi_srv6_locator_decode(struct stream *s, struct srv6_locator *l)
+{
+ uint16_t len = 0;
+
+ STREAM_GETW(s, len);
+ if (len > SRV6_LOCNAME_SIZE)
+ goto stream_failure;
+
+ STREAM_GET(l->name, s, len);
+ STREAM_GETW(s, l->prefix.prefixlen);
+ STREAM_GET(&l->prefix.prefix, s, sizeof(l->prefix.prefix));
+ l->prefix.family = AF_INET6;
+ return 0;
+
+stream_failure:
+ return -1;
+}
+
static int zapi_nhg_encode(struct stream *s, int cmd, struct zapi_nhg *api_nhg)
{
int i;
diff --git a/lib/zclient.h b/lib/zclient.h
index 71187ccae7..f9438d5db7 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -1090,6 +1090,9 @@ extern int zapi_labels_encode(struct stream *s, int cmd,
struct zapi_labels *zl);
extern int zapi_labels_decode(struct stream *s, struct zapi_labels *zl);
+extern int zapi_srv6_locator_encode(struct stream *s,
+ const struct srv6_locator *l);
+extern int zapi_srv6_locator_decode(struct stream *s, struct srv6_locator *l);
extern int zapi_srv6_locator_chunk_encode(struct stream *s,
const struct srv6_locator_chunk *c);
extern int zapi_srv6_locator_chunk_decode(struct stream *s,