nl_bridge::nl_bridge(switch_interface *sw, std::shared_ptr<tap_manager> tap_man, cnetlink *nl, std::shared_ptr<nl_vxlan> vxlan) : bridge(nullptr), sw(sw), tap_man(tap_man), nl(nl), vxlan(vxlan), l2_cache(nl_cache_alloc(nl_cache_ops_lookup("route/neigh")), nl_cache_free) { memset(&empty_br_vlan, 0, sizeof(rtnl_link_bridge_vlan)); memset(&vxlan_dom_bitmap, 0, sizeof(vxlan_dom_bitmap)); }
struct nl_cache *__nl_cache_mngt_require(const char *name) { struct nl_cache_ops *ops; ops = nl_cache_ops_lookup(name); if (ops) return ops->co_major_cache; return NULL; }
/** * Register a set of cache operations * @arg ops cache operations * * Called by users of caches to announce the avaibility of * a certain cache type. * * @return 0 on success or a negative error code. */ int nl_cache_mngt_register(struct nl_cache_ops *ops) { if (!ops->co_name || !ops->co_obj_ops) return -NLE_INVAL; if (nl_cache_ops_lookup(ops->co_name)) return -NLE_EXIST; ops->co_next = cache_ops; cache_ops = ops; NL_DBG(1, "Registered cache operations %s\n", ops->co_name); return 0; }
/** * Add cache responsibility 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; struct nl_af_group *grp; int err, i; ops = nl_cache_ops_lookup(name); if (!ops) return -NLE_NOCACHE; if (ops->co_protocol != mngr->cm_protocol) return -NLE_PROTO_MISMATCH; if (ops->co_groups == NULL) return -NLE_OPNOTSUPP; for (i = 0; i < mngr->cm_nassocs; i++) if (mngr->cm_assocs[i].ca_cache && mngr->cm_assocs[i].ca_cache->c_ops == ops) return -NLE_EXIST; retry: for (i = 0; i < mngr->cm_nassocs; i++) if (!mngr->cm_assocs[i].ca_cache) break; if (i >= mngr->cm_nassocs) { mngr->cm_nassocs += NASSOC_EXPAND; mngr->cm_assocs = realloc(mngr->cm_assocs, mngr->cm_nassocs * sizeof(struct nl_cache_assoc)); if (mngr->cm_assocs == NULL) return -NLE_NOMEM; memset(mngr->cm_assocs + (mngr->cm_nassocs - NASSOC_EXPAND), 0, NASSOC_EXPAND * sizeof(struct nl_cache_assoc)); NL_DBG(1, "Increased capacity of cache manager %p " \ "to %d\n", mngr, mngr->cm_nassocs); goto retry; } cache = nl_cache_alloc(ops); if (!cache) return -NLE_NOMEM; for (grp = ops->co_groups; grp->ag_group; grp++) { err = nl_socket_add_membership(mngr->cm_sock, grp->ag_group); if (err < 0) goto errout_free_cache; } err = nl_cache_refill(mngr->cm_sock, cache); if (err < 0) goto errout_drop_membership; mngr->cm_assocs[i].ca_cache = cache; mngr->cm_assocs[i].ca_change = cb; mngr->cm_assocs[i].ca_change_data = data; if (mngr->cm_flags & NL_AUTO_PROVIDE) nl_cache_mngt_provide(cache); NL_DBG(1, "Added cache %p <%s> to cache manager %p\n", cache, nl_cache_name(cache), mngr); if (result) *result = cache; return 0; errout_drop_membership: for (grp = ops->co_groups; grp->ag_group; grp++) nl_socket_drop_membership(mngr->cm_sock, grp->ag_group); errout_free_cache: nl_cache_free(cache); return err; }