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.c130
1 files changed, 86 insertions, 44 deletions
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index 3d8e55ae6ab6..fd4f76a3e139 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -11,7 +11,8 @@
11#include "mesh.h" 11#include "mesh.h"
12 12
13#ifdef CONFIG_MAC80211_VERBOSE_MHWMP_DEBUG 13#ifdef CONFIG_MAC80211_VERBOSE_MHWMP_DEBUG
14#define mhwmp_dbg(fmt, args...) printk(KERN_DEBUG "Mesh HWMP: " fmt, ##args) 14#define mhwmp_dbg(fmt, args...) \
15 printk(KERN_DEBUG "Mesh HWMP (%s): " fmt "\n", sdata->name, ##args)
15#else 16#else
16#define mhwmp_dbg(fmt, args...) do { (void)(0); } while (0) 17#define mhwmp_dbg(fmt, args...) do { (void)(0); } while (0)
17#endif 18#endif
@@ -68,12 +69,12 @@ static inline u32 u16_field_get(u8 *preq_elem, int offset, bool ae)
68#define PREP_IE_FLAGS(x) PREQ_IE_FLAGS(x) 69#define PREP_IE_FLAGS(x) PREQ_IE_FLAGS(x)
69#define PREP_IE_HOPCOUNT(x) PREQ_IE_HOPCOUNT(x) 70#define PREP_IE_HOPCOUNT(x) PREQ_IE_HOPCOUNT(x)
70#define PREP_IE_TTL(x) PREQ_IE_TTL(x) 71#define PREP_IE_TTL(x) PREQ_IE_TTL(x)
71#define PREP_IE_ORIG_ADDR(x) (x + 3) 72#define PREP_IE_ORIG_ADDR(x) (AE_F_SET(x) ? x + 27 : x + 21)
72#define PREP_IE_ORIG_SN(x) u32_field_get(x, 9, 0) 73#define PREP_IE_ORIG_SN(x) u32_field_get(x, 27, AE_F_SET(x))
73#define PREP_IE_LIFETIME(x) u32_field_get(x, 13, AE_F_SET(x)) 74#define PREP_IE_LIFETIME(x) u32_field_get(x, 13, AE_F_SET(x))
74#define PREP_IE_METRIC(x) u32_field_get(x, 17, AE_F_SET(x)) 75#define PREP_IE_METRIC(x) u32_field_get(x, 17, AE_F_SET(x))
75#define PREP_IE_TARGET_ADDR(x) (AE_F_SET(x) ? x + 27 : x + 21) 76#define PREP_IE_TARGET_ADDR(x) (x + 3)
76#define PREP_IE_TARGET_SN(x) u32_field_get(x, 27, AE_F_SET(x)) 77#define PREP_IE_TARGET_SN(x) u32_field_get(x, 9, 0)
77 78
78#define PERR_IE_TTL(x) (*(x)) 79#define PERR_IE_TTL(x) (*(x))
79#define PERR_IE_TARGET_FLAGS(x) (*(x + 2)) 80#define PERR_IE_TARGET_FLAGS(x) (*(x + 2))
@@ -132,24 +133,25 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
132 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); 133 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
133 /* BSSID == SA */ 134 /* BSSID == SA */
134 memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); 135 memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
135 mgmt->u.action.category = WLAN_CATEGORY_MESH_PATH_SEL; 136 mgmt->u.action.category = WLAN_CATEGORY_MESH_ACTION;
136 mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION; 137 mgmt->u.action.u.mesh_action.action_code =
138 WLAN_MESH_ACTION_HWMP_PATH_SELECTION;
137 139
138 switch (action) { 140 switch (action) {
139 case MPATH_PREQ: 141 case MPATH_PREQ:
140 mhwmp_dbg("sending PREQ to %pM\n", target); 142 mhwmp_dbg("sending PREQ to %pM", target);
141 ie_len = 37; 143 ie_len = 37;
142 pos = skb_put(skb, 2 + ie_len); 144 pos = skb_put(skb, 2 + ie_len);
143 *pos++ = WLAN_EID_PREQ; 145 *pos++ = WLAN_EID_PREQ;
144 break; 146 break;
145 case MPATH_PREP: 147 case MPATH_PREP:
146 mhwmp_dbg("sending PREP to %pM\n", target); 148 mhwmp_dbg("sending PREP to %pM", target);
147 ie_len = 31; 149 ie_len = 31;
148 pos = skb_put(skb, 2 + ie_len); 150 pos = skb_put(skb, 2 + ie_len);
149 *pos++ = WLAN_EID_PREP; 151 *pos++ = WLAN_EID_PREP;
150 break; 152 break;
151 case MPATH_RANN: 153 case MPATH_RANN:
152 mhwmp_dbg("sending RANN from %pM\n", orig_addr); 154 mhwmp_dbg("sending RANN from %pM", orig_addr);
153 ie_len = sizeof(struct ieee80211_rann_ie); 155 ie_len = sizeof(struct ieee80211_rann_ie);
154 pos = skb_put(skb, 2 + ie_len); 156 pos = skb_put(skb, 2 + ie_len);
155 *pos++ = WLAN_EID_RANN; 157 *pos++ = WLAN_EID_RANN;
@@ -163,29 +165,37 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
163 *pos++ = flags; 165 *pos++ = flags;
164 *pos++ = hop_count; 166 *pos++ = hop_count;
165 *pos++ = ttl; 167 *pos++ = ttl;
166 if (action == MPATH_PREQ) { 168 if (action == MPATH_PREP) {
167 memcpy(pos, &preq_id, 4); 169 memcpy(pos, target, ETH_ALEN);
170 pos += ETH_ALEN;
171 memcpy(pos, &target_sn, 4);
168 pos += 4; 172 pos += 4;
169 } 173 } else {
170 memcpy(pos, orig_addr, ETH_ALEN); 174 if (action == MPATH_PREQ) {
171 pos += ETH_ALEN; 175 memcpy(pos, &preq_id, 4);
172 memcpy(pos, &orig_sn, 4); 176 pos += 4;
173 pos += 4; 177 }
174 if (action != MPATH_RANN) { 178 memcpy(pos, orig_addr, ETH_ALEN);
175 memcpy(pos, &lifetime, 4); 179 pos += ETH_ALEN;
180 memcpy(pos, &orig_sn, 4);
176 pos += 4; 181 pos += 4;
177 } 182 }
183 memcpy(pos, &lifetime, 4); /* interval for RANN */
184 pos += 4;
178 memcpy(pos, &metric, 4); 185 memcpy(pos, &metric, 4);
179 pos += 4; 186 pos += 4;
180 if (action == MPATH_PREQ) { 187 if (action == MPATH_PREQ) {
181 /* destination count */ 188 *pos++ = 1; /* destination count */
182 *pos++ = 1;
183 *pos++ = target_flags; 189 *pos++ = target_flags;
184 }
185 if (action != MPATH_RANN) {
186 memcpy(pos, target, ETH_ALEN); 190 memcpy(pos, target, ETH_ALEN);
187 pos += ETH_ALEN; 191 pos += ETH_ALEN;
188 memcpy(pos, &target_sn, 4); 192 memcpy(pos, &target_sn, 4);
193 pos += 4;
194 } else if (action == MPATH_PREP) {
195 memcpy(pos, orig_addr, ETH_ALEN);
196 pos += ETH_ALEN;
197 memcpy(pos, &orig_sn, 4);
198 pos += 4;
189 } 199 }
190 200
191 ieee80211_tx_skb(sdata, skb); 201 ieee80211_tx_skb(sdata, skb);
@@ -224,9 +234,11 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn,
224 234
225 memcpy(mgmt->da, ra, ETH_ALEN); 235 memcpy(mgmt->da, ra, ETH_ALEN);
226 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); 236 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
227 /* BSSID is left zeroed, wildcard value */ 237 /* BSSID == SA */
228 mgmt->u.action.category = WLAN_CATEGORY_MESH_PATH_SEL; 238 memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
229 mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION; 239 mgmt->u.action.category = WLAN_CATEGORY_MESH_ACTION;
240 mgmt->u.action.u.mesh_action.action_code =
241 WLAN_MESH_ACTION_HWMP_PATH_SELECTION;
230 ie_len = 15; 242 ie_len = 15;
231 pos = skb_put(skb, 2 + ie_len); 243 pos = skb_put(skb, 2 + ie_len);
232 *pos++ = WLAN_EID_PERR; 244 *pos++ = WLAN_EID_PERR;
@@ -483,10 +495,10 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
483 orig_sn = PREQ_IE_ORIG_SN(preq_elem); 495 orig_sn = PREQ_IE_ORIG_SN(preq_elem);
484 target_flags = PREQ_IE_TARGET_F(preq_elem); 496 target_flags = PREQ_IE_TARGET_F(preq_elem);
485 497
486 mhwmp_dbg("received PREQ from %pM\n", orig_addr); 498 mhwmp_dbg("received PREQ from %pM", orig_addr);
487 499
488 if (memcmp(target_addr, sdata->vif.addr, ETH_ALEN) == 0) { 500 if (memcmp(target_addr, sdata->vif.addr, ETH_ALEN) == 0) {
489 mhwmp_dbg("PREQ is for us\n"); 501 mhwmp_dbg("PREQ is for us");
490 forward = false; 502 forward = false;
491 reply = true; 503 reply = true;
492 metric = 0; 504 metric = 0;
@@ -522,7 +534,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
522 lifetime = PREQ_IE_LIFETIME(preq_elem); 534 lifetime = PREQ_IE_LIFETIME(preq_elem);
523 ttl = ifmsh->mshcfg.element_ttl; 535 ttl = ifmsh->mshcfg.element_ttl;
524 if (ttl != 0) { 536 if (ttl != 0) {
525 mhwmp_dbg("replying to the PREQ\n"); 537 mhwmp_dbg("replying to the PREQ");
526 mesh_path_sel_frame_tx(MPATH_PREP, 0, target_addr, 538 mesh_path_sel_frame_tx(MPATH_PREP, 0, target_addr,
527 cpu_to_le32(target_sn), 0, orig_addr, 539 cpu_to_le32(target_sn), 0, orig_addr,
528 cpu_to_le32(orig_sn), mgmt->sa, 0, ttl, 540 cpu_to_le32(orig_sn), mgmt->sa, 0, ttl,
@@ -542,7 +554,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
542 ifmsh->mshstats.dropped_frames_ttl++; 554 ifmsh->mshstats.dropped_frames_ttl++;
543 return; 555 return;
544 } 556 }
545 mhwmp_dbg("forwarding the PREQ from %pM\n", orig_addr); 557 mhwmp_dbg("forwarding the PREQ from %pM", orig_addr);
546 --ttl; 558 --ttl;
547 flags = PREQ_IE_FLAGS(preq_elem); 559 flags = PREQ_IE_FLAGS(preq_elem);
548 preq_id = PREQ_IE_PREQ_ID(preq_elem); 560 preq_id = PREQ_IE_PREQ_ID(preq_elem);
@@ -577,7 +589,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata,
577 u8 next_hop[ETH_ALEN]; 589 u8 next_hop[ETH_ALEN];
578 u32 target_sn, orig_sn, lifetime; 590 u32 target_sn, orig_sn, lifetime;
579 591
580 mhwmp_dbg("received PREP from %pM\n", PREP_IE_ORIG_ADDR(prep_elem)); 592 mhwmp_dbg("received PREP from %pM", PREP_IE_ORIG_ADDR(prep_elem));
581 593
582 /* Note that we divert from the draft nomenclature and denominate 594 /* Note that we divert from the draft nomenclature and denominate
583 * destination to what the draft refers to as origininator. So in this 595 * destination to what the draft refers to as origininator. So in this
@@ -683,6 +695,8 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
683 u8 ttl, flags, hopcount; 695 u8 ttl, flags, hopcount;
684 u8 *orig_addr; 696 u8 *orig_addr;
685 u32 orig_sn, metric; 697 u32 orig_sn, metric;
698 u32 interval = ifmsh->mshcfg.dot11MeshHWMPRannInterval;
699 bool root_is_gate;
686 700
687 ttl = rann->rann_ttl; 701 ttl = rann->rann_ttl;
688 if (ttl <= 1) { 702 if (ttl <= 1) {
@@ -691,12 +705,19 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
691 } 705 }
692 ttl--; 706 ttl--;
693 flags = rann->rann_flags; 707 flags = rann->rann_flags;
708 root_is_gate = !!(flags & RANN_FLAG_IS_GATE);
694 orig_addr = rann->rann_addr; 709 orig_addr = rann->rann_addr;
695 orig_sn = rann->rann_seq; 710 orig_sn = rann->rann_seq;
696 hopcount = rann->rann_hopcount; 711 hopcount = rann->rann_hopcount;
697 hopcount++; 712 hopcount++;
698 metric = rann->rann_metric; 713 metric = rann->rann_metric;
699 mhwmp_dbg("received RANN from %pM\n", orig_addr); 714
715 /* Ignore our own RANNs */
716 if (memcmp(orig_addr, sdata->vif.addr, ETH_ALEN) == 0)
717 return;
718
719 mhwmp_dbg("received RANN from %pM (is_gate=%d)", orig_addr,
720 root_is_gate);
700 721
701 rcu_read_lock(); 722 rcu_read_lock();
702 mpath = mesh_path_lookup(orig_addr, sdata); 723 mpath = mesh_path_lookup(orig_addr, sdata);
@@ -708,18 +729,28 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
708 sdata->u.mesh.mshstats.dropped_frames_no_route++; 729 sdata->u.mesh.mshstats.dropped_frames_no_route++;
709 return; 730 return;
710 } 731 }
711 mesh_queue_preq(mpath,
712 PREQ_Q_F_START | PREQ_Q_F_REFRESH);
713 } 732 }
733
734 if ((!(mpath->flags & (MESH_PATH_ACTIVE | MESH_PATH_RESOLVING)) ||
735 time_after(jiffies, mpath->exp_time - 1*HZ)) &&
736 !(mpath->flags & MESH_PATH_FIXED)) {
737 mhwmp_dbg("%s time to refresh root mpath %pM", sdata->name,
738 orig_addr);
739 mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH);
740 }
741
714 if (mpath->sn < orig_sn) { 742 if (mpath->sn < orig_sn) {
715 mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr, 743 mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr,
716 cpu_to_le32(orig_sn), 744 cpu_to_le32(orig_sn),
717 0, NULL, 0, broadcast_addr, 745 0, NULL, 0, broadcast_addr,
718 hopcount, ttl, 0, 746 hopcount, ttl, cpu_to_le32(interval),
719 cpu_to_le32(metric + mpath->metric), 747 cpu_to_le32(metric + mpath->metric),
720 0, sdata); 748 0, sdata);
721 mpath->sn = orig_sn; 749 mpath->sn = orig_sn;
722 } 750 }
751 if (root_is_gate)
752 mesh_path_add_gate(mpath);
753
723 rcu_read_unlock(); 754 rcu_read_unlock();
724} 755}
725 756
@@ -787,7 +818,7 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
787 818
788 preq_node = kmalloc(sizeof(struct mesh_preq_queue), GFP_ATOMIC); 819 preq_node = kmalloc(sizeof(struct mesh_preq_queue), GFP_ATOMIC);
789 if (!preq_node) { 820 if (!preq_node) {
790 mhwmp_dbg("could not allocate PREQ node\n"); 821 mhwmp_dbg("could not allocate PREQ node");
791 return; 822 return;
792 } 823 }
793 824
@@ -796,7 +827,7 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
796 spin_unlock_bh(&ifmsh->mesh_preq_queue_lock); 827 spin_unlock_bh(&ifmsh->mesh_preq_queue_lock);
797 kfree(preq_node); 828 kfree(preq_node);
798 if (printk_ratelimit()) 829 if (printk_ratelimit())
799 mhwmp_dbg("PREQ node queue full\n"); 830 mhwmp_dbg("PREQ node queue full");
800 return; 831 return;
801 } 832 }
802 833
@@ -981,35 +1012,46 @@ void mesh_path_timer(unsigned long data)
981{ 1012{
982 struct mesh_path *mpath = (void *) data; 1013 struct mesh_path *mpath = (void *) data;
983 struct ieee80211_sub_if_data *sdata = mpath->sdata; 1014 struct ieee80211_sub_if_data *sdata = mpath->sdata;
1015 int ret;
984 1016
985 if (sdata->local->quiescing) 1017 if (sdata->local->quiescing)
986 return; 1018 return;
987 1019
988 spin_lock_bh(&mpath->state_lock); 1020 spin_lock_bh(&mpath->state_lock);
989 if (mpath->flags & MESH_PATH_RESOLVED || 1021 if (mpath->flags & MESH_PATH_RESOLVED ||
990 (!(mpath->flags & MESH_PATH_RESOLVING))) 1022 (!(mpath->flags & MESH_PATH_RESOLVING))) {
991 mpath->flags &= ~(MESH_PATH_RESOLVING | MESH_PATH_RESOLVED); 1023 mpath->flags &= ~(MESH_PATH_RESOLVING | MESH_PATH_RESOLVED);
992 else if (mpath->discovery_retries < max_preq_retries(sdata)) { 1024 spin_unlock_bh(&mpath->state_lock);
1025 } else if (mpath->discovery_retries < max_preq_retries(sdata)) {
993 ++mpath->discovery_retries; 1026 ++mpath->discovery_retries;
994 mpath->discovery_timeout *= 2; 1027 mpath->discovery_timeout *= 2;
1028 spin_unlock_bh(&mpath->state_lock);
995 mesh_queue_preq(mpath, 0); 1029 mesh_queue_preq(mpath, 0);
996 } else { 1030 } else {
997 mpath->flags = 0; 1031 mpath->flags = 0;
998 mpath->exp_time = jiffies; 1032 mpath->exp_time = jiffies;
999 mesh_path_flush_pending(mpath); 1033 spin_unlock_bh(&mpath->state_lock);
1034 if (!mpath->is_gate && mesh_gate_num(sdata) > 0) {
1035 ret = mesh_path_send_to_gates(mpath);
1036 if (ret)
1037 mhwmp_dbg("no gate was reachable");
1038 } else
1039 mesh_path_flush_pending(mpath);
1000 } 1040 }
1001
1002 spin_unlock_bh(&mpath->state_lock);
1003} 1041}
1004 1042
1005void 1043void
1006mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata) 1044mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata)
1007{ 1045{
1008 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; 1046 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
1047 u32 interval = ifmsh->mshcfg.dot11MeshHWMPRannInterval;
1048 u8 flags;
1009 1049
1010 mesh_path_sel_frame_tx(MPATH_RANN, 0, sdata->vif.addr, 1050 flags = (ifmsh->mshcfg.dot11MeshGateAnnouncementProtocol)
1051 ? RANN_FLAG_IS_GATE : 0;
1052 mesh_path_sel_frame_tx(MPATH_RANN, flags, sdata->vif.addr,
1011 cpu_to_le32(++ifmsh->sn), 1053 cpu_to_le32(++ifmsh->sn),
1012 0, NULL, 0, broadcast_addr, 1054 0, NULL, 0, broadcast_addr,
1013 0, sdata->u.mesh.mshcfg.element_ttl, 1055 0, sdata->u.mesh.mshcfg.element_ttl,
1014 0, 0, 0, sdata); 1056 cpu_to_le32(interval), 0, 0, sdata);
1015} 1057}