aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/cfg80211.h7
-rw-r--r--include/uapi/linux/nl80211.h6
-rw-r--r--net/wireless/nl80211.c99
-rw-r--r--net/wireless/rdev-ops.h27
-rw-r--r--net/wireless/trace.h45
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
4627static 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
4667static 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
4627static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) 4717static 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
266static 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
266static inline int rdev_dump_mpath(struct cfg80211_registered_device *rdev, 278static 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
291static 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
804TRACE_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
825TRACE_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
804TRACE_EVENT(rdev_return_int_mpath_info, 849TRACE_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),