aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mesh_hwmp.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/mesh_hwmp.c')
-rw-r--r--net/mac80211/mesh_hwmp.c47
1 files changed, 34 insertions, 13 deletions
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index f49ef288e2e2..e12a786e26b8 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -201,6 +201,24 @@ int mesh_path_error_tx(u8 *dst, __le32 dst_dsn, u8 *ra,
201 return 0; 201 return 0;
202} 202}
203 203
204void ieee80211s_update_metric(struct ieee80211_local *local,
205 struct sta_info *stainfo, struct sk_buff *skb)
206{
207 struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb);
208 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
209 int failed;
210
211 if (!ieee80211_is_data(hdr->frame_control))
212 return;
213
214 failed = !(txinfo->flags & IEEE80211_TX_STAT_ACK);
215
216 /* moving average, scaled to 100 */
217 stainfo->fail_avg = ((80 * stainfo->fail_avg + 5) / 100 + 20 * failed);
218 if (stainfo->fail_avg > 95)
219 mesh_plink_broken(stainfo);
220}
221
204static u32 airtime_link_metric_get(struct ieee80211_local *local, 222static u32 airtime_link_metric_get(struct ieee80211_local *local,
205 struct sta_info *sta) 223 struct sta_info *sta)
206{ 224{
@@ -397,7 +415,8 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
397 415
398static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, 416static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
399 struct ieee80211_mgmt *mgmt, 417 struct ieee80211_mgmt *mgmt,
400 u8 *preq_elem, u32 metric) { 418 u8 *preq_elem, u32 metric)
419{
401 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; 420 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
402 struct mesh_path *mpath; 421 struct mesh_path *mpath;
403 u8 *dst_addr, *orig_addr; 422 u8 *dst_addr, *orig_addr;
@@ -430,7 +449,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
430 if ((!(mpath->flags & MESH_PATH_DSN_VALID)) || 449 if ((!(mpath->flags & MESH_PATH_DSN_VALID)) ||
431 DSN_LT(mpath->dsn, dst_dsn)) { 450 DSN_LT(mpath->dsn, dst_dsn)) {
432 mpath->dsn = dst_dsn; 451 mpath->dsn = dst_dsn;
433 mpath->flags &= MESH_PATH_DSN_VALID; 452 mpath->flags |= MESH_PATH_DSN_VALID;
434 } else if ((!(dst_flags & MP_F_DO)) && 453 } else if ((!(dst_flags & MP_F_DO)) &&
435 (mpath->flags & MESH_PATH_ACTIVE)) { 454 (mpath->flags & MESH_PATH_ACTIVE)) {
436 reply = true; 455 reply = true;
@@ -478,6 +497,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
478 hopcount, ttl, cpu_to_le32(lifetime), 497 hopcount, ttl, cpu_to_le32(lifetime),
479 cpu_to_le32(metric), cpu_to_le32(preq_id), 498 cpu_to_le32(metric), cpu_to_le32(preq_id),
480 sdata); 499 sdata);
500 ifmsh->mshstats.fwded_mcast++;
481 ifmsh->mshstats.fwded_frames++; 501 ifmsh->mshstats.fwded_frames++;
482 } 502 }
483} 503}
@@ -536,6 +556,8 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata,
536 cpu_to_le32(lifetime), cpu_to_le32(metric), 556 cpu_to_le32(lifetime), cpu_to_le32(metric),
537 0, sdata); 557 0, sdata);
538 rcu_read_unlock(); 558 rcu_read_unlock();
559
560 sdata->u.mesh.mshstats.fwded_unicast++;
539 sdata->u.mesh.mshstats.fwded_frames++; 561 sdata->u.mesh.mshstats.fwded_frames++;
540 return; 562 return;
541 563
@@ -660,14 +682,14 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
660 spin_unlock(&ifmsh->mesh_preq_queue_lock); 682 spin_unlock(&ifmsh->mesh_preq_queue_lock);
661 683
662 if (time_after(jiffies, ifmsh->last_preq + min_preq_int_jiff(sdata))) 684 if (time_after(jiffies, ifmsh->last_preq + min_preq_int_jiff(sdata)))
663 queue_work(sdata->local->hw.workqueue, &ifmsh->work); 685 ieee80211_queue_work(&sdata->local->hw, &ifmsh->work);
664 686
665 else if (time_before(jiffies, ifmsh->last_preq)) { 687 else if (time_before(jiffies, ifmsh->last_preq)) {
666 /* avoid long wait if did not send preqs for a long time 688 /* avoid long wait if did not send preqs for a long time
667 * and jiffies wrapped around 689 * and jiffies wrapped around
668 */ 690 */
669 ifmsh->last_preq = jiffies - min_preq_int_jiff(sdata) - 1; 691 ifmsh->last_preq = jiffies - min_preq_int_jiff(sdata) - 1;
670 queue_work(sdata->local->hw.workqueue, &ifmsh->work); 692 ieee80211_queue_work(&sdata->local->hw, &ifmsh->work);
671 } else 693 } else
672 mod_timer(&ifmsh->mesh_path_timer, ifmsh->last_preq + 694 mod_timer(&ifmsh->mesh_path_timer, ifmsh->last_preq +
673 min_preq_int_jiff(sdata)); 695 min_preq_int_jiff(sdata));
@@ -686,11 +708,11 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata)
686 u8 ttl, dst_flags; 708 u8 ttl, dst_flags;
687 u32 lifetime; 709 u32 lifetime;
688 710
689 spin_lock(&ifmsh->mesh_preq_queue_lock); 711 spin_lock_bh(&ifmsh->mesh_preq_queue_lock);
690 if (!ifmsh->preq_queue_len || 712 if (!ifmsh->preq_queue_len ||
691 time_before(jiffies, ifmsh->last_preq + 713 time_before(jiffies, ifmsh->last_preq +
692 min_preq_int_jiff(sdata))) { 714 min_preq_int_jiff(sdata))) {
693 spin_unlock(&ifmsh->mesh_preq_queue_lock); 715 spin_unlock_bh(&ifmsh->mesh_preq_queue_lock);
694 return; 716 return;
695 } 717 }
696 718
@@ -698,7 +720,7 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata)
698 struct mesh_preq_queue, list); 720 struct mesh_preq_queue, list);
699 list_del(&preq_node->list); 721 list_del(&preq_node->list);
700 --ifmsh->preq_queue_len; 722 --ifmsh->preq_queue_len;
701 spin_unlock(&ifmsh->mesh_preq_queue_lock); 723 spin_unlock_bh(&ifmsh->mesh_preq_queue_lock);
702 724
703 rcu_read_lock(); 725 rcu_read_lock();
704 mpath = mesh_path_lookup(preq_node->dst, sdata); 726 mpath = mesh_path_lookup(preq_node->dst, sdata);
@@ -784,7 +806,6 @@ int mesh_nexthop_lookup(struct sk_buff *skb,
784 mesh_path_add(dst_addr, sdata); 806 mesh_path_add(dst_addr, sdata);
785 mpath = mesh_path_lookup(dst_addr, sdata); 807 mpath = mesh_path_lookup(dst_addr, sdata);
786 if (!mpath) { 808 if (!mpath) {
787 dev_kfree_skb(skb);
788 sdata->u.mesh.mshstats.dropped_frames_no_route++; 809 sdata->u.mesh.mshstats.dropped_frames_no_route++;
789 err = -ENOSPC; 810 err = -ENOSPC;
790 goto endlookup; 811 goto endlookup;
@@ -792,7 +813,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb,
792 } 813 }
793 814
794 if (mpath->flags & MESH_PATH_ACTIVE) { 815 if (mpath->flags & MESH_PATH_ACTIVE) {
795 if (time_after(jiffies, mpath->exp_time - 816 if (time_after(jiffies, mpath->exp_time +
796 msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) 817 msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time))
797 && !memcmp(sdata->dev->dev_addr, hdr->addr4, 818 && !memcmp(sdata->dev->dev_addr, hdr->addr4,
798 ETH_ALEN) 819 ETH_ALEN)
@@ -804,17 +825,17 @@ int mesh_nexthop_lookup(struct sk_buff *skb,
804 memcpy(hdr->addr1, mpath->next_hop->sta.addr, 825 memcpy(hdr->addr1, mpath->next_hop->sta.addr,
805 ETH_ALEN); 826 ETH_ALEN);
806 } else { 827 } else {
828 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
807 if (!(mpath->flags & MESH_PATH_RESOLVING)) { 829 if (!(mpath->flags & MESH_PATH_RESOLVING)) {
808 /* Start discovery only if it is not running yet */ 830 /* Start discovery only if it is not running yet */
809 mesh_queue_preq(mpath, PREQ_Q_F_START); 831 mesh_queue_preq(mpath, PREQ_Q_F_START);
810 } 832 }
811 833
812 if (skb_queue_len(&mpath->frame_queue) >= 834 if (skb_queue_len(&mpath->frame_queue) >=
813 MESH_FRAME_QUEUE_LEN) { 835 MESH_FRAME_QUEUE_LEN)
814 skb_to_free = mpath->frame_queue.next; 836 skb_to_free = skb_dequeue(&mpath->frame_queue);
815 skb_unlink(skb_to_free, &mpath->frame_queue);
816 }
817 837
838 info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
818 skb_queue_tail(&mpath->frame_queue, skb); 839 skb_queue_tail(&mpath->frame_queue, skb);
819 if (skb_to_free) 840 if (skb_to_free)
820 mesh_path_discard_frame(skb_to_free, sdata); 841 mesh_path_discard_frame(skb_to_free, sdata);