summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/command.h2
-rw-r--r--lib/event.c116
-rw-r--r--lib/frrevent.h6
-rw-r--r--lib/prefix.h40
-rw-r--r--lib/srv6.h55
5 files changed, 129 insertions, 90 deletions
diff --git a/lib/command.h b/lib/command.h
index 3167c652c5..718d34b007 100644
--- a/lib/command.h
+++ b/lib/command.h
@@ -172,6 +172,8 @@ enum node_type {
OPENFABRIC_NODE, /* OpenFabric router configuration node */
VRRP_NODE, /* VRRP node */
BMP_NODE, /* BMP config under router bgp */
+ ISIS_SRV6_NODE, /* ISIS SRv6 node */
+ ISIS_SRV6_NODE_MSD_NODE, /* ISIS SRv6 Node MSDs node */
NODE_TYPE_MAX, /* maximum */
};
/* clang-format on */
diff --git a/lib/event.c b/lib/event.c
index 4b4ca9d7ea..37a30d2511 100644
--- a/lib/event.c
+++ b/lib/event.c
@@ -89,34 +89,41 @@ unsigned long walltime_threshold = CONSUMED_TIME_CHECK;
/* CLI start ---------------------------------------------------------------- */
#include "lib/event_clippy.c"
-static unsigned int cpu_record_hash_key(const struct cpu_event_history *a)
+static uint32_t cpu_record_hash_key(const struct cpu_event_history *a)
{
int size = sizeof(a->func);
return jhash(&a->func, size, 0);
}
-static bool cpu_record_hash_cmp(const struct cpu_event_history *a,
- const struct cpu_event_history *b)
+static int cpu_record_hash_cmp(const struct cpu_event_history *a,
+ const struct cpu_event_history *b)
{
- return a->func == b->func;
+ return numcmp((uintptr_t)a->func, (uintptr_t)b->func);
}
-static void *cpu_record_hash_alloc(struct cpu_event_history *a)
+DECLARE_HASH(cpu_records, struct cpu_event_history, item, cpu_record_hash_cmp,
+ cpu_record_hash_key);
+
+static struct cpu_event_history *cpu_records_get(struct event_loop *loop,
+ void (*func)(struct event *e),
+ const char *funcname)
{
- struct cpu_event_history *new;
+ struct cpu_event_history ref = { .func = func }, *res;
- new = XCALLOC(MTYPE_EVENT_STATS, sizeof(struct cpu_event_history));
- new->func = a->func;
- new->funcname = a->funcname;
- return new;
+ res = cpu_records_find(loop->cpu_records, &ref);
+ if (!res) {
+ res = XCALLOC(MTYPE_EVENT_STATS, sizeof(*res));
+ res->func = func;
+ res->funcname = funcname;
+ cpu_records_add(loop->cpu_records, res);
+ }
+ return res;
}
-static void cpu_record_hash_free(void *a)
+static void cpu_records_free(struct cpu_event_history **p)
{
- struct cpu_event_history *hist = a;
-
- XFREE(MTYPE_EVENT_STATS, hist);
+ XFREE(MTYPE_EVENT_STATS, *p);
}
static void vty_out_cpu_event_history(struct vty *vty,
@@ -136,14 +143,11 @@ static void vty_out_cpu_event_history(struct vty *vty,
a->types & (1 << EVENT_EXECUTE) ? 'X' : ' ', a->funcname);
}
-static void cpu_record_hash_print(struct hash_bucket *bucket, void *args[])
+static void cpu_record_print_one(struct vty *vty, uint8_t filter,
+ struct cpu_event_history *totals,
+ const struct cpu_event_history *a)
{
- struct cpu_event_history *totals = args[0];
struct cpu_event_history copy;
- struct vty *vty = args[1];
- uint8_t *filter = args[2];
-
- struct cpu_event_history *a = bucket->data;
copy.total_active =
atomic_load_explicit(&a->total_active, memory_order_seq_cst);
@@ -165,7 +169,7 @@ static void cpu_record_hash_print(struct hash_bucket *bucket, void *args[])
copy.types = atomic_load_explicit(&a->types, memory_order_seq_cst);
copy.funcname = a->funcname;
- if (!(copy.types & *filter))
+ if (!(copy.types & filter))
return;
vty_out_cpu_event_history(vty, &copy);
@@ -185,7 +189,6 @@ static void cpu_record_hash_print(struct hash_bucket *bucket, void *args[])
static void cpu_record_print(struct vty *vty, uint8_t filter)
{
struct cpu_event_history tmp;
- void *args[3] = {&tmp, vty, &filter};
struct event_loop *m;
struct listnode *ln;
@@ -222,13 +225,13 @@ static void cpu_record_print(struct vty *vty, uint8_t filter)
vty_out(vty,
" CPU_Warn Wall_Warn Starv_Warn Type Thread\n");
- if (m->cpu_record->count)
- hash_iterate(
- m->cpu_record,
- (void (*)(struct hash_bucket *,
- void *))cpu_record_hash_print,
- args);
- else
+ if (cpu_records_count(m->cpu_records)) {
+ struct cpu_event_history *rec;
+
+ frr_each (cpu_records, m->cpu_records, rec)
+ cpu_record_print_one(vty, filter, &tmp,
+ rec);
+ } else
vty_out(vty, "No data to display yet.\n");
vty_out(vty, "\n");
@@ -248,35 +251,29 @@ static void cpu_record_print(struct vty *vty, uint8_t filter)
vty_out_cpu_event_history(vty, &tmp);
}
-static void cpu_record_hash_clear(struct hash_bucket *bucket, void *args[])
-{
- uint8_t *filter = args[0];
- struct hash *cpu_record = args[1];
-
- struct cpu_event_history *a = bucket->data;
-
- if (!(a->types & *filter))
- return;
-
- hash_release(cpu_record, bucket->data);
-}
-
static void cpu_record_clear(uint8_t filter)
{
- uint8_t *tmp = &filter;
struct event_loop *m;
struct listnode *ln;
frr_with_mutex (&masters_mtx) {
for (ALL_LIST_ELEMENTS_RO(masters, ln, m)) {
frr_with_mutex (&m->mtx) {
- void *args[2] = {tmp, m->cpu_record};
+ struct cpu_event_history *item;
+ struct cpu_records_head old[1];
+
+ cpu_records_init(old);
+ cpu_records_swap_all(old, m->cpu_records);
- hash_iterate(
- m->cpu_record,
- (void (*)(struct hash_bucket *,
- void *))cpu_record_hash_clear,
- args);
+ while ((item = cpu_records_pop(old))) {
+ if (item->types & filter)
+ cpu_records_free(&item);
+ else
+ cpu_records_add(m->cpu_records,
+ item);
+ }
+
+ cpu_records_fini(old);
}
}
}
@@ -565,10 +562,7 @@ struct event_loop *event_master_create(const char *name)
snprintf(tmhashname, sizeof(tmhashname), "%s - threadmaster event hash",
name);
- rv->cpu_record = hash_create_size(
- 8, (unsigned int (*)(const void *))cpu_record_hash_key,
- (bool (*)(const void *, const void *))cpu_record_hash_cmp,
- tmhashname);
+ cpu_records_init(rv->cpu_records);
event_list_init(&rv->event);
event_list_init(&rv->ready);
@@ -686,6 +680,7 @@ void event_master_free_unused(struct event_loop *m)
/* Stop thread scheduler. */
void event_master_free(struct event_loop *m)
{
+ struct cpu_event_history *record;
struct event *t;
frr_with_mutex (&masters_mtx) {
@@ -708,7 +703,9 @@ void event_master_free(struct event_loop *m)
list_delete(&m->cancel_req);
m->cancel_req = NULL;
- hash_clean_and_free(&m->cpu_record, cpu_record_hash_free);
+ while ((record = cpu_records_pop(m->cpu_records)))
+ cpu_records_free(&record);
+ cpu_records_fini(m->cpu_records);
XFREE(MTYPE_EVENT_MASTER, m->name);
XFREE(MTYPE_EVENT_MASTER, m->handler.pfds);
@@ -781,7 +778,6 @@ static struct event *thread_get(struct event_loop *m, uint8_t type,
const struct xref_eventsched *xref)
{
struct event *thread = event_list_pop(&m->unuse);
- struct cpu_event_history tmp;
if (!thread) {
thread = XCALLOC(MTYPE_THREAD, sizeof(struct event));
@@ -809,13 +805,9 @@ static struct event *thread_get(struct event_loop *m, uint8_t type,
* hash_get lookups.
*/
if ((thread->xref && thread->xref->funcname != xref->funcname)
- || thread->func != func) {
- tmp.func = func;
- tmp.funcname = xref->funcname;
- thread->hist =
- hash_get(m->cpu_record, &tmp,
- (void *(*)(void *))cpu_record_hash_alloc);
- }
+ || thread->func != func)
+ thread->hist = cpu_records_get(m, func, xref->funcname);
+
thread->hist->total_active++;
thread->func = func;
thread->xref = xref;
diff --git a/lib/frrevent.h b/lib/frrevent.h
index fe33ffd1f2..ab779d9088 100644
--- a/lib/frrevent.h
+++ b/lib/frrevent.h
@@ -65,6 +65,8 @@ struct xref_eventsched {
uint32_t event_type;
};
+PREDECL_HASH(cpu_records);
+
/* Master of the theads. */
struct event_loop {
char *name;
@@ -76,7 +78,7 @@ struct event_loop {
struct list *cancel_req;
bool canceled;
pthread_cond_t cancel_cond;
- struct hash *cpu_record;
+ struct cpu_records_head cpu_records[1];
int io_pipe[2];
int fd_limit;
struct fd_handler handler;
@@ -130,6 +132,8 @@ struct event {
#endif
struct cpu_event_history {
+ struct cpu_records_item item;
+
void (*func)(struct event *e);
atomic_size_t total_cpu_warn;
atomic_size_t total_wall_warn;
diff --git a/lib/prefix.h b/lib/prefix.h
index 7ca525e762..fc6e32dd54 100644
--- a/lib/prefix.h
+++ b/lib/prefix.h
@@ -377,9 +377,9 @@ static inline void ipv4_addr_copy(struct in_addr *dst,
#endif /*s6_addr32*/
/* Prototypes. */
-extern int str2family(const char *);
-extern int afi2family(afi_t);
-extern afi_t family2afi(int);
+extern int str2family(const char *string);
+extern int afi2family(afi_t afi);
+extern afi_t family2afi(int family);
extern const char *family2str(int family);
extern const char *safi2str(safi_t safi);
extern const char *afi2str(afi_t afi);
@@ -409,14 +409,15 @@ extern void prefix_free(struct prefix **p);
extern void prefix_free_lists(void *arg);
extern const char *prefix_family_str(union prefixconstptr pu);
extern int prefix_blen(union prefixconstptr pu);
-extern int str2prefix(const char *, struct prefix *);
+extern int str2prefix(const char *string, struct prefix *prefix);
#define PREFIX2STR_BUFFER PREFIX_STRLEN
extern void prefix_mcast_inet4_dump(const char *onfail, struct in_addr addr,
char *buf, int buf_size);
extern const char *prefix_sg2str(const struct prefix_sg *sg, char *str);
-extern const char *prefix2str(union prefixconstptr, char *, int);
+extern const char *prefix2str(union prefixconstptr upfx, char *buffer,
+ int size);
extern int evpn_type5_prefix_match(const struct prefix *evpn_pfx,
const struct prefix *match_pfx);
extern int prefix_match(union prefixconstptr unet, union prefixconstptr upfx);
@@ -437,36 +438,37 @@ extern bool evpn_addr_same(const struct evpn_addr *e1, const struct evpn_addr *e
#define prefix_copy(a, b) ({ memset(a, 0, sizeof(*a)); prefix_copy(a, b); })
#endif
-extern struct prefix *sockunion2hostprefix(const union sockunion *,
+extern struct prefix *sockunion2hostprefix(const union sockunion *su,
struct prefix *p);
-extern void prefix2sockunion(const struct prefix *, union sockunion *);
+extern void prefix2sockunion(const struct prefix *p, union sockunion *su);
-extern int str2prefix_eth(const char *, struct prefix_eth *);
+extern int str2prefix_eth(const char *string, struct prefix_eth *p);
extern struct prefix_ipv4 *prefix_ipv4_new(void);
extern void prefix_ipv4_free(struct prefix_ipv4 **p);
-extern int str2prefix_ipv4(const char *, struct prefix_ipv4 *);
-extern void apply_mask_ipv4(struct prefix_ipv4 *);
+extern int str2prefix_ipv4(const char *string, struct prefix_ipv4 *p);
+extern void apply_mask_ipv4(struct prefix_ipv4 *p);
-extern int prefix_ipv4_any(const struct prefix_ipv4 *);
-extern void apply_classful_mask_ipv4(struct prefix_ipv4 *);
+extern int prefix_ipv4_any(const struct prefix_ipv4 *p);
+extern void apply_classful_mask_ipv4(struct prefix_ipv4 *p);
-extern uint8_t ip_masklen(struct in_addr);
-extern void masklen2ip(const int, struct in_addr *);
+extern uint8_t ip_masklen(struct in_addr addr);
+extern void masklen2ip(const int length, struct in_addr *addr);
/* given the address of a host on a network and the network mask length,
* calculate the broadcast address for that network;
* special treatment for /31 according to RFC3021 section 3.3 */
extern in_addr_t ipv4_broadcast_addr(in_addr_t hostaddr, int masklen);
-extern int netmask_str2prefix_str(const char *, const char *, char *, size_t);
+extern int netmask_str2prefix_str(const char *net_str, const char *mask_str,
+ char *prefix_str, size_t prefix_str_len);
extern struct prefix_ipv6 *prefix_ipv6_new(void);
extern void prefix_ipv6_free(struct prefix_ipv6 **p);
-extern int str2prefix_ipv6(const char *, struct prefix_ipv6 *);
-extern void apply_mask_ipv6(struct prefix_ipv6 *);
+extern int str2prefix_ipv6(const char *str, struct prefix_ipv6 *p);
+extern void apply_mask_ipv6(struct prefix_ipv6 *p);
-extern int ip6_masklen(struct in6_addr);
-extern void masklen2ip6(const int, struct in6_addr *);
+extern int ip6_masklen(struct in6_addr netmask);
+extern void masklen2ip6(const int masklen, struct in6_addr *netmask);
extern int is_zero_mac(const struct ethaddr *mac);
extern bool is_mcast_mac(const struct ethaddr *mac);
diff --git a/lib/srv6.h b/lib/srv6.h
index 0d3ee7d2ff..7c8c6b4a65 100644
--- a/lib/srv6.h
+++ b/lib/srv6.h
@@ -24,6 +24,16 @@ extern "C" {
#define sid2str(sid, str, size) \
inet_ntop(AF_INET6, sid, str, size)
+/* SRv6 flavors manipulation macros */
+#define CHECK_SRV6_FLV_OP(OPS,OP) ((OPS) & (1 << OP))
+#define SET_SRV6_FLV_OP(OPS,OP) (OPS) |= (1 << OP)
+#define UNSET_SRV6_FLV_OP(OPS,OP) (OPS) &= ~(1 << OP)
+#define RESET_SRV6_FLV_OP(OPS) (OPS) = 0
+
+/* SRv6 Flavors default values */
+#define ZEBRA_DEFAULT_SEG6_LOCAL_FLV_LCBLOCK_LEN 32
+#define ZEBRA_DEFAULT_SEG6_LOCAL_FLV_LCNODE_FN_LEN 16
+
enum seg6_mode_t {
INLINE,
ENCAP,
@@ -50,15 +60,40 @@ enum seg6local_action_t {
ZEBRA_SEG6_LOCAL_ACTION_END_DT46 = 16,
};
+/* Flavor operations for SRv6 End* Behaviors */
+enum seg6local_flavor_op {
+ ZEBRA_SEG6_LOCAL_FLV_OP_UNSPEC = 0,
+ /* PSP Flavor as per RFC 8986 section #4.16.1 */
+ ZEBRA_SEG6_LOCAL_FLV_OP_PSP = 1,
+ /* USP Flavor as per RFC 8986 section #4.16.2 */
+ ZEBRA_SEG6_LOCAL_FLV_OP_USP = 2,
+ /* USD Flavor as per RFC 8986 section #4.16.3 */
+ ZEBRA_SEG6_LOCAL_FLV_OP_USD = 3,
+ /* NEXT-C-SID Flavor as per draft-ietf-spring-srv6-srh-compression-03
+ section 4.1 */
+ ZEBRA_SEG6_LOCAL_FLV_OP_NEXT_CSID = 4,
+};
+
struct seg6_segs {
size_t num_segs;
struct in6_addr segs[256];
};
+struct seg6local_flavors_info {
+ /* Flavor operations */
+ uint32_t flv_ops;
+
+ /* Locator-Block length, expressed in bits */
+ uint8_t lcblock_len;
+ /* Locator-Node Function length, expressed in bits */
+ uint8_t lcnode_func_len;
+};
+
struct seg6local_context {
struct in_addr nh4;
struct in6_addr nh6;
uint32_t table;
+ struct seg6local_flavors_info flv;
};
struct srv6_locator {
@@ -115,14 +150,18 @@ struct srv6_locator_chunk {
* https://www.iana.org/assignments/segment-routing/segment-routing.xhtml
*/
enum srv6_endpoint_behavior_codepoint {
- SRV6_ENDPOINT_BEHAVIOR_RESERVED = 0x0000,
- SRV6_ENDPOINT_BEHAVIOR_END_DT6 = 0x0012,
- SRV6_ENDPOINT_BEHAVIOR_END_DT4 = 0x0013,
- SRV6_ENDPOINT_BEHAVIOR_END_DT46 = 0x0014,
- SRV6_ENDPOINT_BEHAVIOR_END_DT6_USID = 0x003E,
- SRV6_ENDPOINT_BEHAVIOR_END_DT4_USID = 0x003F,
- SRV6_ENDPOINT_BEHAVIOR_END_DT46_USID = 0x0040,
- SRV6_ENDPOINT_BEHAVIOR_OPAQUE = 0xFFFF,
+ SRV6_ENDPOINT_BEHAVIOR_RESERVED = 0x0000,
+ SRV6_ENDPOINT_BEHAVIOR_END = 0x0001,
+ SRV6_ENDPOINT_BEHAVIOR_END_X = 0x0005,
+ SRV6_ENDPOINT_BEHAVIOR_END_DT6 = 0x0012,
+ SRV6_ENDPOINT_BEHAVIOR_END_DT4 = 0x0013,
+ SRV6_ENDPOINT_BEHAVIOR_END_DT46 = 0x0014,
+ SRV6_ENDPOINT_BEHAVIOR_END_NEXT_CSID = 0x002B,
+ SRV6_ENDPOINT_BEHAVIOR_END_X_NEXT_CSID = 0x002C,
+ SRV6_ENDPOINT_BEHAVIOR_END_DT6_USID = 0x003E,
+ SRV6_ENDPOINT_BEHAVIOR_END_DT4_USID = 0x003F,
+ SRV6_ENDPOINT_BEHAVIOR_END_DT46_USID = 0x0040,
+ SRV6_ENDPOINT_BEHAVIOR_OPAQUE = 0xFFFF,
};
struct nexthop_srv6 {