P2P: Do not perform P2P GO CS in some cases
authorIlan Peer <ilan.peer@intel.com>
Mon, 27 Jul 2015 19:24:27 +0000 (22:24 +0300)
committerJouni Malinen <j@w1.fi>
Tue, 4 Aug 2015 15:34:47 +0000 (18:34 +0300)
A P2P GO channel switch should not be triggered in all cases that
require channel list update. Specifically, a P2P GO CS should not
be triggered in case that the P2P GO state changed or in case that
that the P2P GO has just completed a CS.

To fix this, add reason code to wpas_p2p_channel_list_update() and
trigger CS flow only for the relevant cases.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
wpa_supplicant/ctrl_iface.c
wpa_supplicant/events.c
wpa_supplicant/p2p_supplicant.c
wpa_supplicant/p2p_supplicant.h

index 3f533ce..e802489 100644 (file)
@@ -5761,7 +5761,7 @@ static int p2p_ctrl_disallow_freq(struct wpa_supplicant *wpa_s,
                           freq->min, freq->max);
        }
 
-       wpas_p2p_update_channel_list(wpa_s);
+       wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_DISALLOW);
        return 0;
 }
 
index 8b46810..829cd3f 100644 (file)
@@ -3015,7 +3015,7 @@ static void wpa_supplicant_update_channel_list(
                wpa_supplicant_req_scan(wpa_s, 0, 0);
        }
 
-       wpas_p2p_update_channel_list(wpa_s);
+       wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_DRIVER);
 }
 
 
@@ -3154,7 +3154,8 @@ static void wpa_supplicant_notify_avoid_freq(struct wpa_supplicant *wpa_s,
                 * The update channel flow will also take care of moving a GO
                 * from the unsafe frequency if needed.
                 */
-               wpas_p2p_update_channel_list(wpa_s);
+               wpas_p2p_update_channel_list(wpa_s,
+                                            WPAS_P2P_CHANNEL_UPDATE_AVOID);
        }
 #endif /* CONFIG_P2P */
 
index 0ac7690..e849b91 100644 (file)
@@ -146,9 +146,10 @@ static void wpas_p2p_optimize_listen_channel(struct wpa_supplicant *wpa_s,
                                             unsigned int num);
 static void wpas_p2p_move_go(void *eloop_ctx, void *timeout_ctx);
 static int wpas_p2p_go_is_peer_freq(struct wpa_supplicant *wpa_s, int freq);
-static void wpas_p2p_consider_moving_gos(struct wpa_supplicant *wpa_s,
-                                        struct wpa_used_freq_data *freqs,
-                                        unsigned int num);
+static void
+wpas_p2p_consider_moving_gos(struct wpa_supplicant *wpa_s,
+                            struct wpa_used_freq_data *freqs, unsigned int num,
+                            enum wpas_p2p_channel_update_trig trig);
 static void wpas_p2p_reconsider_moving_go(void *eloop_ctx, void *timeout_ctx);
 
 
@@ -7076,7 +7077,8 @@ void wpas_p2p_pbc_overlap_cb(void *eloop_ctx, void *timeout_ctx)
 }
 
 
-void wpas_p2p_update_channel_list(struct wpa_supplicant *wpa_s)
+void wpas_p2p_update_channel_list(struct wpa_supplicant *wpa_s,
+                                 enum wpas_p2p_channel_update_trig trig)
 {
        struct p2p_channels chan, cli_chan;
        struct wpa_used_freq_data *freqs = NULL;
@@ -7109,7 +7111,7 @@ void wpas_p2p_update_channel_list(struct wpa_supplicant *wpa_s)
         * possible that due to policy consideration, it would be preferable to
         * move it to a frequency already used by other station interfaces.
         */
-       wpas_p2p_consider_moving_gos(wpa_s, freqs, num);
+       wpas_p2p_consider_moving_gos(wpa_s, freqs, num, trig);
 
        os_free(freqs);
 }
@@ -8490,7 +8492,8 @@ static void wpas_p2p_reconsider_moving_go(void *eloop_ctx, void *timeout_ctx)
        num = get_shared_radio_freqs_data(wpa_s, freqs, num);
 
        /* Previous attempt to move a GO was not possible -- try again. */
