libnl
3.2.3
|
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-2008 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 = -NLE_NOMEM; 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 return -NLE_MISSING_ATTR; 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 errout: 00221 rtnl_neightbl_put(ntbl); 00222 return err; 00223 } 00224 00225 static int neightbl_request_update(struct nl_cache *c, struct nl_sock *h) 00226 { 00227 return nl_rtgen_request(h, RTM_GETNEIGHTBL, AF_UNSPEC, NLM_F_DUMP); 00228 } 00229 00230 00231 static void neightbl_dump_line(struct nl_object *arg, struct nl_dump_params *p) 00232 { 00233 struct rtnl_neightbl *ntbl = (struct rtnl_neightbl *) arg; 00234 00235 nl_dump_line(p, "%s", ntbl->nt_name); 00236 00237 if (ntbl->nt_parms.ntp_mask & NEIGHTBLPARM_ATTR_IFINDEX) { 00238 struct nl_cache *link_cache; 00239 00240 link_cache = nl_cache_mngt_require("route/link"); 00241 00242 if (link_cache) { 00243 char buf[32]; 00244 nl_dump(p, "<%s> ", 00245 rtnl_link_i2name(link_cache, 00246 ntbl->nt_parms.ntp_ifindex, 00247 buf, sizeof(buf))); 00248 } else 00249 nl_dump(p, "<%u> ", ntbl->nt_parms.ntp_ifindex); 00250 } else 00251 nl_dump(p, " "); 00252 00253 if (ntbl->ce_mask & NEIGHTBL_ATTR_CONFIG) 00254 nl_dump(p, "entries %u ", ntbl->nt_config.ndtc_entries); 00255 00256 if (ntbl->ce_mask & NEIGHTBL_ATTR_PARMS) { 00257 char rt[32], rt2[32]; 00258 struct rtnl_neightbl_parms *pa = &ntbl->nt_parms; 00259 00260 nl_dump(p, "reachable-time %s retransmit-time %s", 00261 nl_msec2str(pa->ntp_reachable_time, rt, sizeof(rt)), 00262 nl_msec2str(pa->ntp_retrans_time, rt2, sizeof(rt2))); 00263 } 00264 00265 nl_dump(p, "\n"); 00266 } 00267 00268 static void neightbl_dump_details(struct nl_object *arg, struct nl_dump_params *p) 00269 { 00270 char x[32], y[32], z[32]; 00271 struct rtnl_neightbl *ntbl = (struct rtnl_neightbl *) arg; 00272 00273 neightbl_dump_line(arg, p); 00274 00275 if (ntbl->ce_mask & NEIGHTBL_ATTR_CONFIG) { 00276 nl_dump_line(p, " key-len %u entry-size %u last-flush %s\n", 00277 ntbl->nt_config.ndtc_key_len, 00278 ntbl->nt_config.ndtc_entry_size, 00279 nl_msec2str(ntbl->nt_config.ndtc_last_flush, 00280 x, sizeof(x))); 00281 00282 nl_dump_line(p, " gc threshold %u/%u/%u interval %s " \ 00283 "chain-position %u\n", 00284 ntbl->nt_gc_thresh1, ntbl->nt_gc_thresh2, 00285 ntbl->nt_gc_thresh3, 00286 nl_msec2str(ntbl->nt_gc_interval, x, sizeof(x)), 00287 ntbl->nt_config.ndtc_hash_chain_gc); 00288 00289 nl_dump_line(p, " hash-rand 0x%08X/0x%08X last-rand %s\n", 00290 ntbl->nt_config.ndtc_hash_rnd, 00291 ntbl->nt_config.ndtc_hash_mask, 00292 nl_msec2str(ntbl->nt_config.ndtc_last_rand, 00293 x, sizeof(x))); 00294 } 00295 00296 if (ntbl->ce_mask & NEIGHTBL_ATTR_PARMS) { 00297 struct rtnl_neightbl_parms *pa = &ntbl->nt_parms; 00298 00299 nl_dump_line(p, " refcnt %u pending-queue-limit %u " \ 00300 "proxy-delayed-queue-limit %u\n", 00301 pa->ntp_refcnt, 00302 pa->ntp_queue_len, 00303 pa->ntp_proxy_qlen); 00304 00305 nl_dump_line(p, " num-userspace-probes %u num-unicast-probes " \ 00306 "%u num-multicast-probes %u\n", 00307 pa->ntp_app_probes, 00308 pa->ntp_ucast_probes, 00309 pa->ntp_mcast_probes); 00310 00311 nl_dump_line(p, " min-age %s base-reachable-time %s " \ 00312 "stale-check-interval %s\n", 00313 nl_msec2str(pa->ntp_locktime, x, sizeof(x)), 00314 nl_msec2str(pa->ntp_base_reachable_time, 00315 y, sizeof(y)), 00316 nl_msec2str(pa->ntp_gc_stale_time, z, sizeof(z))); 00317 00318 nl_dump_line(p, " initial-probe-delay %s answer-delay %s " \ 00319 "proxy-answer-delay %s\n", 00320 nl_msec2str(pa->ntp_probe_delay, x, sizeof(x)), 00321 nl_msec2str(pa->ntp_anycast_delay, y, sizeof(y)), 00322 nl_msec2str(pa->ntp_proxy_delay, z, sizeof(z))); 00323 } 00324 } 00325 00326 static void neightbl_dump_stats(struct nl_object *arg, struct nl_dump_params *p) 00327 { 00328 struct rtnl_neightbl *ntbl = (struct rtnl_neightbl *) arg; 00329 00330 neightbl_dump_details(arg, p); 00331 00332 if (!(ntbl->ce_mask & NEIGHTBL_ATTR_STATS)) 00333 return; 00334 00335 nl_dump_line(p, " lookups %lld hits %lld failed %lld " \ 00336 "allocations %lld destroys %lld\n", 00337 ntbl->nt_stats.ndts_lookups, 00338 ntbl->nt_stats.ndts_hits, 00339 ntbl->nt_stats.ndts_res_failed, 00340 ntbl->nt_stats.ndts_allocs, 00341 ntbl->nt_stats.ndts_destroys); 00342 00343 nl_dump_line(p, " hash-grows %lld forced-gc-runs %lld " \ 00344 "periodic-gc-runs %lld\n", 00345 ntbl->nt_stats.ndts_hash_grows, 00346 ntbl->nt_stats.ndts_forced_gc_runs, 00347 ntbl->nt_stats.ndts_periodic_gc_runs); 00348 00349 nl_dump_line(p, " rcv-unicast-probes %lld rcv-multicast-probes %lld\n", 00350 ntbl->nt_stats.ndts_rcv_probes_ucast, 00351 ntbl->nt_stats.ndts_rcv_probes_mcast); 00352 } 00353 00354 /** 00355 * @name Allocation/Freeing 00356 * @{ 00357 */ 00358 00359 struct rtnl_neightbl *rtnl_neightbl_alloc(void) 00360 { 00361 return (struct rtnl_neightbl *) nl_object_alloc(&neightbl_obj_ops); 00362 } 00363 00364 void rtnl_neightbl_put(struct rtnl_neightbl *neightbl) 00365 { 00366 nl_object_put((struct nl_object *) neightbl); 00367 } 00368 00369 /** @} */ 00370 00371 /** 00372 * @name Neighbour Table Cache Management 00373 * @{ 00374 */ 00375 00376 /** 00377 * Build a neighbour table cache including all neighbour tables currently configured in the kernel. 00378 * @arg sk Netlink socket. 00379 * @arg result Pointer to store resulting cache. 00380 * 00381 * Allocates a new neighbour table cache, initializes it properly and 00382 * updates it to include all neighbour tables currently configured in 00383 * the kernel. 00384 * 00385 * @return 0 on success or a negative error code. 00386 */ 00387 int rtnl_neightbl_alloc_cache(struct nl_sock *sk, struct nl_cache **result) 00388 { 00389 return nl_cache_alloc_and_fill(&rtnl_neightbl_ops, sk, result); 00390 } 00391 00392 /** 00393 * Lookup neighbour table by name and optional interface index 00394 * @arg cache neighbour table cache 00395 * @arg name name of table 00396 * @arg ifindex optional interface index 00397 * 00398 * Looks up the neighbour table matching the specified name and 00399 * optionally the specified ifindex to retrieve device specific 00400 * parameter sets. 00401 * 00402 * @return ptr to neighbour table inside the cache or NULL if no 00403 * match was found. 00404 */ 00405 struct rtnl_neightbl *rtnl_neightbl_get(struct nl_cache *cache, 00406 const char *name, int ifindex) 00407 { 00408 struct rtnl_neightbl *nt; 00409 00410 if (cache->c_ops != &rtnl_neightbl_ops) 00411 return NULL; 00412 00413 nl_list_for_each_entry(nt, &cache->c_items, ce_list) { 00414 if (!strcasecmp(nt->nt_name, name) && 00415 ((!ifindex && !nt->nt_parms.ntp_ifindex) || 00416 (ifindex && ifindex == nt->nt_parms.ntp_ifindex))) { 00417 nl_object_get((struct nl_object *) nt); 00418 return nt; 00419 } 00420 } 00421 00422 return NULL; 00423 } 00424 00425 /** @} */ 00426 00427 /** 00428 * @name Neighbour Table Modifications 00429 * @{ 00430 */ 00431 00432 /** 00433 * Builds a netlink change request message to change neighbour table attributes 00434 * @arg old neighbour table to change 00435 * @arg tmpl template with requested changes 00436 * @arg result Pointer to store resulting message. 00437 * 00438 * Builds a new netlink message requesting a change of neighbour table 00439 * attributes. The netlink message header isn't fully equipped with all 00440 * relevant fields and must be sent out via nl_send_auto_complete() or 00441 * supplemented as needed. 00442 * \a old must point to a neighbour table currently configured in the 00443 * kernel and \a tmpl must contain the attributes to be changed set via 00444 * \c rtnl_neightbl_set_* functions. 00445 * 00446 * @return 0 on success or a negative error code. 00447 */ 00448 int rtnl_neightbl_build_change_request(struct rtnl_neightbl *old, 00449 struct rtnl_neightbl *tmpl, 00450 struct nl_msg **result) 00451 { 00452 struct nl_msg *m, *parms = NULL; 00453 struct ndtmsg ndt = { 00454 .ndtm_family = old->nt_family, 00455 }; 00456 00457 m = nlmsg_alloc_simple(RTM_SETNEIGHTBL, 0); 00458 if (!m) 00459 return -NLE_NOMEM; 00460 00461 if (nlmsg_append(m, &ndt, sizeof(ndt), NLMSG_ALIGNTO) < 0) 00462 goto nla_put_failure; 00463 00464 NLA_PUT_STRING(m, NDTA_NAME, old->nt_name); 00465 00466 if (tmpl->ce_mask & NEIGHTBL_ATTR_THRESH1) 00467 NLA_PUT_U32(m, NDTA_THRESH1, tmpl->nt_gc_thresh1); 00468 00469 if (tmpl->ce_mask & NEIGHTBL_ATTR_THRESH2) 00470 NLA_PUT_U32(m, NDTA_THRESH2, tmpl->nt_gc_thresh2); 00471 00472 if (tmpl->ce_mask & NEIGHTBL_ATTR_THRESH2) 00473 NLA_PUT_U32(m, NDTA_THRESH2, tmpl->nt_gc_thresh2); 00474 00475 if (tmpl->ce_mask & NEIGHTBL_ATTR_GC_INTERVAL) 00476 NLA_PUT_U64(m, NDTA_GC_INTERVAL, 00477 tmpl->nt_gc_interval); 00478 00479 if (tmpl->ce_mask & NEIGHTBL_ATTR_PARMS) { 00480 struct rtnl_neightbl_parms *p = &tmpl->nt_parms; 00481 00482 parms = nlmsg_alloc(); 00483 if (!parms) 00484 goto nla_put_failure; 00485 00486 if (old->nt_parms.ntp_mask & NEIGHTBLPARM_ATTR_IFINDEX) 00487 NLA_PUT_U32(parms, NDTPA_IFINDEX, 00488 old->nt_parms.ntp_ifindex); 00489 00490 00491 if (p->ntp_mask & NEIGHTBLPARM_ATTR_QUEUE_LEN) 00492 NLA_PUT_U32(parms, NDTPA_QUEUE_LEN, p->ntp_queue_len); 00493 00494 if (p->ntp_mask & NEIGHTBLPARM_ATTR_APP_PROBES) 00495 NLA_PUT_U32(parms, NDTPA_APP_PROBES, p->ntp_app_probes); 00496 00497 if (p->ntp_mask & NEIGHTBLPARM_ATTR_UCAST_PROBES) 00498 NLA_PUT_U32(parms, NDTPA_UCAST_PROBES, 00499 p->ntp_ucast_probes); 00500 00501 if (p->ntp_mask & NEIGHTBLPARM_ATTR_MCAST_PROBES) 00502 NLA_PUT_U32(parms, NDTPA_MCAST_PROBES, 00503 p->ntp_mcast_probes); 00504 00505 if (p->ntp_mask & NEIGHTBLPARM_ATTR_PROXY_QLEN) 00506 NLA_PUT_U32(parms, NDTPA_PROXY_QLEN, 00507 p->ntp_proxy_qlen); 00508 00509 if (p->ntp_mask & NEIGHTBLPARM_ATTR_BASE_REACHABLE_TIME) 00510 NLA_PUT_U64(parms, NDTPA_BASE_REACHABLE_TIME, 00511 p->ntp_base_reachable_time); 00512 00513 if (p->ntp_mask & NEIGHTBLPARM_ATTR_RETRANS_TIME) 00514 NLA_PUT_U64(parms, NDTPA_RETRANS_TIME, 00515 p->ntp_retrans_time); 00516 00517 if (p->ntp_mask & NEIGHTBLPARM_ATTR_GC_STALETIME) 00518 NLA_PUT_U64(parms, NDTPA_GC_STALETIME, 00519 p->ntp_gc_stale_time); 00520 00521 if (p->ntp_mask & NEIGHTBLPARM_ATTR_DELAY_PROBE_TIME) 00522 NLA_PUT_U64(parms, NDTPA_DELAY_PROBE_TIME, 00523 p->ntp_proxy_delay); 00524 00525 if (p->ntp_mask & NEIGHTBLPARM_ATTR_ANYCAST_DELAY) 00526 NLA_PUT_U64(parms, NDTPA_ANYCAST_DELAY, 00527 p->ntp_anycast_delay); 00528 00529 if (p->ntp_mask & NEIGHTBLPARM_ATTR_PROXY_DELAY) 00530 NLA_PUT_U64(parms, NDTPA_PROXY_DELAY, 00531 p->ntp_proxy_delay); 00532 00533 if (p->ntp_mask & NEIGHTBLPARM_ATTR_LOCKTIME) 00534 NLA_PUT_U64(parms, NDTPA_LOCKTIME, p->ntp_locktime); 00535 00536 if (nla_put_nested(m, NDTA_PARMS, parms) < 0) 00537 goto nla_put_failure; 00538 00539 nlmsg_free(parms); 00540 } 00541 00542 *result = m; 00543 return 0; 00544 00545 nla_put_failure: 00546 if (parms) 00547 nlmsg_free(parms); 00548 nlmsg_free(m); 00549 return -NLE_MSGSIZE; 00550 } 00551 00552 /** 00553 * Change neighbour table attributes 00554 * @arg sk Netlink socket. 00555 * @arg old neighbour table to be changed 00556 * @arg tmpl template with requested changes 00557 * 00558 * Builds a new netlink message by calling 00559 * rtnl_neightbl_build_change_request(), sends the request to the 00560 * kernel and waits for the next ACK to be received, i.e. blocks 00561 * until the request has been processed. 00562 * 00563 * @return 0 on success or a negative error code 00564 */ 00565 int rtnl_neightbl_change(struct nl_sock *sk, struct rtnl_neightbl *old, 00566 struct rtnl_neightbl *tmpl) 00567 { 00568 struct nl_msg *msg; 00569 int err; 00570 00571 if ((err = rtnl_neightbl_build_change_request(old, tmpl, &msg)) < 0) 00572 return err; 00573 00574 err = nl_send_auto_complete(sk, msg); 00575 nlmsg_free(msg); 00576 if (err < 0) 00577 return err; 00578 00579 return wait_for_ack(sk); 00580 } 00581 00582 /** @} */ 00583 00584 /** 00585 * @name Attribute Modification 00586 * @{ 00587 */ 00588 00589 void rtnl_neightbl_set_family(struct rtnl_neightbl *ntbl, int family) 00590 { 00591 ntbl->nt_family = family; 00592 ntbl->ce_mask |= NEIGHTBL_ATTR_FAMILY; 00593 } 00594 00595 void rtnl_neightbl_set_gc_interval(struct rtnl_neightbl *ntbl, uint64_t ms) 00596 { 00597 ntbl->nt_gc_interval = ms; 00598 ntbl->ce_mask |= NEIGHTBL_ATTR_GC_INTERVAL; 00599 } 00600 00601 void rtnl_neightbl_set_gc_tresh1(struct rtnl_neightbl *ntbl, int thresh) 00602 { 00603 ntbl->nt_gc_thresh1 = thresh; 00604 ntbl->ce_mask |= NEIGHTBL_ATTR_THRESH1; 00605 } 00606 00607 void rtnl_neightbl_set_gc_tresh2(struct rtnl_neightbl *ntbl, int thresh) 00608 { 00609 ntbl->nt_gc_thresh2 = thresh; 00610 ntbl->ce_mask |= NEIGHTBL_ATTR_THRESH2; 00611 } 00612 00613 void rtnl_neightbl_set_gc_tresh3(struct rtnl_neightbl *ntbl, int thresh) 00614 { 00615 ntbl->nt_gc_thresh3 = thresh; 00616 ntbl->ce_mask |= NEIGHTBL_ATTR_THRESH3; 00617 } 00618 00619 void rtnl_neightbl_set_name(struct rtnl_neightbl *ntbl, const char *name) 00620 { 00621 strncpy(ntbl->nt_name, name, sizeof(ntbl->nt_name) - 1); 00622 ntbl->ce_mask |= NEIGHTBL_ATTR_NAME; 00623 } 00624 00625 void rtnl_neightbl_set_dev(struct rtnl_neightbl *ntbl, int ifindex) 00626 { 00627 ntbl->nt_parms.ntp_ifindex = ifindex; 00628 ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_IFINDEX; 00629 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; 00630 } 00631 00632 /** 00633 * Set the queue length for pending requests of a neighbour table to the specified value 00634 * @arg ntbl neighbour table to change 00635 * @arg len new queue len 00636 */ 00637 void rtnl_neightbl_set_queue_len(struct rtnl_neightbl *ntbl, int len) 00638 { 00639 ntbl->nt_parms.ntp_queue_len = len; 00640 ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_QUEUE_LEN; 00641 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; 00642 } 00643 00644 /** 00645 * Set the queue length for delay proxy arp requests of a neighbour table to the specified value 00646 * @arg ntbl neighbour table to change 00647 * @arg len new queue len 00648 */ 00649 void rtnl_neightbl_set_proxy_queue_len(struct rtnl_neightbl *ntbl, int len) 00650 { 00651 ntbl->nt_parms.ntp_proxy_qlen = len; 00652 ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_PROXY_QLEN; 00653 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; 00654 } 00655 00656 /** 00657 * Set the number of application probes of a neighbour table to the specified value 00658 * @arg ntbl neighbour table to change 00659 * @arg probes new probes value 00660 */ 00661 void rtnl_neightbl_set_app_probes(struct rtnl_neightbl *ntbl, int probes) 00662 { 00663 ntbl->nt_parms.ntp_app_probes = probes; 00664 ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_APP_PROBES; 00665 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; 00666 } 00667 00668 /** 00669 * Set the number of unicast probes of a neighbour table to the specified value 00670 * @arg ntbl neighbour table to change 00671 * @arg probes new probes value 00672 */ 00673 void rtnl_neightbl_set_ucast_probes(struct rtnl_neightbl *ntbl, int probes) 00674 { 00675 ntbl->nt_parms.ntp_ucast_probes = probes; 00676 ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_UCAST_PROBES; 00677 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; 00678 } 00679 00680 /** 00681 * Set the number of multicast probes of a neighbour table to the specified value 00682 * @arg ntbl neighbour table to change 00683 * @arg probes new probes value 00684 */ 00685 void rtnl_neightbl_set_mcast_probes(struct rtnl_neightbl *ntbl, int probes) 00686 { 00687 ntbl->nt_parms.ntp_mcast_probes = probes; 00688 ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_MCAST_PROBES; 00689 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; 00690 } 00691 00692 /** 00693 * Set the base reachable time of a neighbour table to the specified value 00694 * @arg ntbl neighbour table to change 00695 * @arg ms new base reachable time in milliseconds 00696 */ 00697 void rtnl_neightbl_set_base_reachable_time(struct rtnl_neightbl *ntbl, 00698 uint64_t ms) 00699 { 00700 ntbl->nt_parms.ntp_base_reachable_time = ms; 00701 ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_BASE_REACHABLE_TIME; 00702 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; 00703 } 00704 00705 /** 00706 * Set the retransmit time of a neighbour table to the specified value 00707 * @arg ntbl neighbour table to change 00708 * @arg ms new retransmit time 00709 */ 00710 void rtnl_neightbl_set_retrans_time(struct rtnl_neightbl *ntbl, uint64_t ms) 00711 { 00712 ntbl->nt_parms.ntp_retrans_time = ms; 00713 ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_RETRANS_TIME; 00714 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; 00715 } 00716 00717 /** 00718 * Set the gc stale time of a neighbour table to the specified value 00719 * @arg ntbl neighbour table to change 00720 * @arg ms new gc stale time in milliseconds 00721 */ 00722 void rtnl_neightbl_set_gc_stale_time(struct rtnl_neightbl *ntbl, uint64_t ms) 00723 { 00724 ntbl->nt_parms.ntp_gc_stale_time = ms; 00725 ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_GC_STALETIME; 00726 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; 00727 } 00728 00729 /** 00730 * Set the first probe delay time of a neighbour table to the specified value 00731 * @arg ntbl neighbour table to change 00732 * @arg ms new first probe delay time in milliseconds 00733 */ 00734 void rtnl_neightbl_set_delay_probe_time(struct rtnl_neightbl *ntbl, uint64_t ms) 00735 { 00736 ntbl->nt_parms.ntp_probe_delay = ms; 00737 ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_DELAY_PROBE_TIME; 00738 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; 00739 } 00740 00741 /** 00742 * Set the anycast delay of a neighbour table to the specified value 00743 * @arg ntbl neighbour table to change 00744 * @arg ms new anycast delay in milliseconds 00745 */ 00746 void rtnl_neightbl_set_anycast_delay(struct rtnl_neightbl *ntbl, uint64_t ms) 00747 { 00748 ntbl->nt_parms.ntp_anycast_delay = ms; 00749 ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_ANYCAST_DELAY; 00750 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; 00751 } 00752 00753 /** 00754 * Set the proxy delay of a neighbour table to the specified value 00755 * @arg ntbl neighbour table to change 00756 * @arg ms new proxy delay in milliseconds 00757 */ 00758 void rtnl_neightbl_set_proxy_delay(struct rtnl_neightbl *ntbl, uint64_t ms) 00759 { 00760 ntbl->nt_parms.ntp_proxy_delay = ms; 00761 ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_PROXY_DELAY; 00762 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; 00763 } 00764 00765 /** 00766 * Set the locktime of a neighbour table to the specified value 00767 * @arg ntbl neighbour table to change 00768 * @arg ms new locktime in milliseconds 00769 */ 00770 void rtnl_neightbl_set_locktime(struct rtnl_neightbl *ntbl, uint64_t ms) 00771 { 00772 ntbl->nt_parms.ntp_locktime = ms; 00773 ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_LOCKTIME; 00774 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; 00775 } 00776 00777 /** @} */ 00778 00779 static struct nl_object_ops neightbl_obj_ops = { 00780 .oo_name = "route/neightbl", 00781 .oo_size = sizeof(struct rtnl_neightbl), 00782 .oo_dump = { 00783 [NL_DUMP_LINE] = neightbl_dump_line, 00784 [NL_DUMP_DETAILS] = neightbl_dump_details, 00785 [NL_DUMP_STATS] = neightbl_dump_stats, 00786 }, 00787 .oo_compare = neightbl_compare, 00788 }; 00789 00790 static struct nl_cache_ops rtnl_neightbl_ops = { 00791 .co_name = "route/neightbl", 00792 .co_hdrsize = sizeof(struct rtgenmsg), 00793 .co_msgtypes = { 00794 { RTM_NEWNEIGHTBL, NL_ACT_NEW, "new" }, 00795 { RTM_SETNEIGHTBL, NL_ACT_SET, "set" }, 00796 { RTM_GETNEIGHTBL, NL_ACT_GET, "get" }, 00797 END_OF_MSGTYPES_LIST, 00798 }, 00799 .co_protocol = NETLINK_ROUTE, 00800 .co_request_update = neightbl_request_update, 00801 .co_msg_parser = neightbl_msg_parser, 00802 .co_obj_ops = &neightbl_obj_ops, 00803 }; 00804 00805 static void __init neightbl_init(void) 00806 { 00807 nl_cache_mngt_register(&rtnl_neightbl_ops); 00808 } 00809 00810 static void __exit neightbl_exit(void) 00811 { 00812 nl_cache_mngt_unregister(&rtnl_neightbl_ops); 00813 } 00814 00815 /** @} */