P2P: Fix shared frequency preference for concurrent operations
authorJouni Malinen <jouni@qca.qualcomm.com>
Thu, 14 Mar 2013 14:22:31 +0000 (16:22 +0200)
committerJouni Malinen <j@w1.fi>
Thu, 14 Mar 2013 14:26:55 +0000 (16:26 +0200)
Commit 50285f5ca8086cca45afa42cd23c3a3c1cd58f40 changed number of rules
in channel selection and among other things, it broke the design where
the currently used operating channel on a virtual interface that is
shared by the same radio is preferred to avoid costs related to
multi-channel concurrency. Fix this regression by making the P2P module
aware of the shared channel and using that preference as the highest
priority when re-selecting the channel during negotiation.

Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>

src/p2p/p2p.c
src/p2p/p2p.h
src/p2p/p2p_go_neg.c
src/p2p/p2p_i.h
wpa_supplicant/p2p_supplicant.c

index 1dbdf6d..d38e9c5 100644 (file)
@@ -4202,6 +4202,14 @@ void p2p_set_best_channels(struct p2p_data *p2p, int freq_24, int freq_5,
 }
 
 
+void p2p_set_own_freq_preference(struct p2p_data *p2p, int freq)
+{
+       wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Own frequency preference: "
+               "%d MHz", freq);
+       p2p->own_freq_preference = freq;
+}
+
+
 const u8 * p2p_get_go_neg_peer(struct p2p_data *p2p)
 {
        if (p2p == NULL || p2p->go_neg_peer == NULL)
index ae96b6e..eb57a3a 100644 (file)
@@ -1641,6 +1641,17 @@ void p2p_update_channel_list(struct p2p_data *p2p, struct p2p_channels *chan);
 void p2p_set_best_channels(struct p2p_data *p2p, int freq_24, int freq_5,
                           int freq_overall);
 
+/**
+ * p2p_set_own_freq_preference - Set own preference for channel
+ * @p2p: P2P module context from p2p_init()
+ * @freq: Frequency (MHz) of the preferred channel or 0 if no preference
+ *
+ * This function can be used to set a preference on the operating channel based
+ * on frequencies used on the other virtual interfaces that share the same
+ * radio. If non-zero, this is used to try to avoid multi-channel concurrency.
+ */
+void p2p_set_own_freq_preference(struct p2p_data *p2p, int freq);
+
 const u8 * p2p_get_go_neg_peer(struct p2p_data *p2p);
 
 /**
index 8a86c54..805bf69 100644 (file)
@@ -350,6 +350,18 @@ void p2p_reselect_channel(struct p2p_data *p2p,
        u8 op_reg_class, op_channel;
        unsigned int i;
 
+       if (p2p->own_freq_preference > 0 &&
+           p2p_freq_to_channel(p2p->cfg->country, p2p->own_freq_preference,
+                               &op_reg_class, &op_channel) == 0 &&
+           p2p_channels_includes(intersection, op_reg_class, op_channel)) {
+               wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Pick own channel "
+                       "preference (reg_class %u channel %u) from "
+                       "intersection", op_reg_class, op_channel);
+               p2p->op_reg_class = op_reg_class;
+               p2p->op_channel = op_channel;
+               return;
+       }
+
        if (p2p->best_freq_overall > 0 &&
            p2p_freq_to_channel(p2p->cfg->country, p2p->best_freq_overall,
                                &op_reg_class, &op_channel) == 0 &&
index c753d49..dff226a 100644 (file)
@@ -417,6 +417,7 @@ struct p2p_data {
        int best_freq_24;
        int best_freq_5;
        int best_freq_overall;
+       int own_freq_preference;
 
        /**
         * wps_vendor_ext - WPS Vendor Extensions to add
index e016f82..3a06406 100644 (file)
@@ -93,6 +93,15 @@ static void wpas_p2p_fallback_to_go_neg(struct wpa_supplicant *wpa_s,
 static int wpas_p2p_stop_find_oper(struct wpa_supplicant *wpa_s);
 
 
+static void wpas_p2p_set_own_freq_preference(struct wpa_supplicant *wpa_s,
+                                            int freq)
+{
+       if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
+               return;
+       p2p_set_own_freq_preference(wpa_s->global->p2p, freq);
+}
+
+
 static void wpas_p2p_scan_res_handler(struct wpa_supplicant *wpa_s,
                                      struct wpa_scan_results *scan_res)
 {
@@ -2410,11 +2419,14 @@ static u8 wpas_invitation_process(void *ctx, const u8 *sa, const u8 *bssid,
        }
 
 accept_inv:
+       wpas_p2p_set_own_freq_preference(wpa_s, 0);
+
        if (wpa_s->current_ssid && wpa_drv_get_bssid(wpa_s, cur_bssid) == 0 &&
            wpa_s->assoc_freq) {
                wpa_printf(MSG_DEBUG, "P2P: Trying to force channel to match "
                           "the channel we are already using");
                *force_freq = wpa_s->assoc_freq;
+               wpas_p2p_set_own_freq_preference(wpa_s, wpa_s->assoc_freq);
        }
 
        res = wpa_drv_shared_freq(wpa_s);
@@ -2423,6 +2435,7 @@ accept_inv:
                           "with the channel we are already using on a "
                           "shared interface");
                *force_freq = res;
+               wpas_p2p_set_own_freq_preference(wpa_s, res);
        }
 
        return P2P_SC_SUCCESS;
@@ -3736,6 +3749,7 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
                                   &oper_freq);
        if (res)
                return res;
+       wpas_p2p_set_own_freq_preference(wpa_s, oper_freq);
 
        wpa_s->create_p2p_iface = wpas_p2p_create_iface(wpa_s);
 
@@ -4807,6 +4821,7 @@ int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname,
                                   &oper_freq);
        if (res)
                return res;
+       wpas_p2p_set_own_freq_preference(wpa_s, oper_freq);
 
        return p2p_invite(wpa_s->global->p2p, peer_addr, role, bssid,
                          ssid->ssid, ssid->ssid_len, force_freq,