Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 10 Dec 2016 10:57:32 -0800
From:      Adrian Chadd <adrian.chadd@gmail.com>
To:        Andriy Voskoboinyk <avos@freebsd.org>
Cc:        "src-committers@freebsd.org" <src-committers@freebsd.org>,  "svn-src-all@freebsd.org" <svn-src-all@freebsd.org>,  "svn-src-head@freebsd.org" <svn-src-head@freebsd.org>
Subject:   Re: svn commit: r309825 - head/sys/dev/usb/wlan
Message-ID:  <CAJ-VmokymV21zqZy9BTN_zMo67E6ipuhSrzJ%2Bvz6Q%2B5HMxFo=g@mail.gmail.com>
In-Reply-To: <201612101847.uBAIlEFb094635@repo.freebsd.org>
References:  <201612101847.uBAIlEFb094635@repo.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
Would you mind updating the manpage to state this monitor/promisc
difference in the LIMITATIONS section, or something?

Thanks!



-a


On 10 December 2016 at 10:47, Andriy Voskoboinyk <avos@freebsd.org> wrote:
> Author: avos
> Date: Sat Dec 10 18:47:13 2016
> New Revision: 309825
> URL: https://svnweb.freebsd.org/changeset/base/309825
>
> Log:
>   rsu: add promiscuous mode support.
>
>   - Add partial promiscuous mode support (no management frames;
>   they cannot be received by the firmware and net80211 at the same time).
>   - Add monitor mode support (all frames).
>
>   Tested with Asus, USB-N10.
>
> Modified:
>   head/sys/dev/usb/wlan/if_rsu.c
>   head/sys/dev/usb/wlan/if_rsureg.h
>
> Modified: head/sys/dev/usb/wlan/if_rsu.c
> ==============================================================================
> --- head/sys/dev/usb/wlan/if_rsu.c      Sat Dec 10 18:29:39 2016        (r309824)
> +++ head/sys/dev/usb/wlan/if_rsu.c      Sat Dec 10 18:47:13 2016        (r309825)
> @@ -23,7 +23,7 @@ __FBSDID("$FreeBSD$");
>   *
>   * TODO:
>   *   o tx a-mpdu
> - *   o monitor / hostap / ibss / mesh
> + *   o hostap / ibss / mesh
>   *   o power-save operation
>   */
>
> @@ -175,6 +175,7 @@ static void rsu_getradiocaps(struct ieee
>  static void    rsu_set_channel(struct ieee80211com *);
>  static void    rsu_scan_curchan(struct ieee80211_scan_state *, unsigned long);
>  static void    rsu_scan_mindwell(struct ieee80211_scan_state *);
> +static void    rsu_update_promisc(struct ieee80211com *);
>  static uint8_t rsu_get_multi_pos(const uint8_t[]);
>  static void    rsu_set_multi(struct rsu_softc *);
>  static void    rsu_update_mcast(struct ieee80211com *);
> @@ -202,6 +203,9 @@ static int  rsu_read_rom(struct rsu_softc
>  static int     rsu_fw_cmd(struct rsu_softc *, uint8_t, void *, int);
>  static void    rsu_calib_task(void *, int);
>  static void    rsu_tx_task(void *, int);
> +static void    rsu_set_led(struct rsu_softc *, int);
> +static int     rsu_monitor_newstate(struct ieee80211vap *,
> +                   enum ieee80211_state, int);
>  static int     rsu_newstate(struct ieee80211vap *, enum ieee80211_state, int);
>  static int     rsu_key_alloc(struct ieee80211vap *, struct ieee80211_key *,
>                     ieee80211_keyix *, ieee80211_keyix *);
> @@ -244,6 +248,9 @@ static struct mbuf *
>  static void    rsu_txeof(struct usb_xfer *, struct rsu_data *);
>  static int     rsu_raw_xmit(struct ieee80211_node *, struct mbuf *,
>                     const struct ieee80211_bpf_params *);
> +static void    rsu_rxfilter_init(struct rsu_softc *);
> +static void    rsu_rxfilter_set(struct rsu_softc *, uint32_t, uint32_t);
> +static void    rsu_rxfilter_refresh(struct rsu_softc *);
>  static void    rsu_init(struct rsu_softc *);
>  static int     rsu_tx_start(struct rsu_softc *, struct ieee80211_node *,
>                     struct mbuf *, struct rsu_data *);
> @@ -536,6 +543,7 @@ rsu_attach(device_t self)
>         /* Set device capabilities. */
>         ic->ic_caps =
>             IEEE80211_C_STA |           /* station mode */
> +           IEEE80211_C_MONITOR |       /* monitor mode supported */
>  #if 0
>             IEEE80211_C_BGSCAN |        /* Background scan. */
>  #endif
> @@ -582,6 +590,7 @@ rsu_attach(device_t self)
>         ic->ic_scan_mindwell = rsu_scan_mindwell;
>         ic->ic_vap_create = rsu_vap_create;
>         ic->ic_vap_delete = rsu_vap_delete;
> +       ic->ic_update_promisc = rsu_update_promisc;
>         ic->ic_update_mcast = rsu_update_mcast;
>         ic->ic_parent = rsu_parent;
>         ic->ic_transmit = rsu_transmit;
> @@ -688,7 +697,10 @@ rsu_vap_create(struct ieee80211com *ic,
>
>         /* override state transition machine */
>         uvp->newstate = vap->iv_newstate;
> -       vap->iv_newstate = rsu_newstate;
> +       if (opmode == IEEE80211_M_MONITOR)
> +               vap->iv_newstate = rsu_monitor_newstate;
> +       else
> +               vap->iv_newstate = rsu_newstate;
>         vap->iv_key_alloc = rsu_key_alloc;
>         vap->iv_key_set = rsu_key_set;
>         vap->iv_key_delete = rsu_key_delete;
> @@ -759,9 +771,30 @@ rsu_getradiocaps(struct ieee80211com *ic
>  }
>
>  static void
> -rsu_set_channel(struct ieee80211com *ic __unused)
> +rsu_set_channel(struct ieee80211com *ic)
>  {
> -       /* We are unable to switch channels, yet. */
> +       struct rsu_softc *sc = ic->ic_softc;
> +
> +       /*
> +        * Only need to set the channel in Monitor mode. AP scanning and auth
> +        * are already taken care of by their respective firmware commands.
> +        */
> +       if (ic->ic_opmode == IEEE80211_M_MONITOR) {
> +               struct r92s_set_channel cmd;
> +               int error;
> +
> +               cmd.channel = IEEE80211_CHAN2IEEE(ic->ic_curchan);
> +
> +               RSU_LOCK(sc);
> +               error = rsu_fw_cmd(sc, R92S_CMD_SET_CHANNEL, &cmd,
> +                   sizeof(cmd));
> +               if (error != 0) {
> +                       device_printf(sc->sc_dev,
> +                           "%s: error %d setting channel\n", __func__,
> +                           error);
> +               }
> +               RSU_UNLOCK(sc);
> +       }
>  }
>
>  static void
> @@ -782,6 +815,17 @@ rsu_scan_mindwell(struct ieee80211_scan_
>         /* NB: don't try to abort scan; wait for firmware to finish */
>  }
>
> +static void
> +rsu_update_promisc(struct ieee80211com *ic)
> +{
> +       struct rsu_softc *sc = ic->ic_softc;
> +
> +       RSU_LOCK(sc);
> +       if (sc->sc_running)
> +               rsu_rxfilter_refresh(sc);
> +       RSU_UNLOCK(sc);
> +}
> +
>  /*
>   * The same as rtwn_get_multi_pos() / rtwn_set_multi().
>   */
> @@ -1343,6 +1387,47 @@ rsu_set_fw_power_state(struct rsu_softc
>         return (error);
>  }
>
> +static void
> +rsu_set_led(struct rsu_softc *sc, int on)
> +{
> +       rsu_write_1(sc, R92S_LEDCFG,
> +           (rsu_read_1(sc, R92S_LEDCFG) & 0xf0) | (!on << 3));
> +}
> +
> +static int
> +rsu_monitor_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate,
> +    int arg)
> +{
> +       struct ieee80211com *ic = vap->iv_ic;
> +       struct rsu_softc *sc = ic->ic_softc;
> +       struct rsu_vap *uvp = RSU_VAP(vap);
> +
> +       if (vap->iv_state != nstate) {
> +               IEEE80211_UNLOCK(ic);
> +               RSU_LOCK(sc);
> +
> +               switch (nstate) {
> +               case IEEE80211_S_INIT:
> +                       sc->sc_vap_is_running = 0;
> +                       rsu_set_led(sc, 0);
> +                       break;
> +               case IEEE80211_S_RUN:
> +                       sc->sc_vap_is_running = 1;
> +                       rsu_set_led(sc, 1);
> +                       break;
> +               default:
> +                       /* NOTREACHED */
> +                       break;
> +               }
> +               rsu_rxfilter_refresh(sc);
> +
> +               RSU_UNLOCK(sc);
> +               IEEE80211_LOCK(ic);
> +       }
> +
> +       return (uvp->newstate(vap, nstate, arg));
> +}
> +
>  static int
>  rsu_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
>  {
> @@ -1376,6 +1461,12 @@ rsu_newstate(struct ieee80211vap *vap, e
>                 RSU_LOCK(sc);
>                 /* Disassociate from our current BSS. */
>                 rsu_disconnect(sc);
> +               usb_pause_mtx(&sc->sc_mtx, USB_MS_TO_TICKS(10));
> +
> +               /* Refresh Rx filter (may be modified by firmware). */
> +               sc->sc_vap_is_running = 0;
> +               rsu_rxfilter_refresh(sc);
> +
>                 /* Reinstall static keys. */
>                 if (sc->sc_running)
>                         rsu_reinit_static_keys(sc);
> @@ -2030,6 +2121,11 @@ rsu_event_join_bss(struct rsu_softc *sc,
>             __func__, ether_sprintf(rsp->bss.macaddr), tmp);
>         /* XXX is this required? What's the top two bits for again? */
>         ni->ni_associd = tmp | 0xc000;
> +
> +       /* Refresh Rx filter (was changed by firmware). */
> +       sc->sc_vap_is_running = 1;
> +       rsu_rxfilter_refresh(sc);
> +
>         RSU_UNLOCK(sc);
>         ieee80211_new_state(vap, IEEE80211_S_RUN,
>             IEEE80211_FC0_SUBTYPE_ASSOC_RESP);
> @@ -3329,6 +3425,65 @@ rsu_raw_xmit(struct ieee80211_node *ni,
>  }
>
>  static void
> +rsu_rxfilter_init(struct rsu_softc *sc)
> +{
> +       uint32_t reg;
> +
> +       RSU_ASSERT_LOCKED(sc);
> +
> +       /* Setup multicast filter. */
> +       rsu_set_multi(sc);
> +
> +       /* Adjust Rx filter. */
> +       reg = rsu_read_4(sc, R92S_RCR);
> +       reg &= ~R92S_RCR_AICV;
> +       reg |= R92S_RCR_APP_PHYSTS;
> +       rsu_write_4(sc, R92S_RCR, reg);
> +
> +       /* Update dynamic Rx filter parts. */
> +       rsu_rxfilter_refresh(sc);
> +}
> +
> +static void
> +rsu_rxfilter_set(struct rsu_softc *sc, uint32_t clear, uint32_t set)
> +{
> +       /* NB: firmware can touch this register too. */
> +       rsu_write_4(sc, R92S_RCR,
> +          (rsu_read_4(sc, R92S_RCR) & ~clear) | set);
> +}
> +
> +static void
> +rsu_rxfilter_refresh(struct rsu_softc *sc)
> +{
> +       struct ieee80211com *ic = &sc->sc_ic;
> +       uint32_t mask_all, mask_min;
> +
> +       RSU_ASSERT_LOCKED(sc);
> +
> +       /* NB: RCR_AMF / RXFLTMAP_MGT are used by firmware. */
> +       mask_all = R92S_RCR_ACF | R92S_RCR_AAP;
> +       mask_min = R92S_RCR_APM;
> +       if (sc->sc_vap_is_running)
> +               mask_min |= R92S_RCR_CBSSID;
> +       else
> +               mask_all |= R92S_RCR_ADF;
> +
> +       if (ic->ic_opmode == IEEE80211_M_MONITOR) {
> +               uint16_t rxfltmap;
> +               if (sc->sc_vap_is_running)
> +                       rxfltmap = 0;
> +               else
> +                       rxfltmap = R92S_RXFLTMAP_MGT_DEF;
> +               rsu_write_2(sc, R92S_RXFLTMAP_MGT, rxfltmap);
> +       }
> +
> +       if (ic->ic_promisc == 0 && ic->ic_opmode != IEEE80211_M_MONITOR)
> +               rsu_rxfilter_set(sc, mask_all, mask_min);
> +       else
> +               rsu_rxfilter_set(sc, mask_min, mask_all);
> +}
> +
> +static void
>  rsu_init(struct rsu_softc *sc)
>  {
>         struct ieee80211com *ic = &sc->sc_ic;
> @@ -3394,12 +3549,8 @@ rsu_init(struct rsu_softc *sc)
>                 goto fail;
>         }
>
> -       /* Append PHY status. */
> -       rsu_write_4(sc, R92S_RCR,
> -           rsu_read_4(sc, R92S_RCR) | 0x02000000);
> -
> -       /* Setup multicast filter (must be done after firmware loading). */
> -       rsu_set_multi(sc);
> +       /* Initialize Rx filter. */
> +       rsu_rxfilter_init(sc);
>
>         /* Set PS mode fully active */
>         error = rsu_set_fw_power_state(sc, RSU_PWR_ACTIVE);
> @@ -3433,6 +3584,7 @@ rsu_stop(struct rsu_softc *sc)
>         RSU_ASSERT_LOCKED(sc);
>
>         sc->sc_running = 0;
> +       sc->sc_vap_is_running = 0;
>         sc->sc_calibrating = 0;
>         taskqueue_cancel_timeout(taskqueue_thread, &sc->calib_task, NULL);
>         taskqueue_cancel(taskqueue_thread, &sc->tx_task, NULL);
>
> Modified: head/sys/dev/usb/wlan/if_rsureg.h
> ==============================================================================
> --- head/sys/dev/usb/wlan/if_rsureg.h   Sat Dec 10 18:29:39 2016        (r309824)
> +++ head/sys/dev/usb/wlan/if_rsureg.h   Sat Dec 10 18:47:13 2016        (r309825)
> @@ -54,6 +54,12 @@
>  #define R92S_TIMECTRL          0x0080
>  #define R92S_TSFTR             (R92S_TIMECTRL + 0x000)
>
> +#define R92S_FIFOCTRL          0x00a0
> +#define R92S_RXFLTMAP_MGT      (R92S_FIFOCTRL + 0x076)
> +#define R92S_RXFLTMAP_CTL      (R92S_FIFOCTRL + 0x078)
> +#define R92S_RXFLTMAP_DATA     (R92S_FIFOCTRL + 0x07a)
> +#define R92S_RXFLTMAP_MESH     (R92S_FIFOCTRL + 0x07c)
> +
>  #define R92S_SECURITY          0x0240
>  #define R92S_CAMCMD            (R92S_SECURITY + 0x000)
>  #define R92S_CAMWRITE          (R92S_SECURITY + 0x004)
> @@ -63,6 +69,7 @@
>  #define R92S_GPIO_CTRL         (R92S_GP + 0x00c)
>  #define R92S_GPIO_IO_SEL       (R92S_GP + 0x00e)
>  #define R92S_MAC_PINMUX_CTRL   (R92S_GP + 0x011)
> +#define R92S_LEDCFG            (R92S_GP + 0x012)
>
>  #define R92S_IOCMD_CTRL                0x0370
>  #define R92S_IOCMD_DATA                0x0374
> @@ -141,6 +148,29 @@
>  #define R92S_TCR_IMEM_RDY      0x20
>  #define R92S_TCR_FWRDY         0x80
>
> +/* Bits for R92S_RCR. */
> +#define R92S_RCR_AAP           0x00000001
> +#define R92S_RCR_APM           0x00000002
> +#define R92S_RCR_AM            0x00000004
> +#define R92S_RCR_AB            0x00000008
> +#define R92S_RCR_ACRC32                0x00000020
> +#define R92S_RCR_AICV          0x00001000
> +#define R92S_RCR_APP_ICV       0x00010000
> +#define R92S_RCR_APP_MIC       0x00020000
> +#define R92S_RCR_ADF           0x00040000
> +#define R92S_RCR_ACF           0x00080000
> +#define R92S_RCR_AMF           0x00100000
> +#define R92S_RCR_ADD3          0x00200000
> +#define R92S_RCR_APWRMGT       0x00400000
> +#define R92S_RCR_CBSSID                0x00800000
> +#define R92S_RCR_APP_PHYSTS    0x02000000
> +#define R92S_RCR_ENMBID                0x08000000
> +
> +/* Bits for R92S_RXFLTMAP*. */
> +#define R92S_RXFLTMAP_MGT_DEF  0x3f3f
> +#define R92S_RXFLTMAP_FW(subtype)      \
> +       (1 << ((subtype) >> IEEE80211_FC0_SUBTYPE_SHIFT))
> +
>  /* Bits for R92S_GPIO_IO_SEL. */
>  #define R92S_GPIO_WPS  0x10
>
> @@ -546,6 +576,11 @@ struct r92s_set_pwr_mode {
>         uint8_t         bcn_pass_time;
>  } __packed;
>
> +/* Structure for R92S_CMD_SET_CHANNEL. */
> +struct r92s_set_channel {
> +       uint32_t        channel;
> +} __packed;
> +
>  /* Structure for event R92S_EVENT_JOIN_BSS. */
>  struct r92s_event_join_bss {
>         uint32_t        next;
> @@ -817,6 +852,7 @@ struct rsu_softc {
>         int                             sc_currssi;
>
>         u_int                           sc_running:1,
> +                                       sc_vap_is_running:1,
>                                         sc_calibrating:1,
>                                         sc_active_scan:1,
>                                         sc_extra_scan:1;
>



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAJ-VmokymV21zqZy9BTN_zMo67E6ipuhSrzJ%2Bvz6Q%2B5HMxFo=g>