diff options
Diffstat (limited to 'net/mac80211/mesh_hwmp.c')
-rw-r--r-- | net/mac80211/mesh_hwmp.c | 47 |
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 | ||
204 | void 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 | |||
204 | static u32 airtime_link_metric_get(struct ieee80211_local *local, | 222 | static 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 | ||
398 | static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, | 416 | static 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); |