Re: [PATCH] bgscan: Add centralized signal_monitor

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



We are abandoning these changes as it's hard to assess the value of
factoring noise floor measurements into a background scan initiation
decision. Please drop this patch from consideration.

On Tue, Apr 9, 2019 at 4:56 PM <npoojary@xxxxxxxxxxxx> wrote:
>
> From: Neeraj Poojary <npoojary@xxxxxxxxxxxx>
>
> The signal strength number tells only half of the picture with
> respect to signal quality.  The other half is the prevailing
> noise on the channel.  The two together indicate how easily the
> interface is able to pull data out of the background noise.
>
> This change takes noise into account, by calculating a CQM
> threshold based both on the RSSI and noise.  This noise value is
> available in the CQM events as well as polled data.  Since most
> background scan algorithms will probably want to do this the same
> way, I have added this as routines in bgscan.c that can be
> utilized by individual background scan mechanisms.
>
> Additionally, I've modified bgscan_simple to use this mechanism,
> and scheduled noisefloor updates to happen at the same rate as
> background scans (the noisefloor should be a slowly changing
> parameter).
>
> This patch also includes changes to the background scan procedure
> to make background scans low priority and resume aborted scans from
> frequencies that haven't been scanned yet.
>
> Signed-off-by: Neeraj Poojary <npoojary@xxxxxxxxxxxx>
> ---
>  src/drivers/driver.h           |   2 +
>  wpa_supplicant/bgscan.c        |  85 ++++++++++++
>  wpa_supplicant/bgscan_i.h      |  66 ++++++++++
>  wpa_supplicant/bgscan_simple.c | 227 +++++++++++++++++++++++++++++----
>  wpa_supplicant/scan.c          |   1 +
>  5 files changed, 355 insertions(+), 26 deletions(-)
>  create mode 100644 wpa_supplicant/bgscan_i.h
>
> diff --git a/src/drivers/driver.h b/src/drivers/driver.h
> index 4ac9f16a0..b4ac6dbdd 100644
> --- a/src/drivers/driver.h
> +++ b/src/drivers/driver.h
> @@ -314,11 +314,13 @@ struct wpa_scan_res {
>   * @res: Array of pointers to allocated variable length scan result entries
>   * @num: Number of entries in the scan result array
>   * @fetch_time: Time when the results were fetched from the driver
> + * @aborted: Whether the scan was aborted
>   */
>  struct wpa_scan_results {
>         struct wpa_scan_res **res;
>         size_t num;
>         struct os_reltime fetch_time;
> +       int aborted;
>  };
>
>  /**
> diff --git a/wpa_supplicant/bgscan.c b/wpa_supplicant/bgscan.c
> index 1ea640114..544f62512 100644
> --- a/wpa_supplicant/bgscan.c
> +++ b/wpa_supplicant/bgscan.c
> @@ -9,9 +9,12 @@
>  #include "includes.h"
>
>  #include "common.h"
> +#include "eloop.h"
>  #include "wpa_supplicant_i.h"
>  #include "config_ssid.h"
> +#include "driver_i.h"
>  #include "bgscan.h"
> +#include "bgscan_i.h"
>
>
>  static const struct bgscan_ops * bgscan_modules[] = {
> @@ -107,3 +110,85 @@ void bgscan_notify_signal_change(struct wpa_supplicant *wpa_s, int above,
>                                                     current_noise,
>                                                     current_txrate);
>  }
> +
> +static void bgscan_apply_signal_monitor(void *eloop_ctx, void *timeout_ctx)
> +{
> +       struct bgscan_signal_monitor_state *sm_state = eloop_ctx;
> +
> +       wpa_drv_signal_monitor(sm_state->wpa_s, sm_state->calc_threshold,
> +                              sm_state->hysteresis);
> +}
> +
> +
> +void bgscan_update_signal_monitor(struct bgscan_signal_monitor_state *sm_state,
> +                                int current_signal, int current_noise)
> +{
> +       int threshold = current_noise + sm_state->headroom;
> +
> +       if (current_noise >= 0)
> +               return;
> +
> +       if (threshold >= sm_state->calc_threshold -
> +           BGSCAN_NOISEFLOOR_TOLERANCE &&
> +           threshold <= sm_state->calc_threshold +
> +           BGSCAN_NOISEFLOOR_TOLERANCE)
> +               return;
> +
> +       wpa_printf(MSG_DEBUG, "%s: noisefloor update: %d -> %d",
> +                  __func__, sm_state->calc_threshold - sm_state->headroom,
> +                  current_noise);
> +
> +       sm_state->calc_threshold = threshold;
> +
> +       /*
> +        * Schedule a noisefloor adjustment.  Do this as a timeout callback,
> +        * so it is implicitly throttled.
> +        */
> +       eloop_cancel_timeout(bgscan_apply_signal_monitor, sm_state, NULL);
> +       eloop_register_timeout(BGSCAN_NOISEFLOOR_UPDATE_DELAY, 0,
> +                              bgscan_apply_signal_monitor, sm_state, NULL);
> +}
> +
> +int bgscan_poll_signal_monitor(struct bgscan_signal_monitor_state *sm_state,
> +                              struct wpa_signal_info *siginfo_ret)
> +{
> +       struct wpa_signal_info siginfo;
> +       int ret;
> +
> +       ret = wpa_drv_signal_poll(sm_state->wpa_s, &siginfo);
> +       if (ret != 0)
> +               return ret;
> +
> +       wpa_printf(MSG_DEBUG, "%s: bgscan poll noisefloor: %d ",
> +                  __func__, siginfo.current_noise);
> +
> +       bgscan_update_signal_monitor(sm_state, siginfo.current_signal,
> +                                    siginfo.current_noise);
> +
> +       if (siginfo_ret != 0)
> +               memcpy(siginfo_ret, &siginfo, sizeof(siginfo));
> +
> +       return 0;
> +}
> +
> +void bgscan_init_signal_monitor(struct bgscan_signal_monitor_state *sm_state,
> +                               struct wpa_supplicant *wpa_s,
> +                               int signal_threshold,
> +                               int hysteresis) {
> +
> +       sm_state->wpa_s = wpa_s;
> +       sm_state->calc_threshold = signal_threshold;
> +       sm_state->hysteresis = hysteresis;
> +       sm_state->headroom = signal_threshold - BGSCAN_DEFAULT_NOISE_FLOOR;
> +
> +       if (wpa_drv_signal_monitor(wpa_s, signal_threshold, hysteresis) < 0)
> +               wpa_printf(MSG_ERROR, "bgscan simple: Failed to enable "
> +                          "signal strength monitoring");
> +}
> +
> +void bgscan_deinit_signal_monitor(struct bgscan_signal_monitor_state *sm_state)
> +{
> +       wpa_drv_signal_monitor(sm_state->wpa_s, 0, 0);
> +       eloop_cancel_timeout(bgscan_apply_signal_monitor, sm_state, NULL);
> +}
> +
> diff --git a/wpa_supplicant/bgscan_i.h b/wpa_supplicant/bgscan_i.h
> new file mode 100644
> index 000000000..42b14df20
> --- /dev/null
> +++ b/wpa_supplicant/bgscan_i.h
> @@ -0,0 +1,66 @@
> +/*
> + * WPA Supplicant - background scan and roaming interface
> + * Copyright (c) 2009-2010, Jouni Malinen <j@xxxxx>
> + *
> + * This software may be distributed under the terms of the BSD license.
> + * See README for more details.
> + */
> +
> +#ifndef BGSCAN_I_H
> +#define BGSCAN_I_H
> +
> +/*
> + * The signal monitoring code is an optional facility for bgscan algorithms
> + * that want to track both signal strength and noise floor (e.g. so they can
> + * make decisions based on received signal strength relative to noise floor).
> + *
> + * calc_threshold: Signal strength threshold for generating CQM events.
> + *     When signal strength passes above or below this value CQM events
> + *     are generated.  rssi_threshold is initialized from user-specified
> + *     options to the algorithm and then recalculated based on the current
> + *     noise floor.
> + * headroom: The the threshold for signal above the noisefloor for
> + *     generating CQM events.  headroom is calculated at initialization
> + *     from the user-specified signal strength and then used to calculate
> + *     calc_threshold using the current noise floor.
> + * hysteresis: Hysterisis value passed into the driver CQM to indicate
> + *     how large a delta in received signal (in dBm) from the last CQM
> + *     event should trigger another CQM event.
> + */
> +struct bgscan_signal_monitor_state {
> +       struct wpa_supplicant *wpa_s;
> +       int calc_threshold;
> +       int headroom;
> +       int hysteresis;
> +};
> +
> +void bgscan_init_signal_monitor(struct bgscan_signal_monitor_state *sm_state,
> +                               struct wpa_supplicant *wpa_s,
> +                               int signal_threshold,
> +                               int hysteresis);
> +void bgscan_deinit_signal_monitor(struct bgscan_signal_monitor_state *sm_state);
> +void bgscan_update_signal_monitor(struct bgscan_signal_monitor_state *sm_state,
> +                                 int current_signal, int current_noise);
> +int bgscan_poll_signal_monitor(struct bgscan_signal_monitor_state *sm_state,
> +                              struct wpa_signal_info *siginfo_ret);
> +
> +
> +/*
> + * The time (secs) to delay updates to the CQM monitoring parameters.  This is
> + * done to collapse rapid changes into a single request.
> + */
> +#define BGSCAN_NOISEFLOOR_UPDATE_DELAY 10
> +
> +/*
> + * The starting/default noise floor for the channel (dBm).  This also
> + * serves as the reference noise floor for user-specified signal strength
> + * values in bgscan algorithms that use these facilities.
> + */
> +#define BGSCAN_DEFAULT_NOISE_FLOOR -95
> +
> +/*
> + * Range [+/-] for determining if the noise floor has changed enough for
> + * us to adjust the RSSI threshold.
> + */
> +#define BGSCAN_NOISEFLOOR_TOLERANCE 1
> +#endif /* BGSCAN_I_H */
> diff --git a/wpa_supplicant/bgscan_simple.c b/wpa_supplicant/bgscan_simple.c
> index 41a26df0d..ae7927aba 100644
> --- a/wpa_supplicant/bgscan_simple.c
> +++ b/wpa_supplicant/bgscan_simple.c
> @@ -16,6 +16,7 @@
>  #include "driver_i.h"
>  #include "scan.h"
>  #include "bgscan.h"
> +#include "bgscan_i.h"
>
>  struct bgscan_simple_data {
>         struct wpa_supplicant *wpa_s;
> @@ -27,9 +28,56 @@ struct bgscan_simple_data {
>         int short_interval; /* use if signal < threshold */
>         int long_interval; /* use if signal > threshold */
>         struct os_reltime last_bgscan;
> +       int *supp_freqs;
> +       int n_supp_freqs;
> +       int *scan_freqs;
> +       int freq_idx;
> +       struct bgscan_signal_monitor_state signal_monitor;
>  };
>
>
> +static int * bgscan_simple_get_freqs(struct bgscan_simple_data *data)
> +{
> +       int *freqs = data->scan_freqs;
> +       int i, j;
> +
> +       if (data->supp_freqs == NULL)
> +               return NULL;
> +
> +       if (freqs == NULL)
> +               return NULL;
> +
> +       j = 0;
> +       for (i = data->freq_idx; i < data->n_supp_freqs; i++)
> +               freqs[j++] = data->supp_freqs[i];
> +       for (i = 0; i < data->freq_idx; i++)
> +               freqs[j++] = data->supp_freqs[i];
> +       freqs[j] = 0;           /* NB: terminator expected elsewhere */
> +
> +       return freqs;
> +}
> +
> +
> +#define BGSCAN_FREQ_LIST_MAX_STRLEN 1000
> +static void log_freqs(const char *tag, const int freqs[])
> +{
> +       char msg[BGSCAN_FREQ_LIST_MAX_STRLEN];
> +       int i, pos;
> +
> +       msg[0] = '\0';
> +       for (i = 0, pos = 0; freqs[i] != 0 && pos < BGSCAN_FREQ_LIST_MAX_STRLEN; i++) {
> +               int ret;
> +               ret = os_snprintf(&msg[pos], BGSCAN_FREQ_LIST_MAX_STRLEN - pos, " %d",
> +                                 freqs[i]);
> +               if (ret < 0 || ret >= BGSCAN_FREQ_LIST_MAX_STRLEN - pos)
> +                       break;
> +               pos += ret;
> +       }
> +       msg[pos] = '\0';
> +       wpa_printf(MSG_DEBUG, "bgscan simple: %s frequencies:%s", tag, msg);
> +}
> +
> +
>  static void bgscan_simple_timeout(void *eloop_ctx, void *timeout_ctx)
>  {
>         struct bgscan_simple_data *data = eloop_ctx;
> @@ -40,19 +88,26 @@ static void bgscan_simple_timeout(void *eloop_ctx, void *timeout_ctx)
>         params.num_ssids = 1;
>         params.ssids[0].ssid = data->ssid->ssid;
>         params.ssids[0].ssid_len = data->ssid->ssid_len;
> -       params.freqs = data->ssid->scan_freq;
>
> -       /*
> -        * A more advanced bgscan module would learn about most like channels
> -        * over time and request scans only for some channels (probing others
> -        * every now and then) to reduce effect on the data connection.
> -        */
> +       if (data->ssid->scan_freq == NULL)
> +               params.freqs = bgscan_simple_get_freqs(data);
> +       else
> +               params.freqs = data->ssid->scan_freq;
>
> -       wpa_printf(MSG_DEBUG, "bgscan simple: Request a background scan");
> +       params.low_priority = 1;
> +
> +       wpa_printf(MSG_DEBUG, "bgscan simple: Request a background scan "
> +                  "with reason %s",
> +                  timeout_ctx ? (char *)timeout_ctx : "None");
> +       if (params.freqs != NULL)
> +               log_freqs("Scanning", params.freqs);
>         if (wpa_supplicant_trigger_scan(wpa_s, &params)) {
>                 wpa_printf(MSG_DEBUG, "bgscan simple: Failed to trigger scan");
> +               eloop_cancel_timeout(bgscan_simple_timeout, data,
> +                                    ELOOP_ALL_CTX);
>                 eloop_register_timeout(data->scan_interval, 0,
> -                                      bgscan_simple_timeout, data, NULL);
> +                                      bgscan_simple_timeout, data,
> +                                      "failed-scan");
>         } else {
>                 if (data->scan_interval == data->short_interval) {
>                         data->short_scan_count++;
> @@ -100,6 +155,70 @@ static int bgscan_simple_get_params(struct bgscan_simple_data *data,
>  }
>
>
> +static int in_array(const int *array, int v, int arraylen)
> +{
> +       int i;
> +
> +       if (array == NULL)
> +               return 0;
> +
> +       for (i = 0; i < arraylen; i++)
> +               if (array[i] == v)
> +                       return 1;
> +       return 0;
> +}
> +
> +
> +static void bgscan_simple_setup_freqs(struct wpa_supplicant *wpa_s,
> +                                     struct bgscan_simple_data *data)
> +{
> +       struct hostapd_hw_modes *modes;
> +       const struct hostapd_hw_modes *infra;
> +       u16 num_modes, flags;
> +       int i, j, *freqs;
> +       size_t count;
> +       u8 dfs_domain;
> +
> +       data->supp_freqs = NULL;
> +       data->freq_idx = 0;
> +
> +       modes = wpa_drv_get_hw_feature_data(wpa_s, &num_modes, &flags, &dfs_domain);
> +       if (!modes)
> +               return;
> +
> +       count = 0;
> +       freqs = NULL;
> +       for (i = 0; i < num_modes; i++) {
> +               for (j = 0; j < modes[i].num_channels; j++) {
> +                       int freq, *n;
> +
> +                       if (modes[i].channels[j].flag & HOSTAPD_CHAN_DISABLED)
> +                               continue;
> +                       freq = modes[i].channels[j].freq;
> +                       if (in_array(freqs, freq, count))       /* NB: de-dup list */
> +                               continue;
> +                       n = os_realloc(freqs, (count + 2) * sizeof(int));
> +                       if (n != NULL) {
> +                               freqs = n;
> +                               freqs[count++] = freq;
> +                               freqs[count] = 0;
> +                       }
> +               }
> +               os_free(modes[i].channels);
> +               os_free(modes[i].rates);
> +       }
> +       os_free(modes);
> +
> +       if (freqs != NULL) {
> +               data->supp_freqs = freqs;
> +               data->n_supp_freqs = count;
> +               data->scan_freqs = os_malloc((count + 1) * sizeof(int));
> +
> +               log_freqs("Supported", freqs);
> +       }
> +}
> +
> +
>  static void * bgscan_simple_init(struct wpa_supplicant *wpa_s,
>                                  const char *params,
>                                  const struct wpa_ssid *ssid)
> @@ -125,23 +244,25 @@ static void * bgscan_simple_init(struct wpa_supplicant *wpa_s,
>                    data->signal_threshold, data->short_interval,
>                    data->long_interval);
>
> -       if (data->signal_threshold &&
> -           wpa_drv_signal_monitor(wpa_s, data->signal_threshold, 4) < 0) {
> -               wpa_printf(MSG_ERROR, "bgscan simple: Failed to enable "
> -                          "signal strength monitoring");
> -       }
> -
>         data->scan_interval = data->short_interval;
>         data->max_short_scans = data->long_interval / data->short_interval + 1;
>         if (data->signal_threshold) {
> -               /* Poll for signal info to set initial scan interval */
>                 struct wpa_signal_info siginfo;
> -               if (wpa_drv_signal_poll(wpa_s, &siginfo) == 0 &&
> +
> +               bgscan_init_signal_monitor(&data->signal_monitor, wpa_s,
> +                                          data->signal_threshold, 4);
> +
> +               /* Poll for signal info to set initial scan interval */
> +               if (bgscan_poll_signal_monitor(&data->signal_monitor,
> +                                              &siginfo) == 0 &&
>                     siginfo.current_signal >= data->signal_threshold)
>                         data->scan_interval = data->long_interval;
>         }
>         wpa_printf(MSG_DEBUG, "bgscan simple: Init scan interval: %d",
>                    data->scan_interval);
> +
> +       bgscan_simple_setup_freqs(wpa_s, data);
> +
>         eloop_register_timeout(data->scan_interval, 0, bgscan_simple_timeout,
>                                data, NULL);
>
> @@ -160,23 +281,70 @@ static void * bgscan_simple_init(struct wpa_supplicant *wpa_s,
>  static void bgscan_simple_deinit(void *priv)
>  {
>         struct bgscan_simple_data *data = priv;
> -       eloop_cancel_timeout(bgscan_simple_timeout, data, NULL);
> +       eloop_cancel_timeout(bgscan_simple_timeout, data, ELOOP_ALL_CTX);
>         if (data->signal_threshold)
> -               wpa_drv_signal_monitor(data->wpa_s, 0, 0);
> +               bgscan_deinit_signal_monitor(&data->signal_monitor);
> +       os_free(data->supp_freqs);
> +       os_free(data->scan_freqs);
>         os_free(data);
>  }
>
>
> +static int find_freq_index(const struct bgscan_simple_data *data, int freq)
> +{
> +       int ix;
> +
> +       for (ix = data->freq_idx; ix < data->n_supp_freqs; ix++)
> +               if (freq == data->supp_freqs[ix])
> +                       return ix;
> +       for (ix = 0; ix < data->freq_idx; ix++)
> +               if (freq == data->supp_freqs[ix])
> +                       return ix;
> +       return -1;
> +}
> +
>  static int bgscan_simple_notify_scan(void *priv,
>                                      struct wpa_scan_results *scan_res)
>  {
>         struct bgscan_simple_data *data = priv;
> +       char *bgscan_reason = NULL;
>
>         wpa_printf(MSG_DEBUG, "bgscan simple: scan result notification");
>
> -       eloop_cancel_timeout(bgscan_simple_timeout, data, NULL);
> +       if (scan_res->aborted && data->supp_freqs != NULL) {
> +               int last_freq, i, idx;
> +               /*
> +                * Scan was aborted; advance the rotor past known
> +                * channels visited.  This does not take into account
> +                * channels that were visited but had no scan results.
> +                * This should be ok as we always supply a complete
> +                * frequency list when we scan.
> +                *
> +                * NB: can't depend on scan results order matching our
> +                * channel list as the upper layers sort results
> +                */
> +               last_freq = 0;
> +               for (i = 0; i < scan_res->num; i++) {
> +                       if (scan_res->res[i]->freq == last_freq)
> +                               continue;
> +                       last_freq = scan_res->res[i]->freq;
> +                       idx = find_freq_index(data, last_freq) + 1;
> +                       if (idx != -1)
> +                               data->freq_idx = (idx + 1) % data->n_supp_freqs;
> +               }
> +       } else
> +               data->freq_idx = 0;
> +       wpa_printf(MSG_DEBUG, "bgscan simple: freq_idx %d", data->freq_idx);
> +
> +       if (data->signal_threshold)
> +               bgscan_poll_signal_monitor(&data->signal_monitor, NULL);
> +       if (data->scan_interval == data->short_interval)
> +               bgscan_reason = "short-interval-scan";
> +       else
> +               bgscan_reason = "long-interval-scan";
> +       eloop_cancel_timeout(bgscan_simple_timeout, data, ELOOP_ALL_CTX);
>         eloop_register_timeout(data->scan_interval, 0, bgscan_simple_timeout,
> -                              data, NULL);
> +                              data, bgscan_reason);
>
>         /*
>          * A more advanced bgscan could process scan results internally, select
> @@ -213,6 +381,10 @@ static void bgscan_simple_notify_signal_change(void *priv, int above,
>                    "(above=%d current_signal=%d current_noise=%d "
>                    "current_txrate=%d))", above, current_signal,
>                    current_noise, current_txrate);
> +
> +       bgscan_update_signal_monitor(&data->signal_monitor, current_signal,
> +                                    current_noise);
> +
>         if (data->scan_interval == data->long_interval && !above) {
>                 wpa_printf(MSG_DEBUG, "bgscan simple: Start using short "
>                            "bgscan interval");
> @@ -234,18 +406,20 @@ static void bgscan_simple_notify_signal_change(void *priv, int above,
>                          * scan is too far in the future.
>                          */
>                         eloop_cancel_timeout(bgscan_simple_timeout, data,
> -                                            NULL);
> +                                            ELOOP_ALL_CTX);
>                         eloop_register_timeout(data->scan_interval, 0,
>                                                bgscan_simple_timeout, data,
> -                                              NULL);
> +                                              "signal-below-short-interval-scan");
>                 }
>         } else if (data->scan_interval == data->short_interval && above) {
>                 wpa_printf(MSG_DEBUG, "bgscan simple: Start using long bgscan "
>                            "interval");
>                 data->scan_interval = data->long_interval;
> -               eloop_cancel_timeout(bgscan_simple_timeout, data, NULL);
> +               eloop_cancel_timeout(bgscan_simple_timeout, data,
> +                                    ELOOP_ALL_CTX);
>                 eloop_register_timeout(data->scan_interval, 0,
> -                                      bgscan_simple_timeout, data, NULL);
> +                                      bgscan_simple_timeout, data,
> +                                      "signal-above-long-interval-scan");
>         } else if (!above) {
>                 /*
>                  * Signal dropped further 4 dB. Request a new scan if we have
> @@ -258,9 +432,10 @@ static void bgscan_simple_notify_signal_change(void *priv, int above,
>
>         if (scan) {
>                 wpa_printf(MSG_DEBUG, "bgscan simple: Trigger immediate scan");
> -               eloop_cancel_timeout(bgscan_simple_timeout, data, NULL);
> +               eloop_cancel_timeout(bgscan_simple_timeout, data,
> +                                    ELOOP_ALL_CTX);
>                 eloop_register_timeout(0, 0, bgscan_simple_timeout, data,
> -                                      NULL);
> +                                      "signal-below-immediate-scan");
>         }
>  }
>
> diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
> index ee39e0c92..517a87cc6 100644
> --- a/wpa_supplicant/scan.c
> +++ b/wpa_supplicant/scan.c
> @@ -2399,6 +2399,7 @@ wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s,
>                 wpa_s->ignore_post_flush_scan_res = 0;
>                 return scan_res;
>         }
> +       scan_res->aborted = (info && info->aborted);
>
>         wpa_bss_update_start(wpa_s);
>         for (i = 0; i < scan_res->num; i++)
> --
> 2.20.1
>

_______________________________________________
Hostap mailing list
Hostap@xxxxxxxxxxxxxxxxxxx
http://lists.infradead.org/mailman/listinfo/hostap



[Index of Archives]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]

  Powered by Linux