325fea5c57
Can be used to reserve worst case length using udebug_entry_append, then setting the final length using udebug_entry_set_length Signed-off-by: Felix Fietkau <nbd@nbd.name>
198 lines
5.3 KiB
C
198 lines
5.3 KiB
C
/*
|
|
* udebug - debug ring buffer library
|
|
*
|
|
* Copyright (C) 2023 Felix Fietkau <nbd@nbd.name>
|
|
*
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
* copyright notice and this permission notice appear in all copies.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
#ifndef __UDEBUG_RINGBUF_H
|
|
#define __UDEBUG_RINGBUF_H
|
|
|
|
#include <sys/types.h>
|
|
#include <stdint.h>
|
|
#include <stdarg.h>
|
|
|
|
#include "list.h"
|
|
#include "uloop.h"
|
|
#include "avl.h"
|
|
|
|
#define UDEBUG_SOCK_NAME "/var/run/udebug.sock"
|
|
|
|
enum udebug_format {
|
|
UDEBUG_FORMAT_PACKET,
|
|
UDEBUG_FORMAT_STRING,
|
|
UDEBUG_FORMAT_BLOBMSG,
|
|
};
|
|
|
|
enum {
|
|
UDEBUG_DLT_ETHERNET = 1,
|
|
UDEBUG_DLT_PPP = 50,
|
|
UDEBUG_DLT_RAW_IP = 101,
|
|
UDEBUG_DLT_IEEE_802_11 = 105,
|
|
UDEBUG_DLT_IEEE_802_11_RADIOTAP = 127,
|
|
UDEBUG_DLT_NETLINK = 253,
|
|
};
|
|
|
|
enum udebug_meta_type {
|
|
UDEBUG_META_IFACE_NAME,
|
|
UDEBUG_META_IFACE_DESC,
|
|
__UDEBUG_META_MAX
|
|
};
|
|
|
|
#define UDEBUG_TS_MSEC 1000ULL
|
|
#define UDEBUG_TS_SEC (1000ULL * UDEBUG_TS_MSEC)
|
|
|
|
struct udebug;
|
|
struct udebug_hdr;
|
|
|
|
struct udebug_buf_flag {
|
|
const char *name;
|
|
uint64_t mask;
|
|
};
|
|
|
|
struct udebug_buf_meta {
|
|
const char *name;
|
|
enum udebug_format format;
|
|
uint32_t sub_format; /* linktype for UDEBUG_FORMAT_PACKET */
|
|
const struct udebug_buf_flag *flags;
|
|
unsigned int n_flags;
|
|
};
|
|
|
|
struct udebug_buf {
|
|
struct udebug *ctx;
|
|
const struct udebug_buf_meta *meta;
|
|
uint32_t id;
|
|
|
|
struct list_head list;
|
|
|
|
struct udebug_hdr *hdr;
|
|
void *data;
|
|
size_t data_size;
|
|
size_t head_size;
|
|
size_t ring_size;
|
|
int fd;
|
|
};
|
|
|
|
struct udebug_packet_info {
|
|
const char *attr[__UDEBUG_META_MAX];
|
|
};
|
|
|
|
struct udebug_remote_buf {
|
|
struct avl_node node;
|
|
struct udebug_buf buf;
|
|
bool poll;
|
|
uint32_t head;
|
|
|
|
/* provided by user */
|
|
uint32_t pcap_iface;
|
|
void *priv;
|
|
const struct udebug_packet_info *meta;
|
|
};
|
|
|
|
struct udebug {
|
|
struct list_head local_rings;
|
|
struct avl_tree remote_rings;
|
|
uint32_t next_id;
|
|
struct uloop_fd fd;
|
|
int poll_handle;
|
|
char *socket_path;
|
|
struct uloop_timeout reconnect;
|
|
|
|
/* filled by user */
|
|
void (*notify_cb)(struct udebug *ctx, struct udebug_remote_buf *rb);
|
|
};
|
|
|
|
struct udebug_ptr {
|
|
uint32_t start;
|
|
uint32_t len;
|
|
uint64_t timestamp;
|
|
};
|
|
|
|
struct udebug_snapshot {
|
|
struct udebug_ptr *entries;
|
|
unsigned int n_entries;
|
|
unsigned int dropped;
|
|
void *data;
|
|
size_t data_size;
|
|
|
|
uint32_t iter_idx;
|
|
|
|
enum udebug_format format;
|
|
uint32_t sub_format;
|
|
|
|
uint32_t rbuf_idx;
|
|
};
|
|
|
|
struct udebug_iter {
|
|
struct udebug_snapshot **list;
|
|
size_t n;
|
|
|
|
struct udebug_snapshot *s;
|
|
unsigned int s_idx;
|
|
|
|
uint64_t timestamp;
|
|
void *data;
|
|
size_t len;
|
|
};
|
|
|
|
uint64_t udebug_timestamp(void);
|
|
|
|
void udebug_entry_init_ts(struct udebug_buf *buf, uint64_t timestamp);
|
|
static inline void udebug_entry_init(struct udebug_buf *buf)
|
|
{
|
|
udebug_entry_init_ts(buf, udebug_timestamp());
|
|
}
|
|
void *udebug_entry_append(struct udebug_buf *buf, const void *data, uint32_t len);
|
|
int udebug_entry_printf(struct udebug_buf *buf, const char *fmt, ...)
|
|
__attribute__ ((format (printf, 2, 3)));
|
|
int udebug_entry_vprintf(struct udebug_buf *buf, const char *fmt, va_list ap)
|
|
__attribute__ ((format (printf, 2, 0)));
|
|
uint16_t udebug_entry_trim(struct udebug_buf *buf, uint16_t len);
|
|
void udebug_entry_set_length(struct udebug_buf *buf, uint16_t len);
|
|
void udebug_entry_add(struct udebug_buf *buf);
|
|
|
|
int udebug_buf_init(struct udebug_buf *buf, size_t entries, size_t size);
|
|
int udebug_buf_add(struct udebug *ctx, struct udebug_buf *buf,
|
|
const struct udebug_buf_meta *meta);
|
|
uint64_t udebug_buf_flags(struct udebug_buf *buf);
|
|
void udebug_buf_free(struct udebug_buf *buf);
|
|
|
|
struct udebug_remote_buf *udebug_remote_buf_get(struct udebug *ctx, uint32_t id);
|
|
int udebug_remote_buf_map(struct udebug *ctx, struct udebug_remote_buf *rb, uint32_t id);
|
|
void udebug_remote_buf_unmap(struct udebug *ctx, struct udebug_remote_buf *rb);
|
|
int udebug_remote_buf_set_poll(struct udebug *ctx, struct udebug_remote_buf *rb, bool val);
|
|
void udebug_remote_buf_set_flags(struct udebug_remote_buf *rb, uint64_t mask, uint64_t set);
|
|
struct udebug_snapshot *udebug_remote_buf_snapshot(struct udebug_remote_buf *rb);
|
|
bool udebug_snapshot_get_entry(struct udebug_snapshot *s, struct udebug_iter *it, unsigned int entry);
|
|
|
|
void udebug_remote_buf_set_start_time(struct udebug_remote_buf *rb, uint64_t ts);
|
|
void udebug_remote_buf_set_start_offset(struct udebug_remote_buf *rb, uint32_t idx);
|
|
|
|
void udebug_iter_start(struct udebug_iter *it, struct udebug_snapshot **s, size_t n);
|
|
bool udebug_iter_next(struct udebug_iter *it);
|
|
|
|
void udebug_init(struct udebug *ctx);
|
|
int udebug_connect(struct udebug *ctx, const char *path);
|
|
void udebug_auto_connect(struct udebug *ctx, const char *path);
|
|
void udebug_add_uloop(struct udebug *ctx);
|
|
void udebug_poll(struct udebug *ctx);
|
|
void udebug_free(struct udebug *ctx);
|
|
|
|
static inline bool udebug_is_connected(struct udebug *ctx)
|
|
{
|
|
return ctx->fd.fd >= 0;
|
|
}
|
|
|
|
int udebug_id_cmp(const void *k1, const void *k2, void *ptr);
|
|
|
|
#endif
|