Skip to content

Commit

Permalink
Allow to allocate cache manager with custom refill socket
Browse files Browse the repository at this point in the history
Cache managers use two sockets: one for cache refill operation,
and another one for notifications.

In order to simulate NETLINK events by reading data from files,
we need to be able to overwrite callbacks for both sockets.

This new function allows us to set up refill socket any way we want.
It does have requirement that the refill socket be blocking.
  • Loading branch information
ievenbach committed Apr 24, 2024
1 parent 96ddcd9 commit 505da87
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 11 deletions.
4 changes: 4 additions & 0 deletions include/netlink/cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,10 @@ struct nl_cache_mngr;
extern int nl_cache_mngr_alloc(struct nl_sock *,
int, int,
struct nl_cache_mngr **);
extern int nl_cache_mngr_alloc_ex(struct nl_sock *,
struct nl_sock *,
int, int,
struct nl_cache_mngr **);
extern int nl_cache_mngr_add(struct nl_cache_mngr *,
const char *,
change_func_t,
Expand Down
47 changes: 36 additions & 11 deletions lib/cache_mngr.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,33 @@ static int event_input(struct nl_msg *msg, void *arg)
*/
int nl_cache_mngr_alloc(struct nl_sock *sk, int protocol, int flags,
struct nl_cache_mngr **result)
{
struct nl_sock *sk_blocking = nl_socket_alloc();
int err;

if (!sk_blocking) {
return -NLE_NOMEM;
}
if ((err = nl_connect(sk_blocking, protocol)) < 0) {
nl_socket_free(sk_blocking);
return err;
}
return nl_cache_mngr_alloc_ex(sk, sk_blocking, protocol, flags, result);
}

/**
* Allocate new cache manager, with custom callback on refill socket
* @arg sk Netlink socket or NULL to auto allocate
* @arg sk_blocking Blocking Netlink socket for cache refills
* @arg protocol Netlink protocol this manager is used for
* @arg flags Flags (\c NL_AUTO_PROVIDE)
* @arg result Result pointer
*
* Same as \f nl_cache_mngr_alloc, but sets custom refill socket
* Note: ownership of the sk_blocking passes to the cache manager
*/
int nl_cache_mngr_alloc_ex(struct nl_sock *sk, struct nl_sock *sk_blocking, int protocol, int flags,
struct nl_cache_mngr **result)
{
struct nl_cache_mngr *mngr;
int err = -NLE_NOMEM;
Expand All @@ -156,10 +183,18 @@ int nl_cache_mngr_alloc(struct nl_sock *sk, int protocol, int flags,
if (flags & NL_ALLOCATED_SOCK)
BUG();

if(!sk_blocking) {
BUG();
}

mngr = calloc(1, sizeof(*mngr));
if (!mngr)
if (!mngr) {
// No manager yet, to free it in case of error
nl_socket_free(sk_blocking);
return -NLE_NOMEM;
}

mngr->cm_sync_sock = sk_blocking;
if (!sk) {
if (!(sk = nl_socket_alloc()))
goto errout;
Expand All @@ -185,23 +220,13 @@ int nl_cache_mngr_alloc(struct nl_sock *sk, int protocol, int flags,
if ((err = nl_socket_set_nonblocking(mngr->cm_sock)) < 0)
goto errout;

/* Create and allocate socket for sync cache fills */
mngr->cm_sync_sock = nl_socket_alloc();
if (!mngr->cm_sync_sock) {
err = -NLE_NOMEM;
goto errout;
}
if ((err = nl_connect(mngr->cm_sync_sock, protocol)) < 0)
goto errout_free_sync_sock;

NL_DBG(1, "Allocated cache manager %p, protocol %d, %d caches\n",
mngr, protocol, mngr->cm_nassocs);

*result = mngr;
return 0;

errout_free_sync_sock:
nl_socket_free(mngr->cm_sync_sock);
errout:
nl_cache_mngr_free(mngr);
return err;
Expand Down
1 change: 1 addition & 0 deletions libnl-3.sym
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ global:
nl_cache_mngr_add;
nl_cache_mngr_add_cache;
nl_cache_mngr_alloc;
nl_cache_mngr_alloc_ex;
nl_cache_mngr_data_ready;
nl_cache_mngr_free;
nl_cache_mngr_get_fd;
Expand Down

0 comments on commit 505da87

Please sign in to comment.