diff options
-rw-r--r-- | include/net/cfg80211.h | 7 | ||||
-rw-r--r-- | include/uapi/linux/nl80211.h | 6 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 99 | ||||
-rw-r--r-- | net/wireless/rdev-ops.h | 27 | ||||
-rw-r--r-- | net/wireless/trace.h | 45 |
5 files changed, 183 insertions, 1 deletions
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index a2ddcf2398fd..3f3aaa06adb5 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -2146,6 +2146,8 @@ struct cfg80211_qos_map { | |||
2146 | * @change_mpath: change a given mesh path | 2146 | * @change_mpath: change a given mesh path |
2147 | * @get_mpath: get a mesh path for the given parameters | 2147 | * @get_mpath: get a mesh path for the given parameters |
2148 | * @dump_mpath: dump mesh path callback -- resume dump at index @idx | 2148 | * @dump_mpath: dump mesh path callback -- resume dump at index @idx |
2149 | * @get_mpp: get a mesh proxy path for the given parameters | ||
2150 | * @dump_mpp: dump mesh proxy path callback -- resume dump at index @idx | ||
2149 | * @join_mesh: join the mesh network with the specified parameters | 2151 | * @join_mesh: join the mesh network with the specified parameters |
2150 | * (invoked with the wireless_dev mutex held) | 2152 | * (invoked with the wireless_dev mutex held) |
2151 | * @leave_mesh: leave the current mesh network | 2153 | * @leave_mesh: leave the current mesh network |
@@ -2396,6 +2398,11 @@ struct cfg80211_ops { | |||
2396 | int (*dump_mpath)(struct wiphy *wiphy, struct net_device *dev, | 2398 | int (*dump_mpath)(struct wiphy *wiphy, struct net_device *dev, |
2397 | int idx, u8 *dst, u8 *next_hop, | 2399 | int idx, u8 *dst, u8 *next_hop, |
2398 | struct mpath_info *pinfo); | 2400 | struct mpath_info *pinfo); |
2401 | int (*get_mpp)(struct wiphy *wiphy, struct net_device *dev, | ||
2402 | u8 *dst, u8 *mpp, struct mpath_info *pinfo); | ||
2403 | int (*dump_mpp)(struct wiphy *wiphy, struct net_device *dev, | ||
2404 | int idx, u8 *dst, u8 *mpp, | ||
2405 | struct mpath_info *pinfo); | ||
2399 | int (*get_mesh_config)(struct wiphy *wiphy, | 2406 | int (*get_mesh_config)(struct wiphy *wiphy, |
2400 | struct net_device *dev, | 2407 | struct net_device *dev, |
2401 | struct mesh_config *conf); | 2408 | struct mesh_config *conf); |
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 4b28dc07bcb1..846071b0cde9 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h | |||
@@ -738,6 +738,10 @@ | |||
738 | * before removing a station entry entirely, or before disassociating | 738 | * before removing a station entry entirely, or before disassociating |
739 | * or similar, cleanup will happen in the driver/device in this case. | 739 | * or similar, cleanup will happen in the driver/device in this case. |
740 | * | 740 | * |
741 | * @NL80211_CMD_GET_MPP: Get mesh path attributes for mesh proxy path to | ||
742 | * destination %NL80211_ATTR_MAC on the interface identified by | ||
743 | * %NL80211_ATTR_IFINDEX. | ||
744 | * | ||
741 | * @NL80211_CMD_MAX: highest used command number | 745 | * @NL80211_CMD_MAX: highest used command number |
742 | * @__NL80211_CMD_AFTER_LAST: internal use | 746 | * @__NL80211_CMD_AFTER_LAST: internal use |
743 | */ | 747 | */ |
@@ -912,6 +916,8 @@ enum nl80211_commands { | |||
912 | NL80211_CMD_ADD_TX_TS, | 916 | NL80211_CMD_ADD_TX_TS, |
913 | NL80211_CMD_DEL_TX_TS, | 917 | NL80211_CMD_DEL_TX_TS, |
914 | 918 | ||
919 | NL80211_CMD_GET_MPP, | ||
920 | |||
915 | /* add new commands above here */ | 921 | /* add new commands above here */ |
916 | 922 | ||
917 | /* used to define NL80211_CMD_MAX below */ | 923 | /* used to define NL80211_CMD_MAX below */ |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index cb9f5a44ffad..d527aa0706c1 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -4624,6 +4624,96 @@ static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info) | |||
4624 | return rdev_del_mpath(rdev, dev, dst); | 4624 | return rdev_del_mpath(rdev, dev, dst); |
4625 | } | 4625 | } |
4626 | 4626 | ||
4627 | static int nl80211_get_mpp(struct sk_buff *skb, struct genl_info *info) | ||
4628 | { | ||
4629 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | ||
4630 | int err; | ||
4631 | struct net_device *dev = info->user_ptr[1]; | ||
4632 | struct mpath_info pinfo; | ||
4633 | struct sk_buff *msg; | ||
4634 | u8 *dst = NULL; | ||
4635 | u8 mpp[ETH_ALEN]; | ||
4636 | |||
4637 | memset(&pinfo, 0, sizeof(pinfo)); | ||
4638 | |||
4639 | if (!info->attrs[NL80211_ATTR_MAC]) | ||
4640 | return -EINVAL; | ||
4641 | |||
4642 | dst = nla_data(info->attrs[NL80211_ATTR_MAC]); | ||
4643 | |||
4644 | if (!rdev->ops->get_mpp) | ||
4645 | return -EOPNOTSUPP; | ||
4646 | |||
4647 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) | ||
4648 | return -EOPNOTSUPP; | ||
4649 | |||
4650 | err = rdev_get_mpp(rdev, dev, dst, mpp, &pinfo); | ||
4651 | if (err) | ||
4652 | return err; | ||
4653 | |||
4654 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
4655 | if (!msg) | ||
4656 | return -ENOMEM; | ||
4657 | |||
4658 | if (nl80211_send_mpath(msg, info->snd_portid, info->snd_seq, 0, | ||
4659 | dev, dst, mpp, &pinfo) < 0) { | ||
4660 | nlmsg_free(msg); | ||
4661 | return -ENOBUFS; | ||
4662 | } | ||
4663 | |||
4664 | return genlmsg_reply(msg, info); | ||
4665 | } | ||
4666 | |||
4667 | static int nl80211_dump_mpp(struct sk_buff *skb, | ||
4668 | struct netlink_callback *cb) | ||
4669 | { | ||
4670 | struct mpath_info pinfo; | ||
4671 | struct cfg80211_registered_device *rdev; | ||
4672 | struct wireless_dev *wdev; | ||
4673 | u8 dst[ETH_ALEN]; | ||
4674 | u8 mpp[ETH_ALEN]; | ||
4675 | int path_idx = cb->args[2]; | ||
4676 | int err; | ||
4677 | |||
4678 | err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev); | ||
4679 | if (err) | ||
4680 | return err; | ||
4681 | |||
4682 | if (!rdev->ops->dump_mpp) { | ||
4683 | err = -EOPNOTSUPP; | ||
4684 | goto out_err; | ||
4685 | } | ||
4686 | |||
4687 | if (wdev->iftype != NL80211_IFTYPE_MESH_POINT) { | ||
4688 | err = -EOPNOTSUPP; | ||
4689 | goto out_err; | ||
4690 | } | ||
4691 | |||
4692 | while (1) { | ||
4693 | err = rdev_dump_mpp(rdev, wdev->netdev, path_idx, dst, | ||
4694 | mpp, &pinfo); | ||
4695 | if (err == -ENOENT) | ||
4696 | break; | ||
4697 | if (err) | ||
4698 | goto out_err; | ||
4699 | |||
4700 | if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).portid, | ||
4701 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | ||
4702 | wdev->netdev, dst, mpp, | ||
4703 | &pinfo) < 0) | ||
4704 | goto out; | ||
4705 | |||
4706 | path_idx++; | ||
4707 | } | ||
4708 | |||
4709 | out: | ||
4710 | cb->args[2] = path_idx; | ||
4711 | err = skb->len; | ||
4712 | out_err: | ||
4713 | nl80211_finish_wdev_dump(rdev); | ||
4714 | return err; | ||
4715 | } | ||
4716 | |||
4627 | static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) | 4717 | static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) |
4628 | { | 4718 | { |
4629 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 4719 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
@@ -9774,6 +9864,15 @@ static const struct genl_ops nl80211_ops[] = { | |||
9774 | NL80211_FLAG_NEED_RTNL, | 9864 | NL80211_FLAG_NEED_RTNL, |
9775 | }, | 9865 | }, |
9776 | { | 9866 | { |
9867 | .cmd = NL80211_CMD_GET_MPP, | ||
9868 | .doit = nl80211_get_mpp, | ||
9869 | .dumpit = nl80211_dump_mpp, | ||
9870 | .policy = nl80211_policy, | ||
9871 | .flags = GENL_ADMIN_PERM, | ||
9872 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | ||
9873 | NL80211_FLAG_NEED_RTNL, | ||
9874 | }, | ||
9875 | { | ||
9777 | .cmd = NL80211_CMD_SET_MPATH, | 9876 | .cmd = NL80211_CMD_SET_MPATH, |
9778 | .doit = nl80211_set_mpath, | 9877 | .doit = nl80211_set_mpath, |
9779 | .policy = nl80211_policy, | 9878 | .policy = nl80211_policy, |
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h index f6d457d6a558..c09e697bcb15 100644 --- a/net/wireless/rdev-ops.h +++ b/net/wireless/rdev-ops.h | |||
@@ -263,6 +263,18 @@ static inline int rdev_get_mpath(struct cfg80211_registered_device *rdev, | |||
263 | 263 | ||
264 | } | 264 | } |
265 | 265 | ||
266 | static inline int rdev_get_mpp(struct cfg80211_registered_device *rdev, | ||
267 | struct net_device *dev, u8 *dst, u8 *mpp, | ||
268 | struct mpath_info *pinfo) | ||
269 | { | ||
270 | int ret; | ||
271 | |||
272 | trace_rdev_get_mpp(&rdev->wiphy, dev, dst, mpp); | ||
273 | ret = rdev->ops->get_mpp(&rdev->wiphy, dev, dst, mpp, pinfo); | ||
274 | trace_rdev_return_int_mpath_info(&rdev->wiphy, ret, pinfo); | ||
275 | return ret; | ||
276 | } | ||
277 | |||
266 | static inline int rdev_dump_mpath(struct cfg80211_registered_device *rdev, | 278 | static inline int rdev_dump_mpath(struct cfg80211_registered_device *rdev, |
267 | struct net_device *dev, int idx, u8 *dst, | 279 | struct net_device *dev, int idx, u8 *dst, |
268 | u8 *next_hop, struct mpath_info *pinfo) | 280 | u8 *next_hop, struct mpath_info *pinfo) |
@@ -271,7 +283,20 @@ static inline int rdev_dump_mpath(struct cfg80211_registered_device *rdev, | |||
271 | int ret; | 283 | int ret; |
272 | trace_rdev_dump_mpath(&rdev->wiphy, dev, idx, dst, next_hop); | 284 | trace_rdev_dump_mpath(&rdev->wiphy, dev, idx, dst, next_hop); |
273 | ret = rdev->ops->dump_mpath(&rdev->wiphy, dev, idx, dst, next_hop, | 285 | ret = rdev->ops->dump_mpath(&rdev->wiphy, dev, idx, dst, next_hop, |
274 | pinfo); | 286 | pinfo); |
287 | trace_rdev_return_int_mpath_info(&rdev->wiphy, ret, pinfo); | ||
288 | return ret; | ||
289 | } | ||
290 | |||
291 | static inline int rdev_dump_mpp(struct cfg80211_registered_device *rdev, | ||
292 | struct net_device *dev, int idx, u8 *dst, | ||
293 | u8 *mpp, struct mpath_info *pinfo) | ||
294 | |||
295 | { | ||
296 | int ret; | ||
297 | |||
298 | trace_rdev_dump_mpp(&rdev->wiphy, dev, idx, dst, mpp); | ||
299 | ret = rdev->ops->dump_mpp(&rdev->wiphy, dev, idx, dst, mpp, pinfo); | ||
275 | trace_rdev_return_int_mpath_info(&rdev->wiphy, ret, pinfo); | 300 | trace_rdev_return_int_mpath_info(&rdev->wiphy, ret, pinfo); |
276 | return ret; | 301 | return ret; |
277 | } | 302 | } |
diff --git a/net/wireless/trace.h b/net/wireless/trace.h index 625a6e6d1168..8e4f8f04332d 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h | |||
@@ -801,6 +801,51 @@ TRACE_EVENT(rdev_dump_mpath, | |||
801 | MAC_PR_ARG(next_hop)) | 801 | MAC_PR_ARG(next_hop)) |
802 | ); | 802 | ); |
803 | 803 | ||
804 | TRACE_EVENT(rdev_get_mpp, | ||
805 | TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, | ||
806 | u8 *dst, u8 *mpp), | ||
807 | TP_ARGS(wiphy, netdev, dst, mpp), | ||
808 | TP_STRUCT__entry( | ||
809 | WIPHY_ENTRY | ||
810 | NETDEV_ENTRY | ||
811 | MAC_ENTRY(dst) | ||
812 | MAC_ENTRY(mpp) | ||
813 | ), | ||
814 | TP_fast_assign( | ||
815 | WIPHY_ASSIGN; | ||
816 | NETDEV_ASSIGN; | ||
817 | MAC_ASSIGN(dst, dst); | ||
818 | MAC_ASSIGN(mpp, mpp); | ||
819 | ), | ||
820 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", destination: " MAC_PR_FMT | ||
821 | ", mpp: " MAC_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG, | ||
822 | MAC_PR_ARG(dst), MAC_PR_ARG(mpp)) | ||
823 | ); | ||
824 | |||
825 | TRACE_EVENT(rdev_dump_mpp, | ||
826 | TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, int idx, | ||
827 | u8 *dst, u8 *mpp), | ||
828 | TP_ARGS(wiphy, netdev, idx, mpp, dst), | ||
829 | TP_STRUCT__entry( | ||
830 | WIPHY_ENTRY | ||
831 | NETDEV_ENTRY | ||
832 | MAC_ENTRY(dst) | ||
833 | MAC_ENTRY(mpp) | ||
834 | __field(int, idx) | ||
835 | ), | ||
836 | TP_fast_assign( | ||
837 | WIPHY_ASSIGN; | ||
838 | NETDEV_ASSIGN; | ||
839 | MAC_ASSIGN(dst, dst); | ||
840 | MAC_ASSIGN(mpp, mpp); | ||
841 | __entry->idx = idx; | ||
842 | ), | ||
843 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", index: %d, destination: " | ||
844 | MAC_PR_FMT ", mpp: " MAC_PR_FMT, | ||
845 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->idx, MAC_PR_ARG(dst), | ||
846 | MAC_PR_ARG(mpp)) | ||
847 | ); | ||
848 | |||
804 | TRACE_EVENT(rdev_return_int_mpath_info, | 849 | TRACE_EVENT(rdev_return_int_mpath_info, |
805 | TP_PROTO(struct wiphy *wiphy, int ret, struct mpath_info *pinfo), | 850 | TP_PROTO(struct wiphy *wiphy, int ret, struct mpath_info *pinfo), |
806 | TP_ARGS(wiphy, ret, pinfo), | 851 | TP_ARGS(wiphy, ret, pinfo), |