Functions | |
struct nl_cache_mngr * | nl_cache_mngr_alloc (struct nl_handle *handle, int protocol, int flags) |
Allocate new cache manager. | |
struct nl_cache * | nl_cache_mngr_add (struct nl_cache_mngr *mngr, const char *name, change_func_t cb) |
Add cache responsibility to cache manager. | |
int | nl_cache_mngr_get_fd (struct nl_cache_mngr *mngr) |
Get file descriptor. | |
int | nl_cache_mngr_poll (struct nl_cache_mngr *mngr, int timeout) |
Check for event notifications. | |
int | nl_cache_mngr_data_ready (struct nl_cache_mngr *mngr) |
Receive available event notifications. | |
void | nl_cache_mngr_free (struct nl_cache_mngr *mngr) |
Free cache manager. |
App libnl Kernel
| |
+-----------------+ [ notification, link change ]
| | Cache Manager | | [ (IFF_UP | IFF_RUNNING) ]
| | |
| | +------------+| | | [ notification, new addr ]
<-------|---| route/link |<-------(async)--+ [ 10.0.1.1/32 dev eth1 ]
| | +------------+| | |
| +------------+| |
<---|---|---| route/addr |<------|-(async)--------------+
| +------------+|
| | +------------+| |
<-------|---| ... ||
| | +------------+| |
+-----------------+
| |
struct nl_cache_mngr *mngr; // Allocate a new cache manager for RTNETLINK and automatically // provide the caches added to the manager. mngr = nl_cache_mngr_alloc(NETLINK_ROUTE, NL_AUTO_PROVIDE);
struct nl_cache *cache; // Create a new cache for links/interfaces and ask the manager to // keep it up to date for us. This will trigger a full dump request // to initially fill the cache. cache = nl_cache_mngr_add(mngr, "route/link");
// Give the manager the ability to receive updates, will call poll() // with a timeout of 5 seconds. if (nl_cache_mngr_poll(mngr, 5000) > 0) { // Manager received at least one update, dump cache? nl_cache_dump(cache, ...); }
nl_cache_mngr_free(mngr);
struct nl_cache_mngr* nl_cache_mngr_alloc | ( | struct nl_handle * | handle, | |
int | protocol, | |||
int | flags | |||
) | [read] |
handle | Netlink socket/handle to be used | |
protocol | Netlink Protocol this manager is used for | |
flags | Flags |
Definition at line 149 of file cache_mngr.c.
References nl_cache_mngr_free(), NL_CB_CUSTOM, NL_CB_VALID, nl_connect(), nl_disable_sequence_check(), nl_socket_modify_cb(), and nl_socket_set_nonblocking().
00151 { 00152 struct nl_cache_mngr *mngr; 00153 00154 if (handle == NULL) 00155 BUG(); 00156 00157 mngr = calloc(1, sizeof(*mngr)); 00158 if (!mngr) 00159 goto enomem; 00160 00161 mngr->cm_handle = handle; 00162 mngr->cm_nassocs = 32; 00163 mngr->cm_protocol = protocol; 00164 mngr->cm_flags = flags; 00165 mngr->cm_assocs = calloc(mngr->cm_nassocs, 00166 sizeof(struct nl_cache_assoc)); 00167 if (!mngr->cm_assocs) 00168 goto enomem; 00169 00170 00171 nl_socket_modify_cb(mngr->cm_handle, NL_CB_VALID, NL_CB_CUSTOM, 00172 event_input, mngr); 00173 00174 /* Required to receive async event notifications */ 00175 nl_disable_sequence_check(mngr->cm_handle); 00176 00177 if (nl_connect(mngr->cm_handle, protocol) < 0) 00178 goto errout; 00179 00180 if (nl_socket_set_nonblocking(mngr->cm_handle) < 0) 00181 goto errout; 00182 00183 NL_DBG(1, "Allocated cache manager %p, protocol %d, %d caches\n", 00184 mngr, protocol, mngr->cm_nassocs); 00185 00186 return mngr; 00187 00188 enomem: 00189 nl_errno(ENOMEM); 00190 errout: 00191 nl_cache_mngr_free(mngr); 00192 return NULL; 00193 }
struct nl_cache* nl_cache_mngr_add | ( | struct nl_cache_mngr * | mngr, | |
const char * | name, | |||
change_func_t | cb | |||
) | [read] |
mngr | Cache manager. | |
name | Name of cache to keep track of | |
cb | Function to be called upon changes. |
Definition at line 209 of file cache_mngr.c.
References nl_af_group::ag_group, nl_cache_ops::co_groups, nl_cache_ops::co_protocol, nl_cache_alloc(), nl_cache_free(), nl_cache_mngt_provide(), nl_cache_ops_lookup(), nl_cache_refill(), nl_socket_add_membership(), and nl_socket_drop_membership().
00211 { 00212 struct nl_cache_ops *ops; 00213 struct nl_cache *cache; 00214 struct nl_af_group *grp; 00215 int err, i; 00216 00217 ops = nl_cache_ops_lookup(name); 00218 if (!ops) { 00219 nl_error(ENOENT, "Unknown cache type"); 00220 return NULL; 00221 } 00222 00223 if (ops->co_protocol != mngr->cm_protocol) { 00224 nl_error(EINVAL, "Netlink protocol mismatch"); 00225 return NULL; 00226 } 00227 00228 if (ops->co_groups == NULL) { 00229 nl_error(EOPNOTSUPP, NULL); 00230 return NULL; 00231 } 00232 00233 for (i = 0; i < mngr->cm_nassocs; i++) { 00234 if (mngr->cm_assocs[i].ca_cache && 00235 mngr->cm_assocs[i].ca_cache->c_ops == ops) { 00236 nl_error(EEXIST, "Cache of this type already managed"); 00237 return NULL; 00238 } 00239 } 00240 00241 retry: 00242 for (i = 0; i < mngr->cm_nassocs; i++) 00243 if (!mngr->cm_assocs[i].ca_cache) 00244 break; 00245 00246 if (i >= mngr->cm_nassocs) { 00247 mngr->cm_nassocs += 16; 00248 mngr->cm_assocs = realloc(mngr->cm_assocs, 00249 mngr->cm_nassocs * 00250 sizeof(struct nl_cache_assoc)); 00251 if (mngr->cm_assocs == NULL) { 00252 nl_errno(ENOMEM); 00253 return NULL; 00254 } else { 00255 NL_DBG(1, "Increased capacity of cache manager %p " \ 00256 "to %d\n", mngr, mngr->cm_nassocs); 00257 goto retry; 00258 } 00259 } 00260 00261 cache = nl_cache_alloc(ops); 00262 if (!cache) { 00263 nl_errno(ENOMEM); 00264 return NULL; 00265 } 00266 00267 for (grp = ops->co_groups; grp->ag_group; grp++) { 00268 err = nl_socket_add_membership(mngr->cm_handle, grp->ag_group); 00269 if (err < 0) 00270 goto errout_free_cache; 00271 } 00272 00273 err = nl_cache_refill(mngr->cm_handle, cache); 00274 if (err < 0) 00275 goto errout_drop_membership; 00276 00277 mngr->cm_assocs[i].ca_cache = cache; 00278 mngr->cm_assocs[i].ca_change = cb; 00279 00280 if (mngr->cm_flags & NL_AUTO_PROVIDE) 00281 nl_cache_mngt_provide(cache); 00282 00283 NL_DBG(1, "Added cache %p <%s> to cache manager %p\n", 00284 cache, nl_cache_name(cache), mngr); 00285 00286 return cache; 00287 00288 errout_drop_membership: 00289 for (grp = ops->co_groups; grp->ag_group; grp++) 00290 nl_socket_drop_membership(mngr->cm_handle, grp->ag_group); 00291 errout_free_cache: 00292 nl_cache_free(cache); 00293 00294 return NULL; 00295 }
int nl_cache_mngr_get_fd | ( | struct nl_cache_mngr * | mngr | ) |
mngr | Cache Manager |
Definition at line 305 of file cache_mngr.c.
int nl_cache_mngr_poll | ( | struct nl_cache_mngr * | mngr, | |
int | timeout | |||
) |
mngr | Cache Manager | |
timeout | Upper limit poll() will block, in milliseconds. |
This functionally is ideally called regularly during an idle period.
Definition at line 325 of file cache_mngr.c.
References nl_cache_mngr_data_ready().
00326 { 00327 int ret; 00328 struct pollfd fds = { 00329 .fd = nl_socket_get_fd(mngr->cm_handle), 00330 .events = POLLIN, 00331 }; 00332 00333 NL_DBG(3, "Cache manager %p, poll() fd %d\n", mngr, fds.fd); 00334 ret = poll(&fds, 1, timeout); 00335 NL_DBG(3, "Cache manager %p, poll() returned %d\n", mngr, ret); 00336 if (ret < 0) 00337 return nl_errno(errno); 00338 00339 if (ret == 0) 00340 return 0; 00341 00342 return nl_cache_mngr_data_ready(mngr); 00343 }
int nl_cache_mngr_data_ready | ( | struct nl_cache_mngr * | mngr | ) |
mngr | Cache manager |
Definition at line 356 of file cache_mngr.c.
References nl_recvmsgs_default().
Referenced by nl_cache_mngr_poll().
00357 { 00358 int err; 00359 00360 err = nl_recvmsgs_default(mngr->cm_handle); 00361 if (err < 0) 00362 return err; 00363 00364 return 1; 00365 }
void nl_cache_mngr_free | ( | struct nl_cache_mngr * | mngr | ) |
mngr | Cache manager |
Definition at line 373 of file cache_mngr.c.
References nl_close(), and nl_handle_destroy().
Referenced by nl_cache_mngr_alloc().
00374 { 00375 if (!mngr) 00376 return; 00377 00378 if (mngr->cm_handle) { 00379 nl_close(mngr->cm_handle); 00380 nl_handle_destroy(mngr->cm_handle); 00381 } 00382 00383 free(mngr->cm_assocs); 00384 free(mngr); 00385 00386 NL_DBG(1, "Cache manager %p freed\n", mngr); 00387 }