summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/frr_pthread.c15
-rw-r--r--lib/libfrr.c4
-rw-r--r--lib/log.c1
-rw-r--r--lib/mpls.h2
-rw-r--r--lib/routemap.c44
-rw-r--r--lib/routemap.h8
-rw-r--r--lib/vrf.c8
-rw-r--r--lib/yang_wrappers.c53
-rw-r--r--lib/yang_wrappers.h8
-rw-r--r--lib/zclient.c137
-rw-r--r--lib/zclient.h29
11 files changed, 283 insertions, 26 deletions
diff --git a/lib/frr_pthread.c b/lib/frr_pthread.c
index 21dfc9256f..97550eae53 100644
--- a/lib/frr_pthread.c
+++ b/lib/frr_pthread.c
@@ -51,12 +51,13 @@ void frr_pthread_init(void)
{
frr_with_mutex(&frr_pthread_list_mtx) {
frr_pthread_list = list_new();
- frr_pthread_list->del = (void (*)(void *))&frr_pthread_destroy;
}
}
void frr_pthread_finish(void)
{
+ frr_pthread_stop_all();
+
frr_with_mutex(&frr_pthread_list_mtx) {
list_delete(&frr_pthread_list);
}
@@ -99,8 +100,11 @@ struct frr_pthread *frr_pthread_new(struct frr_pthread_attr *attr,
void frr_pthread_destroy(struct frr_pthread *fpt)
{
- thread_master_free(fpt->master);
+ frr_with_mutex(&frr_pthread_list_mtx) {
+ listnode_delete(frr_pthread_list, fpt);
+ }
+ thread_master_free(fpt->master);
pthread_mutex_destroy(&fpt->mtx);
pthread_mutex_destroy(fpt->running_cond_mtx);
pthread_cond_destroy(fpt->running_cond);
@@ -183,8 +187,11 @@ void frr_pthread_stop_all(void)
frr_with_mutex(&frr_pthread_list_mtx) {
struct listnode *n;
struct frr_pthread *fpt;
- for (ALL_LIST_ELEMENTS_RO(frr_pthread_list, n, fpt))
- frr_pthread_stop(fpt, NULL);
+ for (ALL_LIST_ELEMENTS_RO(frr_pthread_list, n, fpt)) {
+ if (atomic_load_explicit(&fpt->running,
+ memory_order_relaxed))
+ frr_pthread_stop(fpt, NULL);
+ }
}
}
diff --git a/lib/libfrr.c b/lib/libfrr.c
index 4301dc20ad..478fe4e205 100644
--- a/lib/libfrr.c
+++ b/lib/libfrr.c
@@ -42,6 +42,7 @@
#include "northbound_db.h"
#include "debug.h"
#include "frrcu.h"
+#include "frr_pthread.h"
DEFINE_HOOK(frr_late_init, (struct thread_master * tm), (tm))
DEFINE_KOOH(frr_early_fini, (), ())
@@ -681,6 +682,8 @@ struct thread_master *frr_init(void)
memory_init();
log_filter_cmd_init();
+ frr_pthread_init();
+
log_ref_init();
log_ref_vty_init();
lib_error_init();
@@ -1076,6 +1079,7 @@ void frr_fini(void)
db_close();
#endif
log_ref_fini();
+ frr_pthread_finish();
zprivs_terminate(di->privs);
/* signal_init -> nothing needed */
thread_master_free(master);
diff --git a/lib/log.c b/lib/log.c
index f1c0fabfba..c777868736 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -1041,6 +1041,7 @@ static const struct zebra_desc_table command_types[] = {
DESC_ENTRY(ZEBRA_INTERFACE_LINK_PARAMS),
DESC_ENTRY(ZEBRA_MPLS_LABELS_ADD),
DESC_ENTRY(ZEBRA_MPLS_LABELS_DELETE),
+ DESC_ENTRY(ZEBRA_MPLS_LABELS_REPLACE),
DESC_ENTRY(ZEBRA_IPMR_ROUTE_STATS),
DESC_ENTRY(ZEBRA_LABEL_MANAGER_CONNECT),
DESC_ENTRY(ZEBRA_LABEL_MANAGER_CONNECT_ASYNC),
diff --git a/lib/mpls.h b/lib/mpls.h
index d7b56c47bd..472ee9bc46 100644
--- a/lib/mpls.h
+++ b/lib/mpls.h
@@ -125,7 +125,7 @@ enum lsp_types_t {
ZEBRA_LSP_STATIC = 1, /* Static LSP. */
ZEBRA_LSP_LDP = 2, /* LDP LSP. */
ZEBRA_LSP_BGP = 3, /* BGP LSP. */
- ZEBRA_LSP_SR = 4, /* Segment Routing LSP. */
+ ZEBRA_LSP_OSPF_SR = 4,/* OSPF Segment Routing LSP. */
ZEBRA_LSP_SHARP = 5, /* Identifier for test protocol */
};
diff --git a/lib/routemap.c b/lib/routemap.c
index fc15183bf9..580d898448 100644
--- a/lib/routemap.c
+++ b/lib/routemap.c
@@ -478,11 +478,6 @@ int generic_match_add(struct vty *vty, struct route_map_index *index,
ret = route_map_add_match(index, command, arg, type);
switch (ret) {
- case RMAP_COMPILE_SUCCESS:
- if (type != RMAP_EVENT_MATCH_ADDED) {
- route_map_upd8_dependency(type, arg, index->map->name);
- }
- break;
case RMAP_RULE_MISSING:
vty_out(vty, "%% [%s] Can't find rule.\n", frr_protonameinst);
return CMD_WARNING_CONFIG_FAILED;
@@ -493,7 +488,7 @@ int generic_match_add(struct vty *vty, struct route_map_index *index,
frr_protonameinst);
return CMD_WARNING_CONFIG_FAILED;
break;
- case RMAP_DUPLICATE_RULE:
+ case RMAP_COMPILE_SUCCESS:
/*
* Nothing to do here move along
*/
@@ -526,7 +521,7 @@ int generic_match_delete(struct vty *vty, struct route_map_index *index,
rmap_name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, index->map->name);
}
- ret = route_map_delete_match(index, command, dep_name);
+ ret = route_map_delete_match(index, command, dep_name, type);
switch (ret) {
case RMAP_RULE_MISSING:
vty_out(vty, "%% [%s] Can't find rule.\n", frr_protonameinst);
@@ -539,10 +534,6 @@ int generic_match_delete(struct vty *vty, struct route_map_index *index,
retval = CMD_WARNING_CONFIG_FAILED;
break;
case RMAP_COMPILE_SUCCESS:
- if (type != RMAP_EVENT_MATCH_DELETED && dep_name)
- route_map_upd8_dependency(type, dep_name, rmap_name);
- break;
- case RMAP_DUPLICATE_RULE:
/*
* Nothing to do here
*/
@@ -573,7 +564,6 @@ int generic_set_add(struct vty *vty, struct route_map_index *index,
return CMD_WARNING_CONFIG_FAILED;
break;
case RMAP_COMPILE_SUCCESS:
- case RMAP_DUPLICATE_RULE:
break;
}
@@ -598,7 +588,6 @@ int generic_set_delete(struct vty *vty, struct route_map_index *index,
return CMD_WARNING_CONFIG_FAILED;
break;
case RMAP_COMPILE_SUCCESS:
- case RMAP_DUPLICATE_RULE:
break;
}
@@ -1410,6 +1399,7 @@ enum rmap_compile_rets route_map_add_match(struct route_map_index *index,
struct route_map_rule_cmd *cmd;
void *compile;
int8_t delete_rmap_event_type = 0;
+ const char *rule_key;
/* First lookup rule for add match statement. */
cmd = route_map_lookup_match(match_name);
@@ -1423,6 +1413,12 @@ enum rmap_compile_rets route_map_add_match(struct route_map_index *index,
return RMAP_COMPILE_ERROR;
} else
compile = NULL;
+ /* use the compiled results if applicable */
+ if (compile && cmd->func_get_rmap_rule_key)
+ rule_key = (*cmd->func_get_rmap_rule_key)
+ (compile);
+ else
+ rule_key = match_arg;
/* If argument is completely same ignore it. */
for (rule = index->match_list.head; rule; rule = next) {
@@ -1436,7 +1432,7 @@ enum rmap_compile_rets route_map_add_match(struct route_map_index *index,
if (cmd->func_free)
(*cmd->func_free)(compile);
- return RMAP_DUPLICATE_RULE;
+ return RMAP_COMPILE_SUCCESS;
}
/* Remove the dependency of the route-map on the rule
@@ -1447,7 +1443,7 @@ enum rmap_compile_rets route_map_add_match(struct route_map_index *index,
get_route_map_delete_event(type);
route_map_upd8_dependency(
delete_rmap_event_type,
- rule->rule_str,
+ rule_key,
index->map->name);
}
@@ -1473,6 +1469,8 @@ enum rmap_compile_rets route_map_add_match(struct route_map_index *index,
route_map_notify_dependencies(index->map->name,
RMAP_EVENT_CALL_ADDED);
}
+ if (type != RMAP_EVENT_MATCH_ADDED)
+ route_map_upd8_dependency(type, rule_key, index->map->name);
return RMAP_COMPILE_SUCCESS;
}
@@ -1480,10 +1478,12 @@ enum rmap_compile_rets route_map_add_match(struct route_map_index *index,
/* Delete specified route match rule. */
enum rmap_compile_rets route_map_delete_match(struct route_map_index *index,
const char *match_name,
- const char *match_arg)
+ const char *match_arg,
+ route_map_event_t type)
{
struct route_map_rule *rule;
struct route_map_rule_cmd *cmd;
+ const char *rule_key;
cmd = route_map_lookup_match(match_name);
if (cmd == NULL)
@@ -1492,7 +1492,6 @@ enum rmap_compile_rets route_map_delete_match(struct route_map_index *index,
for (rule = index->match_list.head; rule; rule = rule->next)
if (rule->cmd == cmd && (rulecmp(rule->rule_str, match_arg) == 0
|| match_arg == NULL)) {
- route_map_rule_delete(&index->match_list, rule);
/* Execute event hook. */
if (route_map_master.event_hook) {
(*route_map_master.event_hook)(index->map->name);
@@ -1500,6 +1499,17 @@ enum rmap_compile_rets route_map_delete_match(struct route_map_index *index,
index->map->name,
RMAP_EVENT_CALL_ADDED);
}
+ if (cmd->func_get_rmap_rule_key)
+ rule_key = (*cmd->func_get_rmap_rule_key)
+ (rule->value);
+ else
+ rule_key = match_arg;
+
+ if (type != RMAP_EVENT_MATCH_DELETED && rule_key)
+ route_map_upd8_dependency(type, rule_key,
+ index->map->name);
+
+ route_map_rule_delete(&index->match_list, rule);
return RMAP_COMPILE_SUCCESS;
}
/* Can't find matched rule. */
diff --git a/lib/routemap.h b/lib/routemap.h
index 40525987e9..e6eccd4b29 100644
--- a/lib/routemap.h
+++ b/lib/routemap.h
@@ -123,6 +123,9 @@ struct route_map_rule_cmd {
/* Free allocated value by func_compile (). */
void (*func_free)(void *);
+
+ /** To get the rule key after Compilation **/
+ void *(*func_get_rmap_rule_key)(void *val);
};
/* Route map apply error. */
@@ -135,8 +138,6 @@ enum rmap_compile_rets {
/* Route map rule can't compile */
RMAP_COMPILE_ERROR,
- /* Route map rule is duplicate */
- RMAP_DUPLICATE_RULE
};
/* Route map rule list. */
@@ -228,7 +229,8 @@ extern enum rmap_compile_rets route_map_add_match(struct route_map_index *index,
/* Delete specified route match rule. */
extern enum rmap_compile_rets
route_map_delete_match(struct route_map_index *index,
- const char *match_name, const char *match_arg);
+ const char *match_name, const char *match_arg,
+ route_map_event_t type);
extern const char *route_map_get_match_arg(struct route_map_index *index,
const char *match_name);
diff --git a/lib/vrf.c b/lib/vrf.c
index 575e96bae4..4c6df797ad 100644
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -199,9 +199,14 @@ struct vrf *vrf_get(vrf_id_t vrf_id, const char *name)
/* Set name */
if (name && vrf->name[0] != '\0' && strcmp(name, vrf->name)) {
+ /* update the vrf name */
RB_REMOVE(vrf_name_head, &vrfs_by_name, vrf);
+ strlcpy(vrf->data.l.netns_name,
+ name, NS_NAMSIZ);
strlcpy(vrf->name, name, sizeof(vrf->name));
RB_INSERT(vrf_name_head, &vrfs_by_name, vrf);
+ if (vrf->vrf_id == VRF_DEFAULT)
+ vrf_set_default_name(vrf->name, false);
} else if (name && vrf->name[0] == '\0') {
strlcpy(vrf->name, name, sizeof(vrf->name));
RB_INSERT(vrf_name_head, &vrfs_by_name, vrf);
@@ -870,7 +875,8 @@ void vrf_set_default_name(const char *default_name, bool force)
def_vrf->vrf_id);
return;
}
-
+ if (strmatch(vrf_default_name, default_name))
+ return;
snprintf(vrf_default_name, VRF_NAMSIZ, "%s", default_name);
if (def_vrf) {
if (force)
diff --git a/lib/yang_wrappers.c b/lib/yang_wrappers.c
index 0558383823..cd776f333d 100644
--- a/lib/yang_wrappers.c
+++ b/lib/yang_wrappers.c
@@ -1000,3 +1000,56 @@ void yang_get_default_ipv6p(union prefixptr var, const char *xpath_fmt, ...)
value = yang_get_default_value(xpath);
yang_str2ipv6p(value, var);
}
+
+/*
+ * Derived type: ip.
+ */
+void yang_str2ip(const char *value, struct ipaddr *ip)
+{
+ (void)str2ipaddr(value, ip);
+}
+
+struct yang_data *yang_data_new_ip(const char *xpath, const struct ipaddr *addr)
+{
+ size_t sz = IS_IPADDR_V4(addr) ? INET_ADDRSTRLEN : INET6_ADDRSTRLEN;
+ char value_str[sz];
+
+ ipaddr2str(addr, value_str, sizeof(value_str));
+ return yang_data_new(xpath, value_str);
+}
+
+void yang_dnode_get_ip(struct ipaddr *addr, const struct lyd_node *dnode,
+ const char *xpath_fmt, ...)
+{
+ const struct lyd_node_leaf_list *dleaf;
+
+ assert(dnode);
+ if (xpath_fmt) {
+ va_list ap;
+ char xpath[XPATH_MAXLEN];
+
+ va_start(ap, xpath_fmt);
+ vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
+ va_end(ap);
+ dnode = yang_dnode_get(dnode, xpath);
+ YANG_DNODE_GET_ASSERT(dnode, xpath);
+ }
+
+ dleaf = (const struct lyd_node_leaf_list *)dnode;
+ assert(dleaf->value_type == LY_TYPE_STRING);
+ (void)str2ipaddr(dleaf->value_str, addr);
+}
+
+void yang_get_default_ip(struct ipaddr *var, const char *xpath_fmt, ...)
+{
+ char xpath[XPATH_MAXLEN];
+ const char *value;
+ va_list ap;
+
+ va_start(ap, xpath_fmt);
+ vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
+ va_end(ap);
+
+ value = yang_get_default_value(xpath);
+ yang_str2ip(value, var);
+}
diff --git a/lib/yang_wrappers.h b/lib/yang_wrappers.h
index 5203a033ad..ab7abe173c 100644
--- a/lib/yang_wrappers.h
+++ b/lib/yang_wrappers.h
@@ -154,4 +154,12 @@ extern void yang_dnode_get_ipv6p(union prefixptr prefix,
extern void yang_get_default_ipv6p(union prefixptr var, const char *xpath_fmt,
...);
+/* ip */
+extern void yang_str2ip(const char *value, struct ipaddr *addr);
+extern struct yang_data *yang_data_new_ip(const char *xpath,
+ const struct ipaddr *addr);
+extern void yang_dnode_get_ip(struct ipaddr *addr, const struct lyd_node *dnode,
+ const char *xpath_fmt, ...);
+extern void yang_get_default_ip(struct ipaddr *var, const char *xpath_fmt, ...);
+
#endif /* _FRR_NORTHBOUND_WRAPPERS_H_ */
diff --git a/lib/zclient.c b/lib/zclient.c
index f809704f86..92a495ac61 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -2451,6 +2451,143 @@ int tm_release_table_chunk(struct zclient *zclient, uint32_t start,
return zclient_send_message(zclient);
}
+int zebra_send_mpls_labels(struct zclient *zclient, int cmd,
+ struct zapi_labels *zl)
+{
+ if (zapi_labels_encode(zclient->obuf, cmd, zl) < 0)
+ return -1;
+ return zclient_send_message(zclient);
+}
+
+int zapi_labels_encode(struct stream *s, int cmd, struct zapi_labels *zl)
+{
+ struct zapi_nexthop_label *znh;
+
+ stream_reset(s);
+
+ zclient_create_header(s, cmd, VRF_DEFAULT);
+ stream_putc(s, zl->message);
+ stream_putc(s, zl->type);
+ stream_putl(s, zl->local_label);
+
+ if (CHECK_FLAG(zl->message, ZAPI_LABELS_FTN)) {
+ stream_putw(s, zl->route.prefix.family);
+ stream_put_prefix(s, &zl->route.prefix);
+ stream_putc(s, zl->route.type);
+ stream_putw(s, zl->route.instance);
+ }
+
+ if (zl->nexthop_num > MULTIPATH_NUM) {
+ flog_err(
+ EC_LIB_ZAPI_ENCODE,
+ "%s: label %u: can't encode %u nexthops (maximum is %u)",
+ __func__, zl->local_label, zl->nexthop_num,
+ MULTIPATH_NUM);
+ return -1;
+ }
+ stream_putw(s, zl->nexthop_num);
+
+ for (int i = 0; i < zl->nexthop_num; i++) {
+ znh = &zl->nexthops[i];
+
+ stream_putc(s, znh->type);
+ stream_putw(s, znh->family);
+ switch (znh->family) {
+ case AF_INET:
+ stream_put_in_addr(s, &znh->address.ipv4);
+ break;
+ case AF_INET6:
+ stream_write(s, (uint8_t *)&znh->address.ipv6, 16);
+ break;
+ default:
+ break;
+ }
+ stream_putl(s, znh->ifindex);
+ stream_putl(s, znh->label);
+ }
+
+ /* Put length at the first point of the stream. */
+ stream_putw_at(s, 0, stream_get_endp(s));
+
+ return 0;
+}
+
+int zapi_labels_decode(struct stream *s, struct zapi_labels *zl)
+{
+ struct zapi_nexthop_label *znh;
+
+ memset(zl, 0, sizeof(*zl));
+
+ /* Get data. */
+ STREAM_GETC(s, zl->message);
+ STREAM_GETC(s, zl->type);
+ STREAM_GETL(s, zl->local_label);
+
+ if (CHECK_FLAG(zl->message, ZAPI_LABELS_FTN)) {
+ size_t psize;
+
+ STREAM_GETW(s, zl->route.prefix.family);
+ STREAM_GETC(s, zl->route.prefix.prefixlen);
+
+ psize = PSIZE(zl->route.prefix.prefixlen);
+ switch (zl->route.prefix.family) {
+ case AF_INET:
+ if (zl->route.prefix.prefixlen > IPV4_MAX_BITLEN) {
+ zlog_debug(
+ "%s: Specified prefix length %d is greater than a v4 address can support",
+ __PRETTY_FUNCTION__,
+ zl->route.prefix.prefixlen);
+ return -1;
+ }
+ STREAM_GET(&zl->route.prefix.u.prefix4.s_addr, s,
+ psize);
+ break;
+ case AF_INET6:
+ if (zl->route.prefix.prefixlen > IPV6_MAX_BITLEN) {
+ zlog_debug(
+ "%s: Specified prefix length %d is greater than a v6 address can support",
+ __PRETTY_FUNCTION__,
+ zl->route.prefix.prefixlen);
+ return -1;
+ }
+ STREAM_GET(&zl->route.prefix.u.prefix6, s, psize);
+ break;
+ default:
+ flog_err(EC_LIB_ZAPI_ENCODE,
+ "%s: Specified family %u is not v4 or v6",
+ __PRETTY_FUNCTION__, zl->route.prefix.family);
+ return -1;
+ }
+
+ STREAM_GETC(s, zl->route.type);
+ STREAM_GETW(s, zl->route.instance);
+ }
+
+ STREAM_GETW(s, zl->nexthop_num);
+ for (int i = 0; i < zl->nexthop_num; i++) {
+ znh = &zl->nexthops[i];
+
+ STREAM_GETC(s, znh->type);
+ STREAM_GETW(s, znh->family);
+ switch (znh->family) {
+ case AF_INET:
+ STREAM_GET(&znh->address.ipv4.s_addr, s,
+ IPV4_MAX_BYTELEN);
+ break;
+ case AF_INET6:
+ STREAM_GET(&znh->address.ipv6, s, 16);
+ break;
+ default:
+ break;
+ }
+ STREAM_GETL(s, znh->ifindex);
+ STREAM_GETL(s, znh->label);
+ }
+
+ return 0;
+stream_failure:
+ return -1;
+}
int zebra_send_pw(struct zclient *zclient, int command, struct zapi_pw *pw)
{
diff --git a/lib/zclient.h b/lib/zclient.h
index 81e454d192..eb3c97b111 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -126,6 +126,7 @@ typedef enum {
ZEBRA_INTERFACE_LINK_PARAMS,
ZEBRA_MPLS_LABELS_ADD,
ZEBRA_MPLS_LABELS_DELETE,
+ ZEBRA_MPLS_LABELS_REPLACE,
ZEBRA_IPMR_ROUTE_STATS,
ZEBRA_LABEL_MANAGER_CONNECT,
ZEBRA_LABEL_MANAGER_CONNECT_ASYNC,
@@ -395,6 +396,28 @@ struct zapi_route {
uint32_t tableid;
};
+struct zapi_nexthop_label {
+ enum nexthop_types_t type;
+ int family;
+ union g_addr address;
+ ifindex_t ifindex;
+ mpls_label_t label;
+};
+
+struct zapi_labels {
+ uint8_t message;
+#define ZAPI_LABELS_FTN 0x01
+ enum lsp_types_t type;
+ mpls_label_t local_label;
+ struct {
+ struct prefix prefix;
+ uint8_t type;
+ unsigned short instance;
+ } route;
+ uint16_t nexthop_num;
+ struct zapi_nexthop_label nexthops[MULTIPATH_NUM];
+};
+
struct zapi_pw {
char ifname[IF_NAMESIZE];
ifindex_t ifindex;
@@ -625,6 +648,12 @@ extern int tm_get_table_chunk(struct zclient *zclient, uint32_t chunk_size,
extern int tm_release_table_chunk(struct zclient *zclient, uint32_t start,
uint32_t end);
+extern int zebra_send_mpls_labels(struct zclient *zclient, int cmd,
+ struct zapi_labels *zl);
+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 zebra_send_pw(struct zclient *zclient, int command,
struct zapi_pw *pw);
extern void zebra_read_pw_status_update(ZAPI_CALLBACK_ARGS, struct zapi_pw_status *pw);