diff options
Diffstat (limited to 'net/mac80211/tx.c')
-rw-r--r-- | net/mac80211/tx.c | 75 |
1 files changed, 54 insertions, 21 deletions
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 20d683641b42..0cc2e23f082c 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -165,11 +165,10 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, | |||
165 | return cpu_to_le16(dur); | 165 | return cpu_to_le16(dur); |
166 | } | 166 | } |
167 | 167 | ||
168 | static int inline is_ieee80211_device(struct net_device *dev, | 168 | static int inline is_ieee80211_device(struct ieee80211_local *local, |
169 | struct net_device *master) | 169 | struct net_device *dev) |
170 | { | 170 | { |
171 | return (wdev_priv(dev->ieee80211_ptr) == | 171 | return local == wdev_priv(dev->ieee80211_ptr); |
172 | wdev_priv(master->ieee80211_ptr)); | ||
173 | } | 172 | } |
174 | 173 | ||
175 | /* tx handlers */ | 174 | /* tx handlers */ |
@@ -447,7 +446,8 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | |||
447 | sband = tx->local->hw.wiphy->bands[tx->channel->band]; | 446 | sband = tx->local->hw.wiphy->bands[tx->channel->band]; |
448 | 447 | ||
449 | if (likely(tx->rate_idx < 0)) { | 448 | if (likely(tx->rate_idx < 0)) { |
450 | rate_control_get_rate(tx->dev, sband, tx->skb, &rsel); | 449 | rate_control_get_rate(tx->sdata, sband, tx->sta, |
450 | tx->skb, &rsel); | ||
451 | if (tx->sta) | 451 | if (tx->sta) |
452 | tx->sta->last_txrate_idx = rsel.rate_idx; | 452 | tx->sta->last_txrate_idx = rsel.rate_idx; |
453 | tx->rate_idx = rsel.rate_idx; | 453 | tx->rate_idx = rsel.rate_idx; |
@@ -1001,14 +1001,14 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, | |||
1001 | /* | 1001 | /* |
1002 | * NB: @tx is uninitialised when passed in here | 1002 | * NB: @tx is uninitialised when passed in here |
1003 | */ | 1003 | */ |
1004 | static int ieee80211_tx_prepare(struct ieee80211_tx_data *tx, | 1004 | static int ieee80211_tx_prepare(struct ieee80211_local *local, |
1005 | struct sk_buff *skb, | 1005 | struct ieee80211_tx_data *tx, |
1006 | struct net_device *mdev) | 1006 | struct sk_buff *skb) |
1007 | { | 1007 | { |
1008 | struct net_device *dev; | 1008 | struct net_device *dev; |
1009 | 1009 | ||
1010 | dev = dev_get_by_index(&init_net, skb->iif); | 1010 | dev = dev_get_by_index(&init_net, skb->iif); |
1011 | if (unlikely(dev && !is_ieee80211_device(dev, mdev))) { | 1011 | if (unlikely(dev && !is_ieee80211_device(local, dev))) { |
1012 | dev_put(dev); | 1012 | dev_put(dev); |
1013 | dev = NULL; | 1013 | dev = NULL; |
1014 | } | 1014 | } |
@@ -1258,6 +1258,8 @@ static int ieee80211_skb_resize(struct ieee80211_local *local, | |||
1258 | int ieee80211_master_start_xmit(struct sk_buff *skb, | 1258 | int ieee80211_master_start_xmit(struct sk_buff *skb, |
1259 | struct net_device *dev) | 1259 | struct net_device *dev) |
1260 | { | 1260 | { |
1261 | struct ieee80211_master_priv *mpriv = netdev_priv(dev); | ||
1262 | struct ieee80211_local *local = mpriv->local; | ||
1261 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1263 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1262 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 1264 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
1263 | struct net_device *odev = NULL; | 1265 | struct net_device *odev = NULL; |
@@ -1273,7 +1275,7 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, | |||
1273 | 1275 | ||
1274 | if (skb->iif) | 1276 | if (skb->iif) |
1275 | odev = dev_get_by_index(&init_net, skb->iif); | 1277 | odev = dev_get_by_index(&init_net, skb->iif); |
1276 | if (unlikely(odev && !is_ieee80211_device(odev, dev))) { | 1278 | if (unlikely(odev && !is_ieee80211_device(local, odev))) { |
1277 | dev_put(odev); | 1279 | dev_put(odev); |
1278 | odev = NULL; | 1280 | odev = NULL; |
1279 | } | 1281 | } |
@@ -1449,8 +1451,8 @@ fail: | |||
1449 | int ieee80211_subif_start_xmit(struct sk_buff *skb, | 1451 | int ieee80211_subif_start_xmit(struct sk_buff *skb, |
1450 | struct net_device *dev) | 1452 | struct net_device *dev) |
1451 | { | 1453 | { |
1452 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1454 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1453 | struct ieee80211_sub_if_data *sdata; | 1455 | struct ieee80211_local *local = sdata->local; |
1454 | int ret = 1, head_need; | 1456 | int ret = 1, head_need; |
1455 | u16 ethertype, hdrlen, meshhdrlen = 0; | 1457 | u16 ethertype, hdrlen, meshhdrlen = 0; |
1456 | __le16 fc; | 1458 | __le16 fc; |
@@ -1462,7 +1464,6 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1462 | struct sta_info *sta; | 1464 | struct sta_info *sta; |
1463 | u32 sta_flags = 0; | 1465 | u32 sta_flags = 0; |
1464 | 1466 | ||
1465 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1466 | if (unlikely(skb->len < ETH_HLEN)) { | 1467 | if (unlikely(skb->len < ETH_HLEN)) { |
1467 | ret = 0; | 1468 | ret = 0; |
1468 | goto fail; | 1469 | goto fail; |
@@ -1498,18 +1499,50 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1498 | #ifdef CONFIG_MAC80211_MESH | 1499 | #ifdef CONFIG_MAC80211_MESH |
1499 | case NL80211_IFTYPE_MESH_POINT: | 1500 | case NL80211_IFTYPE_MESH_POINT: |
1500 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); | 1501 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); |
1501 | /* RA TA DA SA */ | ||
1502 | memset(hdr.addr1, 0, ETH_ALEN); | ||
1503 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); | ||
1504 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | ||
1505 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); | ||
1506 | if (!sdata->u.mesh.mshcfg.dot11MeshTTL) { | 1502 | if (!sdata->u.mesh.mshcfg.dot11MeshTTL) { |
1507 | /* Do not send frames with mesh_ttl == 0 */ | 1503 | /* Do not send frames with mesh_ttl == 0 */ |
1508 | sdata->u.mesh.mshstats.dropped_frames_ttl++; | 1504 | sdata->u.mesh.mshstats.dropped_frames_ttl++; |
1509 | ret = 0; | 1505 | ret = 0; |
1510 | goto fail; | 1506 | goto fail; |
1511 | } | 1507 | } |
1512 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, sdata); | 1508 | memset(&mesh_hdr, 0, sizeof(mesh_hdr)); |
1509 | |||
1510 | if (compare_ether_addr(dev->dev_addr, | ||
1511 | skb->data + ETH_ALEN) == 0) { | ||
1512 | /* RA TA DA SA */ | ||
1513 | memset(hdr.addr1, 0, ETH_ALEN); | ||
1514 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); | ||
1515 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | ||
1516 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); | ||
1517 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, sdata); | ||
1518 | } else { | ||
1519 | /* packet from other interface */ | ||
1520 | struct mesh_path *mppath; | ||
1521 | |||
1522 | memset(hdr.addr1, 0, ETH_ALEN); | ||
1523 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); | ||
1524 | memcpy(hdr.addr4, dev->dev_addr, ETH_ALEN); | ||
1525 | |||
1526 | if (is_multicast_ether_addr(skb->data)) | ||
1527 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | ||
1528 | else { | ||
1529 | rcu_read_lock(); | ||
1530 | mppath = mpp_path_lookup(skb->data, sdata); | ||
1531 | if (mppath) | ||
1532 | memcpy(hdr.addr3, mppath->mpp, ETH_ALEN); | ||
1533 | else | ||
1534 | memset(hdr.addr3, 0xff, ETH_ALEN); | ||
1535 | rcu_read_unlock(); | ||
1536 | } | ||
1537 | |||
1538 | mesh_hdr.flags |= MESH_FLAGS_AE_A5_A6; | ||
1539 | mesh_hdr.ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; | ||
1540 | put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &mesh_hdr.seqnum); | ||
1541 | memcpy(mesh_hdr.eaddr1, skb->data, ETH_ALEN); | ||
1542 | memcpy(mesh_hdr.eaddr2, skb->data + ETH_ALEN, ETH_ALEN); | ||
1543 | sdata->u.mesh.mesh_seqnum++; | ||
1544 | meshhdrlen = 18; | ||
1545 | } | ||
1513 | hdrlen = 30; | 1546 | hdrlen = 30; |
1514 | break; | 1547 | break; |
1515 | #endif | 1548 | #endif |
@@ -1923,7 +1956,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
1923 | skb->do_not_encrypt = 1; | 1956 | skb->do_not_encrypt = 1; |
1924 | 1957 | ||
1925 | info->band = band; | 1958 | info->band = band; |
1926 | rate_control_get_rate(local->mdev, sband, skb, &rsel); | 1959 | rate_control_get_rate(sdata, sband, NULL, skb, &rsel); |
1927 | 1960 | ||
1928 | if (unlikely(rsel.rate_idx < 0)) { | 1961 | if (unlikely(rsel.rate_idx < 0)) { |
1929 | if (net_ratelimit()) { | 1962 | if (net_ratelimit()) { |
@@ -2032,7 +2065,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, | |||
2032 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); | 2065 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); |
2033 | } | 2066 | } |
2034 | 2067 | ||
2035 | if (!ieee80211_tx_prepare(&tx, skb, local->mdev)) | 2068 | if (!ieee80211_tx_prepare(local, &tx, skb)) |
2036 | break; | 2069 | break; |
2037 | dev_kfree_skb_any(skb); | 2070 | dev_kfree_skb_any(skb); |
2038 | } | 2071 | } |