diff options
| author | Alexander Aring <alex.aring@gmail.com> | 2014-11-09 02:36:55 -0500 |
|---|---|---|
| committer | Marcel Holtmann <marcel@holtmann.org> | 2014-11-09 13:50:29 -0500 |
| commit | 4b96aea0fcdbba18287f6cca87c8d796f33157b6 (patch) | |
| tree | 24b66c550f99c6d20355e29dc29e2d0fbede8e5a /net/ieee802154 | |
| parent | ca20ce201c8d4123de0fd2b0d59ea19b0160d88f (diff) | |
ieee802154: add wpan_dev dump support
This patch adds support for wpan_dev dump via nl802154 framework.
Signed-off-by: Alexander Aring <alex.aring@gmail.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/ieee802154')
| -rw-r--r-- | net/ieee802154/nl802154.c | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index 32e884732eb1..46df7dca92d9 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c | |||
| @@ -198,6 +198,8 @@ static const struct nla_policy nl802154_policy[NL802154_ATTR_MAX+1] = { | |||
| 198 | .len = 20-1 }, | 198 | .len = 20-1 }, |
| 199 | 199 | ||
| 200 | [NL802154_ATTR_IFINDEX] = { .type = NLA_U32 }, | 200 | [NL802154_ATTR_IFINDEX] = { .type = NLA_U32 }, |
| 201 | [NL802154_ATTR_IFTYPE] = { .type = NLA_U32 }, | ||
| 202 | [NL802154_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 }, | ||
| 201 | 203 | ||
| 202 | [NL802154_ATTR_WPAN_DEV] = { .type = NLA_U64 }, | 204 | [NL802154_ATTR_WPAN_DEV] = { .type = NLA_U64 }, |
| 203 | 205 | ||
| @@ -209,6 +211,18 @@ static const struct nla_policy nl802154_policy[NL802154_ATTR_MAX+1] = { | |||
| 209 | [NL802154_ATTR_CCA_MODE] = { .type = NLA_U8, }, | 211 | [NL802154_ATTR_CCA_MODE] = { .type = NLA_U8, }, |
| 210 | 212 | ||
| 211 | [NL802154_ATTR_SUPPORTED_CHANNEL] = { .type = NLA_U32, }, | 213 | [NL802154_ATTR_SUPPORTED_CHANNEL] = { .type = NLA_U32, }, |
| 214 | |||
| 215 | [NL802154_ATTR_PAN_ID] = { .type = NLA_U16, }, | ||
| 216 | [NL802154_ATTR_EXTENDED_ADDR] = { .type = NLA_U64 }, | ||
| 217 | [NL802154_ATTR_SHORT_ADDR] = { .type = NLA_U16, }, | ||
| 218 | |||
| 219 | [NL802154_ATTR_MIN_BE] = { .type = NLA_U8, }, | ||
| 220 | [NL802154_ATTR_MAX_BE] = { .type = NLA_U8, }, | ||
| 221 | [NL802154_ATTR_MAX_CSMA_BACKOFFS] = { .type = NLA_U8, }, | ||
| 222 | |||
| 223 | [NL802154_ATTR_MAX_FRAME_RETRIES] = { .type = NLA_S8, }, | ||
| 224 | |||
| 225 | [NL802154_ATTR_LBT_MODE] = { .type = NLA_U8, }, | ||
| 212 | }; | 226 | }; |
| 213 | 227 | ||
| 214 | /* message building helper */ | 228 | /* message building helper */ |
| @@ -414,6 +428,128 @@ static int nl802154_get_wpan_phy(struct sk_buff *skb, struct genl_info *info) | |||
| 414 | return genlmsg_reply(msg, info); | 428 | return genlmsg_reply(msg, info); |
| 415 | } | 429 | } |
| 416 | 430 | ||
| 431 | static inline u64 wpan_dev_id(struct wpan_dev *wpan_dev) | ||
| 432 | { | ||
| 433 | return (u64)wpan_dev->identifier | | ||
| 434 | ((u64)wpan_phy_to_rdev(wpan_dev->wpan_phy)->wpan_phy_idx << 32); | ||
| 435 | } | ||
| 436 | |||
| 437 | static int | ||
| 438 | nl802154_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags, | ||
| 439 | struct cfg802154_registered_device *rdev, | ||
| 440 | struct wpan_dev *wpan_dev) | ||
| 441 | { | ||
| 442 | struct net_device *dev = wpan_dev->netdev; | ||
| 443 | void *hdr; | ||
| 444 | |||
| 445 | hdr = nl802154hdr_put(msg, portid, seq, flags, | ||
| 446 | NL802154_CMD_NEW_INTERFACE); | ||
| 447 | if (!hdr) | ||
| 448 | return -1; | ||
| 449 | |||
| 450 | if (dev && | ||
| 451 | (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex) || | ||
| 452 | nla_put_string(msg, NL802154_ATTR_IFNAME, dev->name))) | ||
| 453 | goto nla_put_failure; | ||
| 454 | |||
| 455 | if (nla_put_u32(msg, NL802154_ATTR_WPAN_PHY, rdev->wpan_phy_idx) || | ||
| 456 | nla_put_u32(msg, NL802154_ATTR_IFTYPE, wpan_dev->iftype) || | ||
| 457 | nla_put_u64(msg, NL802154_ATTR_WPAN_DEV, wpan_dev_id(wpan_dev)) || | ||
| 458 | nla_put_u32(msg, NL802154_ATTR_GENERATION, | ||
| 459 | rdev->devlist_generation ^ | ||
| 460 | (cfg802154_rdev_list_generation << 2))) | ||
| 461 | goto nla_put_failure; | ||
| 462 | |||
| 463 | /* address settings */ | ||
| 464 | if (nla_put_le64(msg, NL802154_ATTR_EXTENDED_ADDR, | ||
| 465 | wpan_dev->extended_addr) || | ||
| 466 | nla_put_le16(msg, NL802154_ATTR_SHORT_ADDR, | ||
| 467 | wpan_dev->short_addr) || | ||
| 468 | nla_put_le16(msg, NL802154_ATTR_PAN_ID, wpan_dev->pan_id)) | ||
| 469 | goto nla_put_failure; | ||
| 470 | |||
| 471 | /* ARET handling */ | ||
| 472 | if (nla_put_s8(msg, NL802154_ATTR_MAX_FRAME_RETRIES, | ||
| 473 | wpan_dev->frame_retries) || | ||
| 474 | nla_put_u8(msg, NL802154_ATTR_MAX_BE, wpan_dev->max_be) || | ||
| 475 | nla_put_u8(msg, NL802154_ATTR_MAX_CSMA_BACKOFFS, | ||
| 476 | wpan_dev->csma_retries) || | ||
| 477 | nla_put_u8(msg, NL802154_ATTR_MIN_BE, wpan_dev->min_be)) | ||
| 478 | goto nla_put_failure; | ||
| 479 | |||
| 480 | /* listen before transmit */ | ||
| 481 | if (nla_put_u8(msg, NL802154_ATTR_LBT_MODE, wpan_dev->lbt)) | ||
| 482 | goto nla_put_failure; | ||
| 483 | |||
| 484 | return genlmsg_end(msg, hdr); | ||
| 485 | |||
| 486 | nla_put_failure: | ||
| 487 | genlmsg_cancel(msg, hdr); | ||
| 488 | return -EMSGSIZE; | ||
| 489 | } | ||
| 490 | |||
| 491 | static int | ||
| 492 | nl802154_dump_interface(struct sk_buff *skb, struct netlink_callback *cb) | ||
| 493 | { | ||
| 494 | int wp_idx = 0; | ||
| 495 | int if_idx = 0; | ||
| 496 | int wp_start = cb->args[0]; | ||
| 497 | int if_start = cb->args[1]; | ||
| 498 | struct cfg802154_registered_device *rdev; | ||
| 499 | struct wpan_dev *wpan_dev; | ||
| 500 | |||
| 501 | rtnl_lock(); | ||
| 502 | list_for_each_entry(rdev, &cfg802154_rdev_list, list) { | ||
| 503 | /* TODO netns compare */ | ||
| 504 | if (wp_idx < wp_start) { | ||
| 505 | wp_idx++; | ||
| 506 | continue; | ||
| 507 | } | ||
| 508 | if_idx = 0; | ||
| 509 | |||
| 510 | list_for_each_entry(wpan_dev, &rdev->wpan_dev_list, list) { | ||
| 511 | if (if_idx < if_start) { | ||
| 512 | if_idx++; | ||
| 513 | continue; | ||
| 514 | } | ||
| 515 | if (nl802154_send_iface(skb, NETLINK_CB(cb->skb).portid, | ||
| 516 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | ||
| 517 | rdev, wpan_dev) < 0) { | ||
| 518 | goto out; | ||
| 519 | } | ||
| 520 | if_idx++; | ||
| 521 | } | ||
| 522 | |||
| 523 | wp_idx++; | ||
| 524 | } | ||
| 525 | out: | ||
| 526 | rtnl_unlock(); | ||
| 527 | |||
| 528 | cb->args[0] = wp_idx; | ||
| 529 | cb->args[1] = if_idx; | ||
| 530 | |||
| 531 | return skb->len; | ||
| 532 | } | ||
| 533 | |||
| 534 | static int nl802154_get_interface(struct sk_buff *skb, struct genl_info *info) | ||
| 535 | { | ||
| 536 | struct sk_buff *msg; | ||
| 537 | struct cfg802154_registered_device *rdev = info->user_ptr[0]; | ||
| 538 | struct wpan_dev *wdev = info->user_ptr[1]; | ||
| 539 | |||
| 540 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
| 541 | if (!msg) | ||
| 542 | return -ENOMEM; | ||
| 543 | |||
| 544 | if (nl802154_send_iface(msg, info->snd_portid, info->snd_seq, 0, | ||
| 545 | rdev, wdev) < 0) { | ||
| 546 | nlmsg_free(msg); | ||
| 547 | return -ENOBUFS; | ||
| 548 | } | ||
| 549 | |||
| 550 | return genlmsg_reply(msg, info); | ||
| 551 | } | ||
| 552 | |||
| 417 | #define NL802154_FLAG_NEED_WPAN_PHY 0x01 | 553 | #define NL802154_FLAG_NEED_WPAN_PHY 0x01 |
| 418 | #define NL802154_FLAG_NEED_NETDEV 0x02 | 554 | #define NL802154_FLAG_NEED_NETDEV 0x02 |
| 419 | #define NL802154_FLAG_NEED_RTNL 0x04 | 555 | #define NL802154_FLAG_NEED_RTNL 0x04 |
| @@ -515,6 +651,15 @@ static const struct genl_ops nl802154_ops[] = { | |||
| 515 | .internal_flags = NL802154_FLAG_NEED_WPAN_PHY | | 651 | .internal_flags = NL802154_FLAG_NEED_WPAN_PHY | |
| 516 | NL802154_FLAG_NEED_RTNL, | 652 | NL802154_FLAG_NEED_RTNL, |
| 517 | }, | 653 | }, |
| 654 | { | ||
| 655 | .cmd = NL802154_CMD_GET_INTERFACE, | ||
| 656 | .doit = nl802154_get_interface, | ||
| 657 | .dumpit = nl802154_dump_interface, | ||
| 658 | .policy = nl802154_policy, | ||
| 659 | /* can be retrieved by unprivileged users */ | ||
| 660 | .internal_flags = NL802154_FLAG_NEED_WPAN_DEV | | ||
| 661 | NL802154_FLAG_NEED_RTNL, | ||
| 662 | }, | ||
| 518 | }; | 663 | }; |
| 519 | 664 | ||
| 520 | /* initialisation/exit functions */ | 665 | /* initialisation/exit functions */ |
