neightbl.c revision ef50a38fbd8682a5c9efd559e7db68664977f080
1/* 2 * lib/route/neightbl.c neighbour tables 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation version 2.1 7 * of the License. 8 * 9 * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch> 10 */ 11 12/** 13 * @ingroup rtnl 14 * @defgroup neightbl Neighbour Tables 15 * @brief 16 * @{ 17 */ 18 19#include <netlink-local.h> 20#include <netlink/netlink.h> 21#include <netlink/utils.h> 22#include <netlink/route/rtnl.h> 23#include <netlink/route/neightbl.h> 24#include <netlink/route/link.h> 25 26/** @cond SKIP */ 27#define NEIGHTBL_ATTR_FAMILY 0x001 28#define NEIGHTBL_ATTR_STATS 0x002 29#define NEIGHTBL_ATTR_NAME 0x004 30#define NEIGHTBL_ATTR_THRESH1 0x008 31#define NEIGHTBL_ATTR_THRESH2 0x010 32#define NEIGHTBL_ATTR_THRESH3 0x020 33#define NEIGHTBL_ATTR_CONFIG 0x040 34#define NEIGHTBL_ATTR_PARMS 0x080 35#define NEIGHTBL_ATTR_GC_INTERVAL 0x100 36 37#define NEIGHTBLPARM_ATTR_IFINDEX 0x0001 38#define NEIGHTBLPARM_ATTR_REFCNT 0x0002 39#define NEIGHTBLPARM_ATTR_QUEUE_LEN 0x0004 40#define NEIGHTBLPARM_ATTR_APP_PROBES 0x0008 41#define NEIGHTBLPARM_ATTR_UCAST_PROBES 0x0010 42#define NEIGHTBLPARM_ATTR_MCAST_PROBES 0x0020 43#define NEIGHTBLPARM_ATTR_PROXY_QLEN 0x0040 44#define NEIGHTBLPARM_ATTR_REACHABLE_TIME 0x0080 45#define NEIGHTBLPARM_ATTR_BASE_REACHABLE_TIME 0x0100 46#define NEIGHTBLPARM_ATTR_RETRANS_TIME 0x0200 47#define NEIGHTBLPARM_ATTR_GC_STALETIME 0x0400 48#define NEIGHTBLPARM_ATTR_DELAY_PROBE_TIME 0x0800 49#define NEIGHTBLPARM_ATTR_ANYCAST_DELAY 0x1000 50#define NEIGHTBLPARM_ATTR_PROXY_DELAY 0x2000 51#define NEIGHTBLPARM_ATTR_LOCKTIME 0x4000 52 53static struct nl_cache_ops rtnl_neightbl_ops; 54static struct nl_object_ops neightbl_obj_ops; 55/** @endcond */ 56 57static int neightbl_compare(struct nl_object *_a, struct nl_object *_b, 58 uint32_t attrs, int flags) 59{ 60 struct rtnl_neightbl *a = (struct rtnl_neightbl *) _a; 61 struct rtnl_neightbl *b = (struct rtnl_neightbl *) _b; 62 int diff = 0; 63 64#define NT_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, NEIGHTBL_ATTR_##ATTR, a, b, EXPR) 65 66 diff |= NT_DIFF(FAMILY, a->nt_family != b->nt_family); 67 diff |= NT_DIFF(NAME, strcmp(a->nt_name, b->nt_name)); 68 diff |= NT_DIFF(THRESH1, a->nt_gc_thresh1 != b->nt_gc_thresh1); 69 diff |= NT_DIFF(THRESH2, a->nt_gc_thresh2 != b->nt_gc_thresh2); 70 diff |= NT_DIFF(THRESH3, a->nt_gc_thresh3 != b->nt_gc_thresh3); 71 diff |= NT_DIFF(GC_INTERVAL, a->nt_gc_interval != b->nt_gc_interval); 72 73#undef NT_DIFF 74 75 if (!(a->ce_mask & NEIGHTBL_ATTR_PARMS) && 76 !(b->ce_mask & NEIGHTBL_ATTR_PARMS)) 77 return diff; 78 79 /* XXX: FIXME: Compare parameter table */ 80 81 82#if 0 83#define REQ(F) (fp->ntp_mask & NEIGHTBLPARM_ATTR_##F) 84#define AVAIL(F) (op->ntp_mask & NEIGHTBLPARM_ATTR_##F) 85#define _C(F, N) (REQ(F) && (!AVAIL(F) || (op->N != fp->N))) 86 if (_C(IFINDEX, ntp_ifindex) || 87 _C(QUEUE_LEN, ntp_queue_len) || 88 _C(APP_PROBES, ntp_app_probes) || 89 _C(UCAST_PROBES, ntp_ucast_probes) || 90 _C(MCAST_PROBES, ntp_mcast_probes) || 91 _C(PROXY_QLEN, ntp_proxy_qlen) || 92 _C(LOCKTIME, ntp_locktime) || 93 _C(RETRANS_TIME, ntp_retrans_time) || 94 _C(BASE_REACHABLE_TIME, ntp_base_reachable_time) || 95 _C(GC_STALETIME, ntp_gc_stale_time) || 96 _C(DELAY_PROBE_TIME, ntp_probe_delay) || 97 _C(ANYCAST_DELAY, ntp_anycast_delay) || 98 _C(PROXY_DELAY, ntp_proxy_delay)) 99 return 0; 100#undef REQ 101#undef AVAIL 102#undef _C 103#endif 104 105 return diff; 106} 107 108 109static struct nla_policy neightbl_policy[NDTA_MAX+1] = { 110 [NDTA_NAME] = { .type = NLA_STRING, 111 .maxlen = NTBLNAMSIZ }, 112 [NDTA_THRESH1] = { .type = NLA_U32 }, 113 [NDTA_THRESH2] = { .type = NLA_U32 }, 114 [NDTA_THRESH3] = { .type = NLA_U32 }, 115 [NDTA_GC_INTERVAL] = { .type = NLA_U32 }, 116 [NDTA_CONFIG] = { .minlen = sizeof(struct ndt_config) }, 117 [NDTA_STATS] = { .minlen = sizeof(struct ndt_stats) }, 118 [NDTA_PARMS] = { .type = NLA_NESTED }, 119}; 120 121static int neightbl_msg_parser(struct nl_cache_ops *ops, 122 struct sockaddr_nl *who, struct nlmsghdr *n, 123 struct nl_parser_param *pp) 124{ 125 struct rtnl_neightbl *ntbl; 126 struct nlattr *tb[NDTA_MAX + 1]; 127 struct rtgenmsg *rtmsg; 128 int err; 129 130 ntbl = rtnl_neightbl_alloc(); 131 if (!ntbl) { 132 err = -NLE_NOMEM; 133 goto errout; 134 } 135 136 ntbl->ce_msgtype = n->nlmsg_type; 137 rtmsg = nlmsg_data(n); 138 139 err = nlmsg_parse(n, sizeof(*rtmsg), tb, NDTA_MAX, neightbl_policy); 140 if (err < 0) 141 goto errout; 142 143 ntbl->nt_family = rtmsg->rtgen_family; 144 145 if (tb[NDTA_NAME] == NULL) { 146 return -NLE_MISSING_ATTR; 147 goto errout; 148 } 149 150 nla_strlcpy(ntbl->nt_name, tb[NDTA_NAME], NTBLNAMSIZ); 151 ntbl->ce_mask |= NEIGHTBL_ATTR_NAME; 152 153 if (tb[NDTA_THRESH1]) { 154 ntbl->nt_gc_thresh1 = nla_get_u32(tb[NDTA_THRESH1]); 155 ntbl->ce_mask |= NEIGHTBL_ATTR_THRESH1; 156 } 157 158 if (tb[NDTA_THRESH2]) { 159 ntbl->nt_gc_thresh2 = nla_get_u32(tb[NDTA_THRESH2]); 160 ntbl->ce_mask |= NEIGHTBL_ATTR_THRESH2; 161 } 162 163 if (tb[NDTA_THRESH3]) { 164 ntbl->nt_gc_thresh3 = nla_get_u32(tb[NDTA_THRESH3]); 165 ntbl->ce_mask |= NEIGHTBL_ATTR_THRESH3; 166 } 167 168 if (tb[NDTA_GC_INTERVAL]) { 169 ntbl->nt_gc_interval = nla_get_u32(tb[NDTA_GC_INTERVAL]); 170 ntbl->ce_mask |= NEIGHTBL_ATTR_GC_INTERVAL; 171 } 172 173 if (tb[NDTA_CONFIG]) { 174 nla_memcpy(&ntbl->nt_config, tb[NDTA_CONFIG], 175 sizeof(ntbl->nt_config)); 176 ntbl->ce_mask |= NEIGHTBL_ATTR_CONFIG; 177 } 178 179 if (tb[NDTA_STATS]) { 180 nla_memcpy(&ntbl->nt_stats, tb[NDTA_STATS], 181 sizeof(ntbl->nt_stats)); 182 ntbl->ce_mask |= NEIGHTBL_ATTR_STATS; 183 } 184 185 if (tb[NDTA_PARMS]) { 186 struct nlattr *tbp[NDTPA_MAX + 1]; 187 struct rtnl_neightbl_parms *p = &ntbl->nt_parms; 188 189 err = nla_parse_nested(tbp, NDTPA_MAX, tb[NDTA_PARMS], NULL); 190 if (err < 0) 191 goto errout; 192 193#define COPY_ENTRY(name, var) \ 194 if (tbp[NDTPA_ ##name]) { \ 195 p->ntp_ ##var = nla_get_u32(tbp[NDTPA_ ##name]); \ 196 p->ntp_mask |= NEIGHTBLPARM_ATTR_ ##name; \ 197 } 198 199 COPY_ENTRY(IFINDEX, ifindex); 200 COPY_ENTRY(REFCNT, refcnt); 201 COPY_ENTRY(QUEUE_LEN, queue_len); 202 COPY_ENTRY(APP_PROBES, app_probes); 203 COPY_ENTRY(UCAST_PROBES, ucast_probes); 204 COPY_ENTRY(MCAST_PROBES, mcast_probes); 205 COPY_ENTRY(PROXY_QLEN, proxy_qlen); 206 COPY_ENTRY(PROXY_DELAY, proxy_delay); 207 COPY_ENTRY(ANYCAST_DELAY, anycast_delay); 208 COPY_ENTRY(LOCKTIME, locktime); 209 COPY_ENTRY(REACHABLE_TIME, reachable_time); 210 COPY_ENTRY(BASE_REACHABLE_TIME, base_reachable_time); 211 COPY_ENTRY(RETRANS_TIME, retrans_time); 212 COPY_ENTRY(GC_STALETIME, gc_stale_time); 213 COPY_ENTRY(DELAY_PROBE_TIME, probe_delay); 214#undef COPY_ENTRY 215 216 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; 217 } 218 219 err = pp->pp_cb((struct nl_object *) ntbl, pp); 220 if (err < 0) 221 goto errout; 222 223 err = P_ACCEPT; 224errout: 225 rtnl_neightbl_put(ntbl); 226 return err; 227} 228 229static int neightbl_request_update(struct nl_cache *c, struct nl_sock *h) 230{ 231 return nl_rtgen_request(h, RTM_GETNEIGHTBL, AF_UNSPEC, NLM_F_DUMP); 232} 233 234 235static int neightbl_dump_brief(struct nl_object *arg, struct nl_dump_params *p) 236{ 237 int line = 1; 238 struct rtnl_neightbl *ntbl = (struct rtnl_neightbl *) arg; 239 240 dp_dump(p, "%s", ntbl->nt_name); 241 242 if (ntbl->nt_parms.ntp_mask & NEIGHTBLPARM_ATTR_IFINDEX) { 243 struct nl_cache *link_cache; 244 245 link_cache = nl_cache_mngt_require("route/link"); 246 247 if (link_cache) { 248 char buf[32]; 249 dp_dump(p, "<%s> ", 250 rtnl_link_i2name(link_cache, 251 ntbl->nt_parms.ntp_ifindex, 252 buf, sizeof(buf))); 253 } else 254 dp_dump(p, "<%u> ", ntbl->nt_parms.ntp_ifindex); 255 } else 256 dp_dump(p, " "); 257 258 if (ntbl->ce_mask & NEIGHTBL_ATTR_CONFIG) 259 dp_dump(p, "entries %u ", ntbl->nt_config.ndtc_entries); 260 261 if (ntbl->ce_mask & NEIGHTBL_ATTR_PARMS) { 262 char rt[32], rt2[32]; 263 struct rtnl_neightbl_parms *pa = &ntbl->nt_parms; 264 265 dp_dump(p, "reachable-time %s retransmit-time %s", 266 nl_msec2str(pa->ntp_reachable_time, rt, sizeof(rt)), 267 nl_msec2str(pa->ntp_retrans_time, rt2, sizeof(rt2))); 268 } 269 270 dp_dump(p, "\n"); 271 272 return line; 273} 274 275static int neightbl_dump_full(struct nl_object *arg, struct nl_dump_params *p) 276{ 277 char x[32], y[32], z[32]; 278 struct rtnl_neightbl *ntbl = (struct rtnl_neightbl *) arg; 279 280 int line = neightbl_dump_brief(arg, p); 281 282 if (ntbl->ce_mask & NEIGHTBL_ATTR_CONFIG) { 283 dp_new_line(p, line++); 284 dp_dump(p, " key-len %u entry-size %u last-flush %s\n", 285 ntbl->nt_config.ndtc_key_len, 286 ntbl->nt_config.ndtc_entry_size, 287 nl_msec2str(ntbl->nt_config.ndtc_last_flush, 288 x, sizeof(x))); 289 290 dp_new_line(p, line++); 291 dp_dump(p, " gc threshold %u/%u/%u interval %s " \ 292 "chain-position %u\n", 293 ntbl->nt_gc_thresh1, ntbl->nt_gc_thresh2, 294 ntbl->nt_gc_thresh3, 295 nl_msec2str(ntbl->nt_gc_interval, x, sizeof(x)), 296 ntbl->nt_config.ndtc_hash_chain_gc); 297 298 dp_new_line(p, line++); 299 dp_dump(p, " hash-rand 0x%08X/0x%08X last-rand %s\n", 300 ntbl->nt_config.ndtc_hash_rnd, 301 ntbl->nt_config.ndtc_hash_mask, 302 nl_msec2str(ntbl->nt_config.ndtc_last_rand, 303 x, sizeof(x))); 304 } 305 306 if (ntbl->ce_mask & NEIGHTBL_ATTR_PARMS) { 307 struct rtnl_neightbl_parms *pa = &ntbl->nt_parms; 308 309 dp_new_line(p, line++); 310 dp_dump(p, " refcnt %u pending-queue-limit %u " \ 311 "proxy-delayed-queue-limit %u\n", 312 pa->ntp_refcnt, 313 pa->ntp_queue_len, 314 pa->ntp_proxy_qlen); 315 316 dp_new_line(p, line++); 317 dp_dump(p, " num-userspace-probes %u num-unicast-probes " \ 318 "%u num-multicast-probes %u\n", 319 pa->ntp_app_probes, 320 pa->ntp_ucast_probes, 321 pa->ntp_mcast_probes); 322 323 dp_new_line(p, line++); 324 dp_dump(p, " min-age %s base-reachable-time %s " \ 325 "stale-check-interval %s\n", 326 nl_msec2str(pa->ntp_locktime, x, sizeof(x)), 327 nl_msec2str(pa->ntp_base_reachable_time, 328 y, sizeof(y)), 329 nl_msec2str(pa->ntp_gc_stale_time, z, sizeof(z))); 330 331 dp_new_line(p, line++); 332 dp_dump(p, " initial-probe-delay %s answer-delay %s " \ 333 "proxy-answer-delay %s\n", 334 nl_msec2str(pa->ntp_probe_delay, x, sizeof(x)), 335 nl_msec2str(pa->ntp_anycast_delay, y, sizeof(y)), 336 nl_msec2str(pa->ntp_proxy_delay, z, sizeof(z))); 337 } 338 339 return line; 340} 341 342static int neightbl_dump_stats(struct nl_object *arg, struct nl_dump_params *p) 343{ 344 struct rtnl_neightbl *ntbl = (struct rtnl_neightbl *) arg; 345 int line = neightbl_dump_full(arg, p); 346 347 if (!(ntbl->ce_mask & NEIGHTBL_ATTR_STATS)) 348 return line; 349 350 dp_new_line(p, line++); 351 dp_dump(p, " lookups %lld hits %lld failed %lld " \ 352 "allocations %lld destroys %lld\n", 353 ntbl->nt_stats.ndts_lookups, 354 ntbl->nt_stats.ndts_hits, 355 ntbl->nt_stats.ndts_res_failed, 356 ntbl->nt_stats.ndts_allocs, 357 ntbl->nt_stats.ndts_destroys); 358 359 dp_new_line(p, line++); 360 dp_dump(p, " hash-grows %lld forced-gc-runs %lld " \ 361 "periodic-gc-runs %lld\n", 362 ntbl->nt_stats.ndts_hash_grows, 363 ntbl->nt_stats.ndts_forced_gc_runs, 364 ntbl->nt_stats.ndts_periodic_gc_runs); 365 366 dp_dump(p, " rcv-unicast-probes %lld rcv-multicast-probes %lld\n", 367 ntbl->nt_stats.ndts_rcv_probes_ucast, 368 ntbl->nt_stats.ndts_rcv_probes_mcast); 369 370 return line; 371} 372 373/** 374 * @name Allocation/Freeing 375 * @{ 376 */ 377 378struct rtnl_neightbl *rtnl_neightbl_alloc(void) 379{ 380 return (struct rtnl_neightbl *) nl_object_alloc(&neightbl_obj_ops); 381} 382 383void rtnl_neightbl_put(struct rtnl_neightbl *neightbl) 384{ 385 nl_object_put((struct nl_object *) neightbl); 386} 387 388/** @} */ 389 390/** 391 * @name Neighbour Table Cache Management 392 * @{ 393 */ 394 395/** 396 * Build a neighbour table cache including all neighbour tables currently configured in the kernel. 397 * @arg sk Netlink socket. 398 * @arg result Pointer to store resulting cache. 399 * 400 * Allocates a new neighbour table cache, initializes it properly and 401 * updates it to include all neighbour tables currently configured in 402 * the kernel. 403 * 404 * @return 0 on success or a negative error code. 405 */ 406int rtnl_neightbl_alloc_cache(struct nl_sock *sk, struct nl_cache **result) 407{ 408 return nl_cache_alloc_and_fill(&rtnl_neightbl_ops, sk, result); 409} 410 411/** 412 * Lookup neighbour table by name and optional interface index 413 * @arg cache neighbour table cache 414 * @arg name name of table 415 * @arg ifindex optional interface index 416 * 417 * Looks up the neighbour table matching the specified name and 418 * optionally the specified ifindex to retrieve device specific 419 * parameter sets. 420 * 421 * @return ptr to neighbour table inside the cache or NULL if no 422 * match was found. 423 */ 424struct rtnl_neightbl *rtnl_neightbl_get(struct nl_cache *cache, 425 const char *name, int ifindex) 426{ 427 struct rtnl_neightbl *nt; 428 429 if (cache->c_ops != &rtnl_neightbl_ops) 430 return NULL; 431 432 nl_list_for_each_entry(nt, &cache->c_items, ce_list) { 433 if (!strcasecmp(nt->nt_name, name) && 434 ((!ifindex && !nt->nt_parms.ntp_ifindex) || 435 (ifindex && ifindex == nt->nt_parms.ntp_ifindex))) { 436 nl_object_get((struct nl_object *) nt); 437 return nt; 438 } 439 } 440 441 return NULL; 442} 443 444/** @} */ 445 446/** 447 * @name Neighbour Table Modifications 448 * @{ 449 */ 450 451/** 452 * Builds a netlink change request message to change neighbour table attributes 453 * @arg old neighbour table to change 454 * @arg tmpl template with requested changes 455 * @arg result Pointer to store resulting message. 456 * 457 * Builds a new netlink message requesting a change of neighbour table 458 * attributes. The netlink message header isn't fully equipped with all 459 * relevant fields and must be sent out via nl_send_auto_complete() or 460 * supplemented as needed. 461 * \a old must point to a neighbour table currently configured in the 462 * kernel and \a tmpl must contain the attributes to be changed set via 463 * \c rtnl_neightbl_set_* functions. 464 * 465 * @return 0 on success or a negative error code. 466 */ 467int rtnl_neightbl_build_change_request(struct rtnl_neightbl *old, 468 struct rtnl_neightbl *tmpl, 469 struct nl_msg **result) 470{ 471 struct nl_msg *m, *parms = NULL; 472 struct ndtmsg ndt = { 473 .ndtm_family = old->nt_family, 474 }; 475 476 m = nlmsg_alloc_simple(RTM_SETNEIGHTBL, 0); 477 if (!m) 478 return -NLE_NOMEM; 479 480 if (nlmsg_append(m, &ndt, sizeof(ndt), NLMSG_ALIGNTO) < 0) 481 goto nla_put_failure; 482 483 NLA_PUT_STRING(m, NDTA_NAME, old->nt_name); 484 485 if (tmpl->ce_mask & NEIGHTBL_ATTR_THRESH1) 486 NLA_PUT_U32(m, NDTA_THRESH1, tmpl->nt_gc_thresh1); 487 488 if (tmpl->ce_mask & NEIGHTBL_ATTR_THRESH2) 489 NLA_PUT_U32(m, NDTA_THRESH2, tmpl->nt_gc_thresh2); 490 491 if (tmpl->ce_mask & NEIGHTBL_ATTR_THRESH2) 492 NLA_PUT_U32(m, NDTA_THRESH2, tmpl->nt_gc_thresh2); 493 494 if (tmpl->ce_mask & NEIGHTBL_ATTR_GC_INTERVAL) 495 NLA_PUT_U64(m, NDTA_GC_INTERVAL, 496 tmpl->nt_gc_interval); 497 498 if (tmpl->ce_mask & NEIGHTBL_ATTR_PARMS) { 499 struct rtnl_neightbl_parms *p = &tmpl->nt_parms; 500 501 parms = nlmsg_alloc(); 502 if (!parms) 503 goto nla_put_failure; 504 505 if (old->nt_parms.ntp_mask & NEIGHTBLPARM_ATTR_IFINDEX) 506 NLA_PUT_U32(parms, NDTPA_IFINDEX, 507 old->nt_parms.ntp_ifindex); 508 509 510 if (p->ntp_mask & NEIGHTBLPARM_ATTR_QUEUE_LEN) 511 NLA_PUT_U32(parms, NDTPA_QUEUE_LEN, p->ntp_queue_len); 512 513 if (p->ntp_mask & NEIGHTBLPARM_ATTR_APP_PROBES) 514 NLA_PUT_U32(parms, NDTPA_APP_PROBES, p->ntp_app_probes); 515 516 if (p->ntp_mask & NEIGHTBLPARM_ATTR_UCAST_PROBES) 517 NLA_PUT_U32(parms, NDTPA_UCAST_PROBES, 518 p->ntp_ucast_probes); 519 520 if (p->ntp_mask & NEIGHTBLPARM_ATTR_MCAST_PROBES) 521 NLA_PUT_U32(parms, NDTPA_MCAST_PROBES, 522 p->ntp_mcast_probes); 523 524 if (p->ntp_mask & NEIGHTBLPARM_ATTR_PROXY_QLEN) 525 NLA_PUT_U32(parms, NDTPA_PROXY_QLEN, 526 p->ntp_proxy_qlen); 527 528 if (p->ntp_mask & NEIGHTBLPARM_ATTR_BASE_REACHABLE_TIME) 529 NLA_PUT_U64(parms, NDTPA_BASE_REACHABLE_TIME, 530 p->ntp_base_reachable_time); 531 532 if (p->ntp_mask & NEIGHTBLPARM_ATTR_RETRANS_TIME) 533 NLA_PUT_U64(parms, NDTPA_RETRANS_TIME, 534 p->ntp_retrans_time); 535 536 if (p->ntp_mask & NEIGHTBLPARM_ATTR_GC_STALETIME) 537 NLA_PUT_U64(parms, NDTPA_GC_STALETIME, 538 p->ntp_gc_stale_time); 539 540 if (p->ntp_mask & NEIGHTBLPARM_ATTR_DELAY_PROBE_TIME) 541 NLA_PUT_U64(parms, NDTPA_DELAY_PROBE_TIME, 542 p->ntp_proxy_delay); 543 544 if (p->ntp_mask & NEIGHTBLPARM_ATTR_ANYCAST_DELAY) 545 NLA_PUT_U64(parms, NDTPA_ANYCAST_DELAY, 546 p->ntp_anycast_delay); 547 548 if (p->ntp_mask & NEIGHTBLPARM_ATTR_PROXY_DELAY) 549 NLA_PUT_U64(parms, NDTPA_PROXY_DELAY, 550 p->ntp_proxy_delay); 551 552 if (p->ntp_mask & NEIGHTBLPARM_ATTR_LOCKTIME) 553 NLA_PUT_U64(parms, NDTPA_LOCKTIME, p->ntp_locktime); 554 555 if (nla_put_nested(m, NDTA_PARMS, parms) < 0) 556 goto nla_put_failure; 557 558 nlmsg_free(parms); 559 } 560 561 *result = m; 562 return 0; 563 564nla_put_failure: 565 if (parms) 566 nlmsg_free(parms); 567 nlmsg_free(m); 568 return -NLE_MSGSIZE; 569} 570 571/** 572 * Change neighbour table attributes 573 * @arg sk Netlink socket. 574 * @arg old neighbour table to be changed 575 * @arg tmpl template with requested changes 576 * 577 * Builds a new netlink message by calling 578 * rtnl_neightbl_build_change_request(), sends the request to the 579 * kernel and waits for the next ACK to be received, i.e. blocks 580 * until the request has been processed. 581 * 582 * @return 0 on success or a negative error code 583 */ 584int rtnl_neightbl_change(struct nl_sock *sk, struct rtnl_neightbl *old, 585 struct rtnl_neightbl *tmpl) 586{ 587 struct nl_msg *msg; 588 int err; 589 590 if ((err = rtnl_neightbl_build_change_request(old, tmpl, &msg)) < 0) 591 return err; 592 593 err = nl_send_auto_complete(sk, msg); 594 nlmsg_free(msg); 595 if (err < 0) 596 return err; 597 598 return nl_wait_for_ack(sk); 599} 600 601/** @} */ 602 603/** 604 * @name Attribute Modification 605 * @{ 606 */ 607 608void rtnl_neightbl_set_family(struct rtnl_neightbl *ntbl, int family) 609{ 610 ntbl->nt_family = family; 611 ntbl->ce_mask |= NEIGHTBL_ATTR_FAMILY; 612} 613 614void rtnl_neightbl_set_gc_interval(struct rtnl_neightbl *ntbl, uint64_t ms) 615{ 616 ntbl->nt_gc_interval = ms; 617 ntbl->ce_mask |= NEIGHTBL_ATTR_GC_INTERVAL; 618} 619 620void rtnl_neightbl_set_gc_tresh1(struct rtnl_neightbl *ntbl, int thresh) 621{ 622 ntbl->nt_gc_thresh1 = thresh; 623 ntbl->ce_mask |= NEIGHTBL_ATTR_THRESH1; 624} 625 626void rtnl_neightbl_set_gc_tresh2(struct rtnl_neightbl *ntbl, int thresh) 627{ 628 ntbl->nt_gc_thresh2 = thresh; 629 ntbl->ce_mask |= NEIGHTBL_ATTR_THRESH2; 630} 631 632void rtnl_neightbl_set_gc_tresh3(struct rtnl_neightbl *ntbl, int thresh) 633{ 634 ntbl->nt_gc_thresh3 = thresh; 635 ntbl->ce_mask |= NEIGHTBL_ATTR_THRESH3; 636} 637 638void rtnl_neightbl_set_name(struct rtnl_neightbl *ntbl, const char *name) 639{ 640 strncpy(ntbl->nt_name, name, sizeof(ntbl->nt_name) - 1); 641 ntbl->ce_mask |= NEIGHTBL_ATTR_NAME; 642} 643 644void rtnl_neightbl_set_dev(struct rtnl_neightbl *ntbl, int ifindex) 645{ 646 ntbl->nt_parms.ntp_ifindex = ifindex; 647 ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_IFINDEX; 648 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; 649} 650 651/** 652 * Set the queue length for pending requests of a neighbour table to the specified value 653 * @arg ntbl neighbour table to change 654 * @arg len new queue len 655 */ 656void rtnl_neightbl_set_queue_len(struct rtnl_neightbl *ntbl, int len) 657{ 658 ntbl->nt_parms.ntp_queue_len = len; 659 ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_QUEUE_LEN; 660 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; 661} 662 663/** 664 * Set the queue length for delay proxy arp requests of a neighbour table to the specified value 665 * @arg ntbl neighbour table to change 666 * @arg len new queue len 667 */ 668void rtnl_neightbl_set_proxy_queue_len(struct rtnl_neightbl *ntbl, int len) 669{ 670 ntbl->nt_parms.ntp_proxy_qlen = len; 671 ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_PROXY_QLEN; 672 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; 673} 674 675/** 676 * Set the number of application probes of a neighbour table to the specified value 677 * @arg ntbl neighbour table to change 678 * @arg probes new probes value 679 */ 680void rtnl_neightbl_set_app_probes(struct rtnl_neightbl *ntbl, int probes) 681{ 682 ntbl->nt_parms.ntp_app_probes = probes; 683 ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_APP_PROBES; 684 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; 685} 686 687/** 688 * Set the number of unicast probes of a neighbour table to the specified value 689 * @arg ntbl neighbour table to change 690 * @arg probes new probes value 691 */ 692void rtnl_neightbl_set_ucast_probes(struct rtnl_neightbl *ntbl, int probes) 693{ 694 ntbl->nt_parms.ntp_ucast_probes = probes; 695 ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_UCAST_PROBES; 696 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; 697} 698 699/** 700 * Set the number of multicast probes of a neighbour table to the specified value 701 * @arg ntbl neighbour table to change 702 * @arg probes new probes value 703 */ 704void rtnl_neightbl_set_mcast_probes(struct rtnl_neightbl *ntbl, int probes) 705{ 706 ntbl->nt_parms.ntp_mcast_probes = probes; 707 ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_MCAST_PROBES; 708 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; 709} 710 711/** 712 * Set the base reachable time of a neighbour table to the specified value 713 * @arg ntbl neighbour table to change 714 * @arg ms new base reachable time in milliseconds 715 */ 716void rtnl_neightbl_set_base_reachable_time(struct rtnl_neightbl *ntbl, 717 uint64_t ms) 718{ 719 ntbl->nt_parms.ntp_base_reachable_time = ms; 720 ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_BASE_REACHABLE_TIME; 721 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; 722} 723 724/** 725 * Set the retransmit time of a neighbour table to the specified value 726 * @arg ntbl neighbour table to change 727 * @arg ms new retransmit time 728 */ 729void rtnl_neightbl_set_retrans_time(struct rtnl_neightbl *ntbl, uint64_t ms) 730{ 731 ntbl->nt_parms.ntp_retrans_time = ms; 732 ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_RETRANS_TIME; 733 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; 734} 735 736/** 737 * Set the gc stale time of a neighbour table to the specified value 738 * @arg ntbl neighbour table to change 739 * @arg ms new gc stale time in milliseconds 740 */ 741void rtnl_neightbl_set_gc_stale_time(struct rtnl_neightbl *ntbl, uint64_t ms) 742{ 743 ntbl->nt_parms.ntp_gc_stale_time = ms; 744 ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_GC_STALETIME; 745 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; 746} 747 748/** 749 * Set the first probe delay time of a neighbour table to the specified value 750 * @arg ntbl neighbour table to change 751 * @arg ms new first probe delay time in milliseconds 752 */ 753void rtnl_neightbl_set_delay_probe_time(struct rtnl_neightbl *ntbl, uint64_t ms) 754{ 755 ntbl->nt_parms.ntp_probe_delay = ms; 756 ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_DELAY_PROBE_TIME; 757 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; 758} 759 760/** 761 * Set the anycast delay of a neighbour table to the specified value 762 * @arg ntbl neighbour table to change 763 * @arg ms new anycast delay in milliseconds 764 */ 765void rtnl_neightbl_set_anycast_delay(struct rtnl_neightbl *ntbl, uint64_t ms) 766{ 767 ntbl->nt_parms.ntp_anycast_delay = ms; 768 ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_ANYCAST_DELAY; 769 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; 770} 771 772/** 773 * Set the proxy delay of a neighbour table to the specified value 774 * @arg ntbl neighbour table to change 775 * @arg ms new proxy delay in milliseconds 776 */ 777void rtnl_neightbl_set_proxy_delay(struct rtnl_neightbl *ntbl, uint64_t ms) 778{ 779 ntbl->nt_parms.ntp_proxy_delay = ms; 780 ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_PROXY_DELAY; 781 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; 782} 783 784/** 785 * Set the locktime of a neighbour table to the specified value 786 * @arg ntbl neighbour table to change 787 * @arg ms new locktime in milliseconds 788 */ 789void rtnl_neightbl_set_locktime(struct rtnl_neightbl *ntbl, uint64_t ms) 790{ 791 ntbl->nt_parms.ntp_locktime = ms; 792 ntbl->nt_parms.ntp_mask |= NEIGHTBLPARM_ATTR_LOCKTIME; 793 ntbl->ce_mask |= NEIGHTBL_ATTR_PARMS; 794} 795 796/** @} */ 797 798static struct nl_object_ops neightbl_obj_ops = { 799 .oo_name = "route/neightbl", 800 .oo_size = sizeof(struct rtnl_neightbl), 801 .oo_dump[NL_DUMP_BRIEF] = neightbl_dump_brief, 802 .oo_dump[NL_DUMP_FULL] = neightbl_dump_full, 803 .oo_dump[NL_DUMP_STATS] = neightbl_dump_stats, 804 .oo_compare = neightbl_compare, 805}; 806 807static struct nl_cache_ops rtnl_neightbl_ops = { 808 .co_name = "route/neightbl", 809 .co_hdrsize = sizeof(struct rtgenmsg), 810 .co_msgtypes = { 811 { RTM_NEWNEIGHTBL, NL_ACT_NEW, "new" }, 812 { RTM_SETNEIGHTBL, NL_ACT_SET, "set" }, 813 { RTM_GETNEIGHTBL, NL_ACT_GET, "get" }, 814 END_OF_MSGTYPES_LIST, 815 }, 816 .co_protocol = NETLINK_ROUTE, 817 .co_request_update = neightbl_request_update, 818 .co_msg_parser = neightbl_msg_parser, 819 .co_obj_ops = &neightbl_obj_ops, 820}; 821 822static void __init neightbl_init(void) 823{ 824 nl_cache_mngt_register(&rtnl_neightbl_ops); 825} 826 827static void __exit neightbl_exit(void) 828{ 829 nl_cache_mngt_unregister(&rtnl_neightbl_ops); 830} 831 832/** @} */ 833