summaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2014-09-09 15:55:35 -0400
committerJohannes Berg <johannes.berg@intel.com>2014-09-11 06:21:18 -0400
commit960d01acf62747d6518694f92be5b06f67473833 (patch)
tree5b57554171de78264adaa953b125f6c741911e51 /net/wireless
parent9d58f25b12f70f52581a5a1fdb1e59d322c4c729 (diff)
cfg80211: add WMM traffic stream API
Add nl80211 and driver API to validate, add and delete traffic streams with appropriate settings. The API calls for userspace doing the action frame handshake with the peer, and then allows only to set up the parameters in the driver. To avoid setting up a session only to tear it down again, the validate API is provided, but the real usage later can still fail so userspace must be prepared for that. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/nl80211.c109
-rw-r--r--net/wireless/rdev-ops.h31
-rw-r--r--net/wireless/trace.h45
3 files changed, 185 insertions, 0 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index e9fbd4f4ddb0..ab7ee4893e40 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -391,6 +391,9 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
391 [NL80211_ATTR_IFACE_SOCKET_OWNER] = { .type = NLA_FLAG }, 391 [NL80211_ATTR_IFACE_SOCKET_OWNER] = { .type = NLA_FLAG },
392 [NL80211_ATTR_CSA_C_OFFSETS_TX] = { .type = NLA_BINARY }, 392 [NL80211_ATTR_CSA_C_OFFSETS_TX] = { .type = NLA_BINARY },
393 [NL80211_ATTR_USE_RRM] = { .type = NLA_FLAG }, 393 [NL80211_ATTR_USE_RRM] = { .type = NLA_FLAG },
394 [NL80211_ATTR_TSID] = { .type = NLA_U8 },
395 [NL80211_ATTR_USER_PRIO] = { .type = NLA_U8 },
396 [NL80211_ATTR_ADMITTED_TIME] = { .type = NLA_U16 },
394}; 397};
395 398
396/* policy for the key attributes */ 399/* policy for the key attributes */
@@ -1510,6 +1513,9 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
1510 if (rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH) 1513 if (rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH)
1511 CMD(channel_switch, CHANNEL_SWITCH); 1514 CMD(channel_switch, CHANNEL_SWITCH);
1512 CMD(set_qos_map, SET_QOS_MAP); 1515 CMD(set_qos_map, SET_QOS_MAP);
1516 if (rdev->wiphy.flags &
1517 WIPHY_FLAG_SUPPORTS_WMM_ADMISSION)
1518 CMD(add_tx_ts, ADD_TX_TS);
1513 } 1519 }
1514 /* add into the if now */ 1520 /* add into the if now */
1515#undef CMD 1521#undef CMD
@@ -9390,6 +9396,93 @@ static int nl80211_set_qos_map(struct sk_buff *skb,
9390 return ret; 9396 return ret;
9391} 9397}
9392 9398
9399static int nl80211_add_tx_ts(struct sk_buff *skb, struct genl_info *info)
9400{
9401 struct cfg80211_registered_device *rdev = info->user_ptr[0];
9402 struct net_device *dev = info->user_ptr[1];
9403 struct wireless_dev *wdev = dev->ieee80211_ptr;
9404 const u8 *peer;
9405 u8 tsid, up;
9406 u16 admitted_time = 0;
9407 int err;
9408
9409 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_WMM_ADMISSION))
9410 return -EOPNOTSUPP;
9411
9412 if (!info->attrs[NL80211_ATTR_TSID] || !info->attrs[NL80211_ATTR_MAC] ||
9413 !info->attrs[NL80211_ATTR_USER_PRIO])
9414 return -EINVAL;
9415
9416 tsid = nla_get_u8(info->attrs[NL80211_ATTR_TSID]);
9417 if (tsid >= IEEE80211_NUM_TIDS)
9418 return -EINVAL;
9419
9420 up = nla_get_u8(info->attrs[NL80211_ATTR_USER_PRIO]);
9421 if (up >= IEEE80211_NUM_UPS)
9422 return -EINVAL;
9423
9424 /* WMM uses TIDs 0-7 even for TSPEC */
9425 if (tsid < IEEE80211_FIRST_TSPEC_TSID) {
9426 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_WMM_ADMISSION))
9427 return -EINVAL;
9428 } else {
9429 /* TODO: handle 802.11 TSPEC/admission control
9430 * need more attributes for that (e.g. BA session requirement)
9431 */
9432 return -EINVAL;
9433 }
9434
9435 peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
9436
9437 if (info->attrs[NL80211_ATTR_ADMITTED_TIME]) {
9438 admitted_time =
9439 nla_get_u16(info->attrs[NL80211_ATTR_ADMITTED_TIME]);
9440 if (!admitted_time)
9441 return -EINVAL;
9442 }
9443
9444 wdev_lock(wdev);
9445 switch (wdev->iftype) {
9446 case NL80211_IFTYPE_STATION:
9447 case NL80211_IFTYPE_P2P_CLIENT:
9448 if (wdev->current_bss)
9449 break;
9450 err = -ENOTCONN;
9451 goto out;
9452 default:
9453 err = -EOPNOTSUPP;
9454 goto out;
9455 }
9456
9457 err = rdev_add_tx_ts(rdev, dev, tsid, peer, up, admitted_time);
9458
9459 out:
9460 wdev_unlock(wdev);
9461 return err;
9462}
9463
9464static int nl80211_del_tx_ts(struct sk_buff *skb, struct genl_info *info)
9465{
9466 struct cfg80211_registered_device *rdev = info->user_ptr[0];
9467 struct net_device *dev = info->user_ptr[1];
9468 struct wireless_dev *wdev = dev->ieee80211_ptr;
9469 const u8 *peer;
9470 u8 tsid;
9471 int err;
9472
9473 if (!info->attrs[NL80211_ATTR_TSID] || !info->attrs[NL80211_ATTR_MAC])
9474 return -EINVAL;
9475
9476 tsid = nla_get_u8(info->attrs[NL80211_ATTR_TSID]);
9477 peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
9478
9479 wdev_lock(wdev);
9480 err = rdev_del_tx_ts(rdev, dev, tsid, peer);
9481 wdev_unlock(wdev);
9482
9483 return err;
9484}
9485
9393#define NL80211_FLAG_NEED_WIPHY 0x01 9486#define NL80211_FLAG_NEED_WIPHY 0x01
9394#define NL80211_FLAG_NEED_NETDEV 0x02 9487#define NL80211_FLAG_NEED_NETDEV 0x02
9395#define NL80211_FLAG_NEED_RTNL 0x04 9488#define NL80211_FLAG_NEED_RTNL 0x04
@@ -10147,6 +10240,22 @@ static const struct genl_ops nl80211_ops[] = {
10147 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 10240 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10148 NL80211_FLAG_NEED_RTNL, 10241 NL80211_FLAG_NEED_RTNL,
10149 }, 10242 },
10243 {
10244 .cmd = NL80211_CMD_ADD_TX_TS,
10245 .doit = nl80211_add_tx_ts,
10246 .policy = nl80211_policy,
10247 .flags = GENL_ADMIN_PERM,
10248 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10249 NL80211_FLAG_NEED_RTNL,
10250 },
10251 {
10252 .cmd = NL80211_CMD_DEL_TX_TS,
10253 .doit = nl80211_del_tx_ts,
10254 .policy = nl80211_policy,
10255 .flags = GENL_ADMIN_PERM,
10256 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10257 NL80211_FLAG_NEED_RTNL,
10258 },
10150}; 10259};
10151 10260
10152/* notification functions */ 10261/* notification functions */
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index 56c2240c30ce..f6d457d6a558 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -915,4 +915,35 @@ rdev_set_ap_chanwidth(struct cfg80211_registered_device *rdev,
915 return ret; 915 return ret;
916} 916}
917 917
918static inline int
919rdev_add_tx_ts(struct cfg80211_registered_device *rdev,
920 struct net_device *dev, u8 tsid, const u8 *peer,
921 u8 user_prio, u16 admitted_time)
922{
923 int ret = -EOPNOTSUPP;
924
925 trace_rdev_add_tx_ts(&rdev->wiphy, dev, tsid, peer,
926 user_prio, admitted_time);
927 if (rdev->ops->add_tx_ts)
928 ret = rdev->ops->add_tx_ts(&rdev->wiphy, dev, tsid, peer,
929 user_prio, admitted_time);
930 trace_rdev_return_int(&rdev->wiphy, ret);
931
932 return ret;
933}
934
935static inline int
936rdev_del_tx_ts(struct cfg80211_registered_device *rdev,
937 struct net_device *dev, u8 tsid, const u8 *peer)
938{
939 int ret = -EOPNOTSUPP;
940
941 trace_rdev_del_tx_ts(&rdev->wiphy, dev, tsid, peer);
942 if (rdev->ops->del_tx_ts)
943 ret = rdev->ops->del_tx_ts(&rdev->wiphy, dev, tsid, peer);
944 trace_rdev_return_int(&rdev->wiphy, ret);
945
946 return ret;
947}
948
918#endif /* __CFG80211_RDEV_OPS */ 949#endif /* __CFG80211_RDEV_OPS */
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index 0c524cd76c83..625a6e6d1168 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -1896,6 +1896,51 @@ TRACE_EVENT(rdev_set_ap_chanwidth,
1896 WIPHY_PR_ARG, NETDEV_PR_ARG, CHAN_DEF_PR_ARG) 1896 WIPHY_PR_ARG, NETDEV_PR_ARG, CHAN_DEF_PR_ARG)
1897); 1897);
1898 1898
1899TRACE_EVENT(rdev_add_tx_ts,
1900 TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
1901 u8 tsid, const u8 *peer, u8 user_prio, u16 admitted_time),
1902 TP_ARGS(wiphy, netdev, tsid, peer, user_prio, admitted_time),
1903 TP_STRUCT__entry(
1904 WIPHY_ENTRY
1905 NETDEV_ENTRY
1906 MAC_ENTRY(peer)
1907 __field(u8, tsid)
1908 __field(u8, user_prio)
1909 __field(u16, admitted_time)
1910 ),
1911 TP_fast_assign(
1912 WIPHY_ASSIGN;
1913 NETDEV_ASSIGN;
1914 MAC_ASSIGN(peer, peer);
1915 __entry->tsid = tsid;
1916 __entry->user_prio = user_prio;
1917 __entry->admitted_time = admitted_time;
1918 ),
1919 TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT ", TSID %d, UP %d, time %d",
1920 WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer),
1921 __entry->tsid, __entry->user_prio, __entry->admitted_time)
1922);
1923
1924TRACE_EVENT(rdev_del_tx_ts,
1925 TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
1926 u8 tsid, const u8 *peer),
1927 TP_ARGS(wiphy, netdev, tsid, peer),
1928 TP_STRUCT__entry(
1929 WIPHY_ENTRY
1930 NETDEV_ENTRY
1931 MAC_ENTRY(peer)
1932 __field(u8, tsid)
1933 ),
1934 TP_fast_assign(
1935 WIPHY_ASSIGN;
1936 NETDEV_ASSIGN;
1937 MAC_ASSIGN(peer, peer);
1938 __entry->tsid = tsid;
1939 ),
1940 TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT ", TSID %d",
1941 WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer), __entry->tsid)
1942);
1943
1899/************************************************************* 1944/*************************************************************
1900 * cfg80211 exported functions traces * 1945 * cfg80211 exported functions traces *
1901 *************************************************************/ 1946 *************************************************************/