-       wpas_p2p_consider_moving_gos(wpa_s, freqs, num);
+       wpas_p2p_consider_moving_gos(wpa_s, freqs, num,
+                                    WPAS_P2P_CHANNEL_UPDATE_ANY);
 
        os_free(freqs);
 }
@@ -8591,7 +8594,8 @@ static void wpas_p2p_consider_moving_one_go(struct wpa_supplicant *wpa_s,
 
 static void wpas_p2p_consider_moving_gos(struct wpa_supplicant *wpa_s,
                                         struct wpa_used_freq_data *freqs,
-                                        unsigned int num)
+                                        unsigned int num,
+                                        enum wpas_p2p_channel_update_trig trig)
 {
        struct wpa_supplicant *ifs;
 
@@ -8609,6 +8613,21 @@ static void wpas_p2p_consider_moving_gos(struct wpa_supplicant *wpa_s,
                    ifs->current_ssid->mode != WPAS_MODE_P2P_GO)
                        continue;
 
+               /*
+                * The GO was just started or completed channel switch, no need
+                * to move it.
+                */
+               if (wpa_s == ifs &&
+                   (trig == WPAS_P2P_CHANNEL_UPDATE_STATE_CHANGE ||
+                    trig == WPAS_P2P_CHANNEL_UPDATE_CS)) {
+                       wpa_dbg(wpa_s, MSG_DEBUG,
+                               "P2P: GO move - schedule re-consideration");
+                       eloop_register_timeout(P2P_RECONSIDER_GO_MOVE_DELAY, 0,
+                                              wpas_p2p_reconsider_moving_go,
+                                              wpa_s, NULL);
+                       continue;
+               }
+
                wpas_p2p_consider_moving_one_go(ifs, freqs, num);
        }
 }
@@ -8619,7 +8638,8 @@ void wpas_p2p_indicate_state_change(struct wpa_supplicant *wpa_s)
        if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
                return;
 
-       wpas_p2p_update_channel_list(wpa_s);
+       wpas_p2p_update_channel_list(wpa_s,
+                                    WPAS_P2P_CHANNEL_UPDATE_STATE_CHANGE);
 }
 
 
index b02f924..f622c28 100644 (file)
@@ -17,6 +17,15 @@ struct p2p_channels;
 struct wps_event_fail;
 struct p2ps_provision;
 
+enum wpas_p2p_channel_update_trig {
+       WPAS_P2P_CHANNEL_UPDATE_ANY,
+       WPAS_P2P_CHANNEL_UPDATE_DRIVER,
+       WPAS_P2P_CHANNEL_UPDATE_STATE_CHANGE,
+       WPAS_P2P_CHANNEL_UPDATE_AVOID,
+       WPAS_P2P_CHANNEL_UPDATE_DISALLOW,
+       WPAS_P2P_CHANNEL_UPDATE_CS,
+};
+
 int wpas_p2p_add_p2pdev_interface(struct wpa_supplicant *wpa_s,
                                  const char *conf_p2p_dev);
 struct wpa_supplicant * wpas_get_p2p_go_iface(struct wpa_supplicant *wpa_s,
@@ -161,7 +170,10 @@ int wpas_p2p_probe_req_rx(struct wpa_supplicant *wpa_s, const u8 *addr,
                          unsigned int rx_freq, int ssi_signal);
 void wpas_p2p_wps_success(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
                          int registrar);
-void wpas_p2p_update_channel_list(struct wpa_supplicant *wpa_s);
+
+void wpas_p2p_update_channel_list(struct wpa_supplicant *wpa_s,
+                                 enum wpas_p2p_channel_update_trig trig);
+
 void wpas_p2p_update_best_channels(struct wpa_supplicant *wpa_s,
                                   int freq_24, int freq_5, int freq_overall);
 void wpas_p2p_rx_action(struct wpa_supplicant *wpa_s, const u8 *da,
@@ -222,7 +234,9 @@ static inline void wpas_p2p_wps_success(struct wpa_supplicant *wpa_s,
 {
 }
 
-static inline void wpas_p2p_update_channel_list(struct wpa_supplicant *wpa_s)
+static inline void
+wpas_p2p_update_channel_list(struct wpa_supplicant *wpa_s,
+                            enum wpas_p2p_channel_update_trig trig)
 {
 }