/** * Add cache to cache manager * @arg mngr Cache manager. * @arg name Name of cache to keep track of * @arg cb Function to be called upon changes. * @arg data Argument passed on to change callback * @arg result Pointer to store added cache (optional) * * Allocates a new cache of the specified type and adds it to the manager. * The operation will trigger a full dump request from the kernel to * initially fill the contents of the cache. The manager will subscribe * to the notification group of the cache and keep track of any further * changes. * * The user is responsible for calling nl_cache_mngr_poll() or monitor * the socket and call nl_cache_mngr_data_ready() to allow the library * to process netlink notification events. * * @see nl_cache_mngr_poll() * @see nl_cache_mngr_data_ready() * * @return 0 on success or a negative error code. * @return -NLE_NOCACHE Unknown cache type * @return -NLE_PROTO_MISMATCH Protocol mismatch between cache manager and * cache type * @return -NLE_OPNOTSUPP Cache type does not support updates * @return -NLE_EXIST Cache of this type already being managed */ int nl_cache_mngr_add(struct nl_cache_mngr *mngr, const char *name, change_func_t cb, void *data, struct nl_cache **result) { struct nl_cache_ops *ops; struct nl_cache *cache; int err; ops = nl_cache_ops_lookup_safe(name); if (!ops) return -NLE_NOCACHE; cache = nl_cache_alloc(ops); nl_cache_ops_put(ops); if (!cache) return -NLE_NOMEM; err = nl_cache_mngr_add_cache(mngr, cache, cb, data); if (err < 0) goto errout_free_cache; *result = cache; return 0; errout_free_cache: nl_cache_free(cache); return err; }
/** * Add cache to cache manager * @arg mngr Cache manager. * @arg cache Cache to be added to cache manager * @arg cb V2 function to be called upon changes. * @arg data Argument passed on to change callback * * Adds cache to the manager. The operation will trigger a full * dump request from the kernel to initially fill the contents * of the cache. The manager will subscribe to the notification group * of the cache and keep track of any further changes. * * The user is responsible for calling nl_cache_mngr_poll() or monitor * the socket and call nl_cache_mngr_data_ready() to allow the library * to process netlink notification events. * * @see nl_cache_mngr_poll() * @see nl_cache_mngr_data_ready() * * @return 0 on success or a negative error code. * @return -NLE_PROTO_MISMATCH Protocol mismatch between cache manager and * cache type * @return -NLE_OPNOTSUPP Cache type does not support updates * @return -NLE_EXIST Cache of this type already being managed */ int nl_cache_mngr_add_cache_v2(struct nl_cache_mngr *mngr, struct nl_cache *cache, change_func_v2_t cb, void *data) { int err; err = nl_cache_mngr_add_cache(mngr, cache, NULL, NULL); if (err < 0) return err; return nl_cache_mngr_set_change_func_v2(mngr, cache, cb, data); }
void NetlinkManager::registerWNetlink() { initDumpParams(); nlResources_ = std::make_unique<NlResources>(); auto errCode = nl_cache_mngr_add_cache( nlResources_->manager, nlResources_->routeCache, netlinkRouteUpdated, this); checkError(errCode, "Failed to add route cache to cache manager"); VLOG(1) << "Added route cache to cache manager"; return; }
static J4statusPluginContext * _j4status_nl_init(J4statusCoreInterface *core) { gchar **interfaces = NULL; guint64 addresses = ADDRESSES_ALL; GKeyFile *key_file; key_file = j4status_config_get_key_file("Netlink"); if ( key_file != NULL ) { interfaces = g_key_file_get_string_list(key_file, "Netlink", "Interfaces", NULL, NULL); j4status_config_key_file_get_enum(key_file, "Netlink", "Addresses", _j4status_nl_addresses, G_N_ELEMENTS(_j4status_nl_addresses), &addresses); g_key_file_free(key_file); } if ( interfaces == NULL ) { g_message("No interface to monitor, aborting"); return NULL; } gint err; J4statusPluginContext *self; self = g_new0(J4statusPluginContext, 1); self->addresses = addresses; self->sections = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, _j4status_nl_section_free); self->source = g_water_nl_source_new_cache_mngr(NULL, NETLINK_ROUTE, NL_AUTO_PROVIDE, &err); if ( self->source == NULL ) { g_warning("Couldn't subscribe to events: %s", nl_geterror(err)); goto error; } self->sock = g_water_nl_source_get_sock(self->source); self->cache_mngr = g_water_nl_source_get_cache_mngr(self->source); err = rtnl_link_alloc_cache(self->sock, AF_UNSPEC, &self->link_cache); if ( err < 0 ) { g_warning("Couldn't allocate links cache: %s", nl_geterror(err)); goto error; } err = nl_cache_mngr_add_cache(self->cache_mngr, self->link_cache, _j4status_nl_cache_change, self); if ( err < 0 ) { g_warning("Couldn't manage links cache: %s", nl_geterror(err)); goto error; } err = rtnl_addr_alloc_cache(self->sock, &self->addr_cache); if ( err < 0 ) { g_warning("Couldn't allocate addresses cache: %s", nl_geterror(err)); goto error; } err = nl_cache_mngr_add_cache(self->cache_mngr, self->addr_cache, _j4status_nl_cache_change, self); if ( err < 0 ) { g_warning("Couldn't manage addresses cache: %s", nl_geterror(err)); goto error; } gchar **interface; for ( interface = interfaces ; *interface != NULL ; ++interface ) { J4statusNlSection *section; section = _j4status_nl_section_new(self, core, *interface); if ( section != NULL ) g_hash_table_insert(self->sections, GINT_TO_POINTER(section->ifindex), section); else g_free(*interface); } g_free(interfaces); if ( g_hash_table_size(self->sections) < 1 ) goto error; self->formats.up = j4status_format_string_parse(NULL, _j4status_nl_format_up_tokens, G_N_ELEMENTS(_j4status_nl_format_up_tokens), J4STATUS_NL_DEFAULT_UP_FORMAT, NULL); self->formats.down = j4status_format_string_parse(NULL, NULL, 0, J4STATUS_NL_DEFAULT_DOWN_FORMAT, NULL); return self; error: _j4status_nl_uninit(self); return NULL; }