libnl 1.1
|
00001 /* 00002 * lib/route/neightbl.c neighbour tables 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation version 2.1 00007 * of the License. 00008 * 00009 * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch> 00010 */ 00011 00012 /** 00013 * @ingroup rtnl 00014 * @defgroup neightbl Neighbour Tables 00015 * @brief 00016 * @{ 00017 */ 00018 00019 #include <netlink-local.h> 00020 #include <netlink/netlink.h> 00021 #include <netlink/utils.h> 00022 #include <netlink/route/rtnl.h> 00023 #include <netlink/route/neightbl.h> 00024 #include <netlink/route/link.h> 00025 00026 /** @cond SKIP */ 00027 #define NEIGHTBL_ATTR_FAMILY 0x001 00028 #define NEIGHTBL_ATTR_STATS 0x002 00029 #define NEIGHTBL_ATTR_NAME 0x004 00030 #define NEIGHTBL_ATTR_THRESH1 0x008 00031 #define NEIGHTBL_ATTR_THRESH2 0x010 00032 #define NEIGHTBL_ATTR_THRESH3 0x020 00033 #define NEIGHTBL_ATTR_CONFIG 0x040 00034 #define NEIGHTBL_ATTR_PARMS 0x080 00035 #define NEIGHTBL_ATTR_GC_INTERVAL 0x100 00036 00037 #define NEIGHTBLPARM_ATTR_IFINDEX 0x0001 00038 #define NEIGHTBLPARM_ATTR_REFCNT 0x0002 00039 #define NEIGHTBLPARM_ATTR_QUEUE_LEN 0x0004 00040 #define NEIGHTBLPARM_ATTR_APP_PROBES 0x0008 00041 #define NEIGHTBLPARM_ATTR_UCAST_PROBES 0x0010 00042 #define NEIGHTBLPARM_ATTR_MCAST_PROBES 0x0020 00043 #define NEIGHTBLPARM_ATTR_PROXY_QLEN 0x0040 00044 #define NEIGHTBLPARM_ATTR_REACHABLE_TIME 0x0080 00045 #define NEIGHTBLPARM_ATTR_BASE_REACHABLE_TIME 0x0100 00046 #define NEIGHTBLPARM_ATTR_RETRANS_TIME 0x0200 00047 #define NEIGHTBLPARM_ATTR_GC_STALETIME 0x0400 00048 #define NEIGHTBLPARM_ATTR_DELAY_PROBE_TIME 0x0800 00049 #define NEIGHTBLPARM_ATTR_ANYCAST_DELAY 0x1000 00050 #define NEIGHTBLPARM_ATTR_PROXY_DELAY 0x2000 00051 #define NEIGHTBLPARM_ATTR_LOCKTIME 0x4000 00052 00053 static struct nl_cache_ops rtnl_neightbl_ops; 00054 static struct nl_object_ops neightbl_obj_ops; 00055 /** @endcond */ 00056 00057 static int neightbl_compare(struct nl_object *_a, struct nl_object *_b, 00058 uint32_t attrs, int flags) 00059 { 00060 struct rtnl_neightbl *a = (struct rtnl_neightbl *) _a; 00061 struct rtnl_neightbl *b = (struct rtnl_neightbl *) _b; 00062 int diff = 0; 00063 00064 #define NT_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, NEIGHTBL_ATTR_##ATTR, a, b, EXPR) 00065 00066 diff |= NT_DIFF(FAMILY, a->nt_family != b->nt_family); 00067 diff |= NT_DIFF(NAME, strcmp(a->nt_name, b->nt_name)); 00068 diff |= NT_DIFF(THRESH1, a->nt_gc_thresh1 != b->nt_gc_thresh1); 00069 diff |= NT_DIFF(THRESH2, a->nt_gc_thresh2 != b->nt_gc_thresh2); 00070 diff |= NT_DIFF(THRESH3, a->nt_gc_thresh3 != b->nt_gc_thresh3); 00071 diff |= NT_DIFF(GC_INTERVAL, a->nt_gc_interval != b->nt_gc_interval); 00072 00073 #undef NT_DIFF 00074 00075 if (!(a->ce_mask & NEIGHTBL_ATTR_PARMS) && 00076 !(b->ce_mask & NEIGHTBL_ATTR_PARMS)) 00077 return diff; 00078 00079 /* XXX: FIXME: Compare parameter table */ 00080 00081 00082 #if 0 00083 #define REQ(F) (fp->ntp_mask & NEIGHTBLPARM_ATTR_##F) 00084 #define AVAIL(F) (op->ntp_mask & NEIGHTBLPARM_ATTR_##F) 00085 #define _C(F, N) (REQ(F) && (!AVAIL(F) || (op->N != fp->N))) 00086 if (_C(IFINDEX, ntp_ifindex) || 00087 _C(QUEUE_LEN, ntp_queue_len) || 00088 _C(APP_PROBES, ntp_app_probes) || 00089 _C(UCAST_PROBES, ntp_ucast_probes) || 00090 _C(MCAST_PROBES, ntp_mcast_probes) || 00091 _C(PROXY_QLEN, ntp_proxy_qlen) || 00092 _C(LOCKTIME, ntp_locktime) || 00093 _C(RETRANS_TIME, ntp_retrans_time) || 00094 _C(BASE_REACHABLE_TIME, ntp_base_reachable_time) || 00095 _C(GC_STALETIME, ntp_gc_stale_time) || 00096 _C(DELAY_PROBE_TIME, ntp_probe_delay) || 00097 _C(ANYCAST_DELAY, ntp_anycast_delay) || 00098 _C(PROXY_DELAY, ntp_proxy_delay)) 00099 return 0; 00100 #undef REQ 00101 #undef AVAIL 00102 #undef _C 00103 #endif 00104 00105 return diff; 00106 } 00107 00108 00109 static struct nla_policy neightbl_policy[NDTA_MAX+1] = { 00110 [NDTA_NAME] = { .type = NLA_STRING, 00111 .maxlen = NTBLNAMSIZ }, 00112 [NDTA_THRESH1] = { .type = NLA_U32 }, 00113 [NDTA_THRESH2] = { .type = NLA_U32 }, 00114 [NDTA_THRESH3] = { .type = NLA_U32 }, 00115 [NDTA_GC_INTERVAL] = { .type = NLA_U32 }, 00116 [NDTA_CONFIG] = { .minlen = sizeof(struct ndt_config) }, 00117 [NDTA_STATS] = { .minlen = sizeof(struct ndt_stats) }, 00118 [NDTA_PARMS] = { .type = NLA_NESTED }, 00119 }; 00120 00121 static int neightbl_msg_parser(struct nl_cache_ops *ops, 00122 struct sockaddr_nl *who, struct nlmsghdr *n, 00123 struct nl_parser_param *pp) 00124 { 00125 struct rtnl_neightbl *ntbl; 00126 struct nlattr *tb[NDTA_MAX + 1]; 00127 struct rtgenmsg *rtmsg; 00128 int err; 00129 00130 ntbl = rtnl_neightbl_alloc(); 00131 if (!ntbl) { 00132 err = nl_errno(ENOMEM); 00133 goto errout; 00134 } 00135 00136 ntbl->ce_msgtype = n->nlmsg_type; 00137 rtmsg = nlmsg_data(n); 00138 00139 err = nlmsg_parse(n, sizeof(*rtmsg), tb, NDTA_MAX, neightbl_policy); 00140 if (err < 0) 00141 goto errout; 00142 00143 ntbl->nt_family = rtmsg->rtgen_family; 00144 00145 if (tb[NDTA_NAME] == NULL) { 00146 err = nl_error(EINVAL, "NDTA_NAME is missing"); 00147 goto errout; 00148 } 00149 00150 nla_strlcpy(ntbl->nt_name, tb[NDTA_NAME], NTBLNAMSIZ); 00151 ntbl->ce_mask |= NEIGHTBL_ATTR_NAME; 00152 00153 if (tb[NDTA_THRESH1]) { 00154 ntbl->nt_gc_thresh1 = nla_get_u32(tb[NDTA_THRESH1]); 00155 ntbl->ce_mask |= NEIGHTBL_ATTR_THRESH1; 00156 } 00157 00158 if (tb[NDTA_THRESH2]) { 00159 ntbl->nt_gc_thresh2 = nla_get_u32(tb[NDTA_THRESH2]); 00160 ntbl->ce_mask |= NEIGHTBL_ATTR_THRESH2; 00161 } 00162 00163 if (tb[NDTA_THRESH3]) { 00164 ntbl->nt_gc_thresh3 = nla_get_u32(tb[NDTA_THRESH3]); 00165 ntbl->ce_mask |= NEIGHTBL_ATTR_THRESH3; 00166 } 00167 00168 if (tb[NDTA_GC_INTERVAL]) { 00169 ntbl->nt_gc_interval = nla_get_u32(tb[NDTA_GC_INTERVAL]); 00170 ntbl->ce_mask |= NEIGHTBL_ATTR_GC_INTERVAL; 00171 } 00172 00173 if (tb[NDTA_CONFIG]) { 00174 nla_memcpy(&ntbl->nt_config, tb[NDTA_CONFIG], 00175 sizeof(ntbl->nt_config)); 00176 ntbl->ce_mask |= NEIGHTBL_ATTR_CONFIG; 00177 } 00178 00179 if (tb[NDTA_STATS]) { 00180 nla_memcpy(&ntbl->nt_stats, tb[NDTA_STATS], 00181 sizeof(ntbl->nt_stats)); 00182 ntbl->ce_mask |= NEIGHTBL_ATTR_STATS; 00183 } 00184 00185 if (tb[NDTA_PARMS]) { 00186 struct nlattr *tbp[NDTPA_MAX + 1]; 00187 struct rtnl_neightbl_parms *p = &ntbl->nt_parms; 00188 00189 err = nla_parse_nested(tbp, NDTPA_MAX, tb[NDTA_PARMS], NULL); 00190 if (err < 0) 00191 goto errout; 00192 00193 #define COPY_ENTRY(name, var) \ 00194 if (tbp[NDTPA_ ##name]) { \ 00195 p->ntp_ ##var = nla_get_u32(tbp[NDTPA_ ##name]); \ 00196 p->ntp_mask |= NEIGHTBLPARM_ATTR_ ##name; \ 00197 } 00198 00199 COPY_ENTRY(IFINDEX, ifindex); 00200 COPY_ENTRY(REFCNT, refcnt); 00201 COPY_ENTRY(QUEUE_LEN, queue_len); 00202 COPY_ENTRY(APP_PROBES, app_probes); 00203 COPY_ENTRY(UCAST_PROBES, ucast_probes); 00204 COPY_ENTRY(MCAST_PROBES, mcast_probes); 00205 COPY_ENTRY(PROXY_QLEN, proxy_qlen); 00206 COPY_ENTRY(PROXY_DELAY, proxy_delay); 00207 COPY_ENTRY(ANYCAST_DELAY, anycast_delay); 00208 COPY_ENTRY(LOCKTIME, locktime); 00209 COPY_ENTRY(REACHABLE_TIME, reachable_time); 00210 COPY_ENTRY(BASE_REACHABLE_TIME, base_reachable_time); 00211 COPY_ENTRY(RETRANS_TIME, retrans_time); 00212 COPY_ENTRY(GC_STALETIME, gc_stale_time); 00213 COPY_ENTRY(DELAY_PROBE_TIME, probe_delay); 00214 #undef COPY_ENTRY 00215 00216 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; 00217 } 00218 00219 err = pp->pp_cb((struct nl_object *) ntbl, pp); 00220 if (err < 0) 00221 goto errout; 00222 00223 err = P_ACCEPT; 00224 errout: 00225 rtnl_neightbl_put(ntbl); 00226 return err; 00227 } 00228 00229 static int neightbl_request_update(struct nl_cache *c, struct nl_handle *h) 00230 { 00231 return nl_rtgen_request(h, RTM_GETNEIGHTBL, AF_UNSPEC, NLM_F_DUMP); 00232 } 00233 00234 00235 static int neightbl_dump_brief(struct nl_object *arg, struct nl_dump_params *p) 00236 { 00237 int line = 1; 00238 struct rtnl_neightbl *ntbl = (struct rtnl_neightbl *) arg; 00239 00240 dp_dump(p, "%s", ntbl->nt_name); 00241 00242 if (ntbl->nt_parms.ntp_mask & NEIGHTBLPARM_ATTR_IFINDEX) { 00243 struct nl_cache *link_cache; 00244 00245 link_cache = nl_cache_mngt_require("route/link"); 00246 00247 if (link_cache) { 00248 char buf[32]; 00249 dp_dump(p, "<%s> ", 00250 rtnl_link_i2name(link_cache, 00251 ntbl->nt_parms.ntp_ifindex, 00252 buf, sizeof(buf))); 00253 } else 00254 dp_dump(p, "<%u> ", ntbl->nt_parms.ntp_ifindex); 00255 } else 00256 dp_dump(p, " "); 00257 00258 if (ntbl->ce_mask & NEIGHTBL_ATTR_CONFIG) 00259 dp_dump(p, "entries %u ", ntbl->nt_config.ndtc_entries); 00260 00261 if (ntbl->ce_mask & NEIGHTBL_ATTR_PARMS) { 00262 char rt[32], rt2[32]; 00263 struct rtnl_neightbl_parms *pa = &ntbl->nt_parms; 00264 00265 dp_dump(p, "reachable-time %s retransmit-time %s", 00266 nl_msec2str(pa->ntp_reachable_time, rt, sizeof(rt)), 00267 nl_msec2str(pa->ntp_retrans_time, rt2, sizeof(rt2))); 00268 } 00269 00270 dp_dump(p, "\n"); 00271 00272 return line; 00273 } 00274 00275 static int neightbl_dump_full(struct nl_object *arg, struct nl_dump_params *p) 00276 { 00277 char x[32], y[32], z[32]; 00278 struct rtnl_neightbl *ntbl = (struct rtnl_neightbl *) arg; 00279 00280 int line = neightbl_dump_brief(arg, p); 00281 00282 if (ntbl->ce_mask & NEIGHTBL_ATTR_CONFIG) { 00283 dp_new_line(p, line++); 00284 dp_dump(p, " key-len %u entry-size %u last-flush %s\n", 00285 ntbl->nt_config.ndtc_key_len, 00286 ntbl->nt_config.ndtc_entry_size, 00287 nl_msec2str(ntbl->nt_config.ndtc_last_flush, 00288 x, sizeof(x))); 00289 00290 dp_new_line(p, line++); 00291 dp_dump(p, " gc threshold %u/%u/%u interval %s " \ 00292 "chain-position %u\n", 00293 ntbl->nt_gc_thresh1, ntbl->nt_gc_thresh2, 00294 ntbl->nt_gc_thresh3, 00295 nl_msec2str(ntbl->nt_gc_interval, x, sizeof(x)), 00296 ntbl->nt_config.ndtc_hash_chain_gc); 00297 00298 dp_new_line(p, line++); 00299 dp_dump(p, " hash-rand 0x%08X/0x%08X last-rand %s\n", 00300 ntbl->nt_config.ndtc_hash_rnd, 00301 ntbl->nt_config.ndtc_hash_mask, 00302 nl_msec2str(ntbl->nt_config.ndtc_last_rand, 00303 x, sizeof(x))); 00304 } 00305 00306 if (ntbl->ce_mask & NEIGHTBL_ATTR_PARMS) { 00307 struct rtnl_neightbl_parms *pa = &ntbl->nt_parms; 00308 00309 dp_new_line(p, line++); 00310 dp_dump(p, " refcnt %u pending-queue-limit %u " \ 00311 "proxy-delayed-queue-limit %u\n", 00312 pa->ntp_refcnt, 00313 pa->ntp_queue_len, 00314 pa->ntp_proxy_qlen); 00315 00316 dp_new_line(p, line++); 00317 dp_dump(p, " num-userspace-probes %u num-unicast-probes " \ 00318 "%u num-multicast-probes %u\n", 00319 pa->ntp_app_probes, 00320 pa->ntp_ucast_probes, 00321 pa->ntp_mcast_probes); 00322 00323 dp_new_line(p, line++); 00324 dp_dump(p, " min-age %s base-reachable-time %s " \ 00325 "stale-check-interval %s\n", 00326 nl_msec2str(pa->ntp_locktime, x, sizeof(x)), 00327 nl_msec2str(pa->ntp_base_reachable_time, 00328 y, sizeof(y)), 00329 nl_msec2str(pa->ntp_gc_stale_time, z, sizeof(z))); 00330 00331 dp_new_line(p, line++); 00332 dp_dump(p, " initial-probe-delay %s answer-delay %s " \ 00333 "proxy-answer-delay %s\n", 00334 nl_msec2str(pa->ntp_probe_delay, x, sizeof(x)), 00335 nl_msec2str(pa->ntp_anycast_delay, y, sizeof(y)), 00336 nl_msec2str(pa->ntp_proxy_delay, z, sizeof(z))); 00337 } 00338 00339 return line; 00340 } 00341 00342 static int neightbl_dump_stats(struct nl_object *arg, struct nl_dump_params *p) 00343 { 00344 struct rtnl_neightbl *ntbl = (struct rtnl_neightbl *) arg; 00345 int line = neightbl_dump_full(arg, p); 00346 00347 if (!(ntbl->ce_mask & NEIGHTBL_ATTR_STATS)) 00348 return line; 00349 00350 dp_new_line(p, line++); 00351 dp_dump(p, " lookups %lld hits %lld failed %lld " \ 00352 "allocations %lld destroys %lld\n", 00353 ntbl->nt_stats.ndts_lookups, 00354 ntbl->nt_stats.ndts_hits, 00355 ntbl->nt_stats.ndts_res_failed, 00356 ntbl->nt_stats.ndts_allocs, 00357 ntbl->nt_stats.ndts_destroys); 00358 00359 dp_new_line(p, line++); 00360 dp_dump(p, " hash-grows %lld forced-gc-runs %lld " \ 00361 "periodic-gc-runs %lld\n", 00362 ntbl->nt_stats.ndts_hash_grows, 00363 ntbl->nt_stats.ndts_forced_gc_runs, 00364 ntbl->nt_stats.ndts_periodic_gc_runs); 00365 00366 dp_dump(p, " rcv-unicast-probes %lld rcv-multicast-probes %lld\n", 00367 ntbl->nt_stats.ndts_rcv_probes_ucast, 00368 ntbl->nt_stats.ndts_rcv_probes_mcast); 00369 00370 return line; 00371 } 00372 00373 /** 00374 * @name Allocation/Freeing 00375 * @{ 00376 */ 00377 00378 struct rtnl_neightbl *rtnl_neightbl_alloc(void) 00379 { 00380 return (struct rtnl_neightbl *) nl_object_alloc(&neightbl_obj_ops); 00381 } 00382 00383 void rtnl_neightbl_put(struct rtnl_neightbl *neightbl) 00384 { 00385 nl_object_put((struct nl_object *) neightbl); 00386 } 00387 00388 /** @} */ 00389 00390 /** 00391 * @name Neighbour Table Cache Management 00392 * @{ 00393 */ 00394 00395 /** 00396 * Build a neighbour table cache including all neighbour tables currently configured in the kernel. 00397 * @arg handle netlink handle 00398 * 00399 * Allocates a new neighbour table cache, initializes it properly and 00400 * updates it to include all neighbour tables currently configured in 00401 * the kernel. 00402 * 00403 * @note The caller is responsible for destroying and freeing the 00404 * cache after using it. 00405 * @return The new cache or NULL if an error occured. 00406 */ 00407 struct nl_cache * rtnl_neightbl_alloc_cache(struct nl_handle *handle) 00408 { 00409 struct nl_cache * cache; 00410 00411 cache = nl_cache_alloc(&rtnl_neightbl_ops); 00412 if (cache == NULL) 00413 return NULL; 00414 00415 if (handle && nl_cache_refill(handle, cache) < 0) { 00416 nl_cache_free(cache); 00417 return NULL; 00418 } 00419 00420 return cache; 00421 } 00422 00423 /** 00424 * Lookup neighbour table by name and optional interface index 00425 * @arg cache neighbour table cache 00426 * @arg name name of table 00427 * @arg ifindex optional interface index 00428 * 00429 * Looks up the neighbour table matching the specified name and 00430 * optionally the specified ifindex to retrieve device specific 00431 * parameter sets. 00432 * 00433 * @return ptr to neighbour table inside the cache or NULL if no 00434 * match was found. 00435 */ 00436 struct rtnl_neightbl *rtnl_neightbl_get(struct nl_cache *cache, 00437 const char *name, int ifindex) 00438 { 00439 struct rtnl_neightbl *nt; 00440 00441 if (cache->c_ops != &rtnl_neightbl_ops) 00442 return NULL; 00443 00444 nl_list_for_each_entry(nt, &cache->c_items, ce_list) { 00445 if (!strcasecmp(nt->nt_name, name) && 00446 ((!ifindex && !nt->nt_parms.ntp_ifindex) || 00447 (ifindex && ifindex == nt->nt_parms.ntp_ifindex))) { 00448 nl_object_get((struct nl_object *) nt); 00449 return nt; 00450 } 00451 } 00452 00453 return NULL; 00454 } 00455 00456 /** @} */ 00457 00458 /** 00459 * @name Neighbour Table Modifications 00460 * @{ 00461 */ 00462 00463 /** 00464 * Builds a netlink change request message to change neighbour table attributes 00465 * @arg old neighbour table to change 00466 * @arg tmpl template with requested changes 00467 * 00468 * Builds a new netlink message requesting a change of neighbour table 00469 * attributes. The netlink message header isn't fully equipped with all 00470 * relevant fields and must be sent out via nl_send_auto_complete() or 00471 * supplemented as needed. 00472 * \a old must point to a neighbour table currently configured in the 00473 * kernel and \a tmpl must contain the attributes to be changed set via 00474 * \c rtnl_neightbl_set_* functions. 00475 * 00476 * @return New netlink message 00477 */ 00478 struct nl_msg * rtnl_neightbl_build_change_request(struct rtnl_neightbl *old, 00479 struct rtnl_neightbl *tmpl) 00480 { 00481 struct nl_msg *m; 00482 struct ndtmsg ndt = { 00483 .ndtm_family = old->nt_family, 00484 }; 00485 00486 m = nlmsg_alloc_simple(RTM_SETNEIGHTBL, 0); 00487 nlmsg_append(m, &ndt, sizeof(ndt), NLMSG_ALIGNTO); 00488 00489 nla_put_string(m, NDTA_NAME, old->nt_name); 00490 00491 if (tmpl->ce_mask & NEIGHTBL_ATTR_THRESH1) 00492 nla_put_u32(m, NDTA_THRESH1, tmpl->nt_gc_thresh1); 00493 00494 if (tmpl->ce_mask & NEIGHTBL_ATTR_THRESH2) 00495 nla_put_u32(m, NDTA_THRESH2, tmpl->nt_gc_thresh2); 00496 00497 if (tmpl->ce_mask & NEIGHTBL_ATTR_THRESH2) 00498 nla_put_u32(m, NDTA_THRESH2, tmpl->nt_gc_thresh2); 00499 00500 if (tmpl->ce_mask & NEIGHTBL_ATTR_GC_INTERVAL) 00501 nla_put_u64(m, NDTA_GC_INTERVAL, 00502 tmpl->nt_gc_interval); 00503 00504 if (tmpl->ce_mask & NEIGHTBL_ATTR_PARMS) { 00505 struct rtnl_neightbl_parms *p = &tmpl->nt_parms; 00506 struct nl_msg *parms = nlmsg_alloc(); 00507 00508 if (old->nt_parms.ntp_mask & NEIGHTBLPARM_ATTR_IFINDEX) 00509 nla_put_u32(parms, NDTPA_IFINDEX, 00510 old->nt_parms.ntp_ifindex); 00511 00512 00513 if (p->ntp_mask & NEIGHTBLPARM_ATTR_QUEUE_LEN) 00514 nla_put_u32(parms, NDTPA_QUEUE_LEN, p->ntp_queue_len); 00515 00516 if (p->ntp_mask & NEIGHTBLPARM_ATTR_APP_PROBES) 00517 nla_put_u32(parms, NDTPA_APP_PROBES, p->ntp_app_probes); 00518 00519 if (p->ntp_mask & NEIGHTBLPARM_ATTR_UCAST_PROBES) 00520 nla_put_u32(parms, NDTPA_UCAST_PROBES, 00521 p->ntp_ucast_probes); 00522 00523 if (p->ntp_mask & NEIGHTBLPARM_ATTR_MCAST_PROBES) 00524 nla_put_u32(parms, NDTPA_MCAST_PROBES, 00525 p->ntp_mcast_probes); 00526 00527 if (p->ntp_mask & NEIGHTBLPARM_ATTR_PROXY_QLEN) 00528 nla_put_u32(parms, NDTPA_PROXY_QLEN, 00529 p->ntp_proxy_qlen); 00530 00531 if (p->ntp_mask & NEIGHTBLPARM_ATTR_BASE_REACHABLE_TIME) 00532 nla_put_u64(parms, NDTPA_BASE_REACHABLE_TIME, 00533 p->ntp_base_reachable_time); 00534 00535 if (p->ntp_mask & NEIGHTBLPARM_ATTR_RETRANS_TIME) 00536 nla_put_u64(parms, NDTPA_RETRANS_TIME, 00537 p->ntp_retrans_time); 00538 00539 if (p->ntp_mask & NEIGHTBLPARM_ATTR_GC_STALETIME) 00540 nla_put_u64(parms, NDTPA_GC_STALETIME, 00541 p->ntp_gc_stale_time); 00542 00543 if (p->ntp_mask & NEIGHTBLPARM_ATTR_DELAY_PROBE_TIME) 00544 nla_put_u64(parms, NDTPA_DELAY_PROBE_TIME, 00545 p->ntp_proxy_delay); 00546 00547 if (p->ntp_mask & NEIGHTBLPARM_ATTR_ANYCAST_DELAY) 00548 nla_put_u64(parms, NDTPA_ANYCAST_DELAY, 00549 p->ntp_anycast_delay); 00550 00551 if (p->ntp_mask & NEIGHTBLPARM_ATTR_PROXY_DELAY) 00552 nla_put_u64(parms, NDTPA_PROXY_DELAY, 00553 p->ntp_proxy_delay); 00554 00555 if (p->ntp_mask & NEIGHTBLPARM_ATTR_LOCKTIME) 00556 nla_put_u64(parms, NDTPA_LOCKTIME, p->ntp_locktime); 00557 00558 nla_put_nested(m, NDTA_PARMS, parms); 00559 nlmsg_free(parms); 00560 } 00561 00562 return m; 00563 } 00564 00565 /** 00566 * Change neighbour table attributes 00567 * @arg handle netlink handle 00568 * @arg old neighbour table to be changed 00569 * @arg tmpl template with requested changes 00570 * 00571 * Builds a new netlink message by calling 00572 * rtnl_neightbl_build_change_request(), sends the request to the 00573 * kernel and waits for the next ACK to be received, i.e. blocks 00574 * until the request has been processed. 00575 * 00576 * @return 0 on success or a negative error code 00577 */ 00578 int rtnl_neightbl_change(struct nl_handle *handle, struct rtnl_neightbl *old, 00579 struct rtnl_neightbl *tmpl) 00580 { 00581 int err; 00582 struct nl_msg *msg; 00583 00584 msg = rtnl_neightbl_build_change_request(old, tmpl); 00585 err = nl_send_auto_complete(handle, msg); 00586 if (err < 0) 00587 return err; 00588 00589 nlmsg_free(msg); 00590 return nl_wait_for_ack(handle); 00591 } 00592 00593 /** @} */ 00594 00595 /** 00596 * @name Attribute Modification 00597 * @{ 00598 */ 00599 00600 void rtnl_neightbl_set_family(struct rtnl_neightbl *ntbl, int family) 00601 { 00602 ntbl->nt_family = family; 00603 ntbl->ce_mask |= NEIGHTBL_ATTR_FAMILY; 00604 } 00605 00606 void rtnl_neightbl_set_gc_interval(struct rtnl_neightbl *ntbl, uint64_t ms) 00607 { 00608 ntbl->nt_gc_interval = ms; 00609 ntbl->ce_mask |= NEIGHTBL_ATTR_GC_INTERVAL; 00610 } 00611 00612 void rtnl_neightbl_set_gc_tresh1(struct rtnl_neightbl *ntbl, int thresh) 00613 { 00614 ntbl->nt_gc_thresh1 = thresh; 00615 ntbl->ce_mask |= NEIGHTBL_ATTR_THRESH1; 00616 } 00617 00618 void rtnl_neightbl_set_gc_tresh2(struct rtnl_neightbl *ntbl, int thresh) 00619 { 00620 ntbl->nt_gc_thresh2 = thresh; 00621 ntbl->ce_mask |= NEIGHTBL_ATTR_THRESH2; 00622 } 00623 00624 void rtnl_neightbl_set_gc_tresh3(struct rtnl_neightbl *ntbl, int thresh) 00625 { 00626 ntbl->nt_gc_thresh3 = thresh; 00627 ntbl->ce_mask |= NEIGHTBL_ATTR_THRESH3; 00628 } 00629 00630 void rtnl_neightbl_set_name(struct rtnl_neightbl *ntbl, const char *name) 00631 { 00632 strncpy(ntbl->nt_name, name, sizeof(ntbl->nt_name) - 1); 00633 ntbl->ce_mask |= NEIGHTBL_ATTR_NAME; 00634 } 00635 00636 void rtnl_neightbl_set_dev(struct rtnl_neightbl *ntbl, int ifindex) 00637 { 00638 ntbl->nt_parms.ntp_ifindex = ifindex; 00639 ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_IFINDEX; 00640 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; 00641 } 00642 00643 /** 00644 * Set the queue length for pending requests of a neighbour table to the specified value 00645 * @arg ntbl neighbour table to change 00646 * @arg len new queue len 00647 */ 00648 void rtnl_neightbl_set_queue_len(struct rtnl_neightbl *ntbl, int len) 00649 { 00650 ntbl->nt_parms.ntp_queue_len = len; 00651 ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_QUEUE_LEN; 00652 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; 00653 } 00654 00655 /** 00656 * Set the queue length for delay proxy arp requests of a neighbour table to the specified value 00657 * @arg ntbl neighbour table to change 00658 * @arg len new queue len 00659 */ 00660 void rtnl_neightbl_set_proxy_queue_len(struct rtnl_neightbl *ntbl, int len) 00661 { 00662 ntbl->nt_parms.ntp_proxy_qlen = len; 00663 ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_PROXY_QLEN; 00664 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; 00665 } 00666 00667 /** 00668 * Set the number of application probes of a neighbour table to the specified value 00669 * @arg ntbl neighbour table to change 00670 * @arg probes new probes value 00671 */ 00672 void rtnl_neightbl_set_app_probes(struct rtnl_neightbl *ntbl, int probes) 00673 { 00674 ntbl->nt_parms.ntp_app_probes = probes; 00675 ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_APP_PROBES; 00676 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; 00677 } 00678 00679 /** 00680 * Set the number of unicast probes of a neighbour table to the specified value 00681 * @arg ntbl neighbour table to change 00682 * @arg probes new probes value 00683 */ 00684 void rtnl_neightbl_set_ucast_probes(struct rtnl_neightbl *ntbl, int probes) 00685 { 00686 ntbl->nt_parms.ntp_ucast_probes = probes; 00687 ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_UCAST_PROBES; 00688 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; 00689 } 00690 00691 /** 00692 * Set the number of multicast probes of a neighbour table to the specified value 00693 * @arg ntbl neighbour table to change 00694 * @arg probes new probes value 00695 */ 00696 void rtnl_neightbl_set_mcast_probes(struct rtnl_neightbl *ntbl, int probes) 00697 { 00698 ntbl->nt_parms.ntp_mcast_probes = probes; 00699 ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_MCAST_PROBES; 00700 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; 00701 } 00702 00703 /** 00704 * Set the base reachable time of a neighbour table to the specified value 00705 * @arg ntbl neighbour table to change 00706 * @arg ms new base reachable time in milliseconds 00707 */ 00708 void rtnl_neightbl_set_base_reachable_time(struct rtnl_neightbl *ntbl, 00709 uint64_t ms) 00710 { 00711 ntbl->nt_parms.ntp_base_reachable_time = ms; 00712 ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_BASE_REACHABLE_TIME; 00713 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; 00714 } 00715 00716 /** 00717 * Set the retransmit time of a neighbour table to the specified value 00718 * @arg ntbl neighbour table to change 00719 * @arg ms new retransmit time 00720 */ 00721 void rtnl_neightbl_set_retrans_time(struct rtnl_neightbl *ntbl, uint64_t ms) 00722 { 00723 ntbl->nt_parms.ntp_retrans_time = ms; 00724 ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_RETRANS_TIME; 00725 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; 00726 } 00727 00728 /** 00729 * Set the gc stale time of a neighbour table to the specified value 00730 * @arg ntbl neighbour table to change 00731 * @arg ms new gc stale time in milliseconds 00732 */ 00733 void rtnl_neightbl_set_gc_stale_time(struct rtnl_neightbl *ntbl, uint64_t ms) 00734 { 00735 ntbl->nt_parms.ntp_gc_stale_time = ms; 00736 ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_GC_STALETIME; 00737 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; 00738 } 00739 00740 /** 00741 * Set the first probe delay time of a neighbour table to the specified value 00742 * @arg ntbl neighbour table to change 00743 * @arg ms new first probe delay time in milliseconds 00744 */ 00745 void rtnl_neightbl_set_delay_probe_time(struct rtnl_neightbl *ntbl, uint64_t ms) 00746 { 00747 ntbl->nt_parms.ntp_probe_delay = ms; 00748 ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_DELAY_PROBE_TIME; 00749 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; 00750 } 00751 00752 /** 00753 * Set the anycast delay of a neighbour table to the specified value 00754 * @arg ntbl neighbour table to change 00755 * @arg ms new anycast delay in milliseconds 00756 */ 00757 void rtnl_neightbl_set_anycast_delay(struct rtnl_neightbl *ntbl, uint64_t ms) 00758 { 00759 ntbl->nt_parms.ntp_anycast_delay = ms; 00760 ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_ANYCAST_DELAY; 00761 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; 00762 } 00763 00764 /** 00765 * Set the proxy delay of a neighbour table to the specified value 00766 * @arg ntbl neighbour table to change 00767 * @arg ms new proxy delay in milliseconds 00768 */ 00769 void rtnl_neightbl_set_proxy_delay(struct rtnl_neightbl *ntbl, uint64_t ms) 00770 { 00771 ntbl->nt_parms.ntp_proxy_delay = ms; 00772 ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_PROXY_DELAY; 00773 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; 00774 } 00775 00776 /** 00777 * Set the locktime of a neighbour table to the specified value 00778 * @arg ntbl neighbour table to change 00779 * @arg ms new locktime in milliseconds 00780 */ 00781 void rtnl_neightbl_set_locktime(struct rtnl_neightbl *ntbl, uint64_t ms) 00782 { 00783 ntbl->nt_parms.ntp_locktime = ms; 00784 ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_LOCKTIME; 00785 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; 00786 } 00787 00788 /** @} */ 00789 00790 static struct nl_object_ops neightbl_obj_ops = { 00791 .oo_name = "route/neightbl", 00792 .oo_size = sizeof(struct rtnl_neightbl), 00793 .oo_dump[NL_DUMP_BRIEF] = neightbl_dump_brief, 00794 .oo_dump[NL_DUMP_FULL] = neightbl_dump_full, 00795 .oo_dump[NL_DUMP_STATS] = neightbl_dump_stats, 00796 .oo_compare = neightbl_compare, 00797 }; 00798 00799 static struct nl_cache_ops rtnl_neightbl_ops = { 00800 .co_name = "route/neightbl", 00801 .co_hdrsize = sizeof(struct rtgenmsg), 00802 .co_msgtypes = { 00803 { RTM_NEWNEIGHTBL, NL_ACT_NEW, "new" }, 00804 { RTM_SETNEIGHTBL, NL_ACT_SET, "set" }, 00805 { RTM_GETNEIGHTBL, NL_ACT_GET, "get" }, 00806 END_OF_MSGTYPES_LIST, 00807 }, 00808 .co_protocol = NETLINK_ROUTE, 00809 .co_request_update = neightbl_request_update, 00810 .co_msg_parser = neightbl_msg_parser, 00811 .co_obj_ops = &neightbl_obj_ops, 00812 }; 00813 00814 static void __init neightbl_init(void) 00815 { 00816 nl_cache_mngt_register(&rtnl_neightbl_ops); 00817 } 00818 00819 static void __exit neightbl_exit(void) 00820 { 00821 nl_cache_mngt_unregister(&rtnl_neightbl_ops); 00822 } 00823 00824 /** @} */