All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC 0/3] enable HT in a mesh
@ 2011-08-24 19:02 Thomas Pedersen
  2011-08-24 19:02 ` [RFC 1/3] mac80211: comment allocation of mesh frames Thomas Pedersen
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Thomas Pedersen @ 2011-08-24 19:02 UTC (permalink / raw)
  To: linux-wireless; +Cc: Thomas Pedersen, johannes, linville

Hi I'm adding HT support for mesh.

This patchset is pretty basic, and relies on Alexander Simon's HT IE helper
funtions. No channel type negotiation takes place, and the HT info IE from the
peer is not even read.

In practice, nodes with mismatched channel types seem to communicate fine,
although throughput is affected (TX from HT40 -> HT20 is the worst case).

We measured these data rates in our (widely uncontrolled) office environment
using the ath9k_htc driver:

        A\B           NO HT             HT20                  HT40+           
       NO HT        r: 54Mb/s         r: MCS 13             r: MCS 13         
                    D: 20Mb/s         D: 16Mb/s             D: 16Mb/s         
       HT20         r: 54Mb/s         r: MCS 13             r: MCS 13         
                   D: 22.5Mb/s       D: 18.5Mb/s            D: 15Mb/s         
       HT40+        r: 54Mb/s         r: MCS 0          r: MCS 12 @ 40Mhz     
                    D: 22Mb/s        D: 5.1Mb/s             D: 20Mb/s  

	r: rate reported by minstrel.
	D: TX throughput (A -> B using 'iperf -c <B> -u -b400M')

Is it odd that even HT40+ -> HT40+ is not any better than the non-HT case? Are
we doing something wrong? Are you surprised that mismatched channel types work
at all?

So currently, our channel type is always just whatever the user configured
through iw. The path selection algorithm should be able to compensate by
detecting faster links and adjusting the respective mpaths accordingly.

If this is completely wrong, I would appreciate any suggestions on the right
way to handle mesh peers with different channel types.

Thanks,
Thomas

Thomas Pedersen (3):
  mac80211: comment allocation of mesh frames
  mac80211: add HT IEs to mesh frames
  mac80211: set HT capabilities for mesh peer

 net/mac80211/mesh.c       |   43 +++++++++++++++++++++++++++++++++++++++++++
 net/mac80211/mesh.h       |    4 ++++
 net/mac80211/mesh_hwmp.c  |   10 ++++++++--
 net/mac80211/mesh_plink.c |   39 ++++++++++++++++++++++++++++++++-------
 net/mac80211/tx.c         |   16 +++++++++++++---
 5 files changed, 100 insertions(+), 12 deletions(-)

-- 
1.7.4.1


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [RFC 1/3] mac80211: comment allocation of mesh frames
  2011-08-24 19:02 [RFC 0/3] enable HT in a mesh Thomas Pedersen
@ 2011-08-24 19:02 ` Thomas Pedersen
  2011-08-29 13:52   ` Johannes Berg
  2011-08-24 19:02 ` [RFC 2/3] mac80211: add HT IEs to " Thomas Pedersen
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 6+ messages in thread
From: Thomas Pedersen @ 2011-08-24 19:02 UTC (permalink / raw)
  To: linux-wireless; +Cc: Thomas Pedersen, johannes, linville

save a few bytes and hopefully improve readability.

Signed-off-by: Thomas Pedersen <thomas@cozybit.com>
---
 net/mac80211/mesh_hwmp.c  |   10 ++++++++--
 net/mac80211/mesh_plink.c |   13 +++++++++++--
 net/mac80211/tx.c         |   12 +++++++++---
 3 files changed, 28 insertions(+), 7 deletions(-)

diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index f09e5e8..d5f4a41 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -129,11 +129,14 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
 		struct ieee80211_sub_if_data *sdata)
 {
 	struct ieee80211_local *local = sdata->local;
-	struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400);
+	struct sk_buff *skb = NULL;
 	struct ieee80211_mgmt *mgmt;
 	u8 *pos;
 	int ie_len;
 
+	skb = dev_alloc_skb(local->hw.extra_tx_headroom +
+			    25 + sizeof(mgmt->u.action.u.mesh_action) +
+			    2 + 37); /* HWMP IEs */
 	if (!skb)
 		return -1;
 	skb_reserve(skb, local->hw.extra_tx_headroom);
@@ -232,11 +235,14 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn,
 		       struct ieee80211_sub_if_data *sdata)
 {
 	struct ieee80211_local *local = sdata->local;
-	struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400);
+	struct sk_buff *skb = NULL;
 	struct ieee80211_mgmt *mgmt;
 	u8 *pos;
 	int ie_len;
 
+	skb = dev_alloc_skb(local->hw.extra_tx_headroom +
+			    25 + sizeof(mgmt->u.action.u.mesh_action) +
+			    2 + 15 /* PERR IE */);
 	if (!skb)
 		return -1;
 	skb_reserve(skb, local->hw.extra_tx_headroom);
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 1a00d0f..f8c9666 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -143,14 +143,23 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
 		enum ieee80211_self_protected_actioncode action,
 		u8 *da, __le16 llid, __le16 plid, __le16 reason) {
 	struct ieee80211_local *local = sdata->local;
-	struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400 +
-			sdata->u.mesh.ie_len);
+	struct sk_buff *skb = NULL;
 	struct ieee80211_mgmt *mgmt;
 	bool include_plid = false;
 	int ie_len = 4;
 	u16 peering_proto = 0;
 	u8 *pos;
 
+	skb = dev_alloc_skb(local->hw.extra_tx_headroom +
+			    25 + sizeof(mgmt->u.action.u.self_prot) +
+			    2 + /* capability info */
+			    2 + /* AID */
+			    2 + 8 + /* supported rates */
+			    2 + (IEEE80211_MAX_SUPP_RATES - 8) +
+			    2 + sdata->u.mesh.mesh_id_len +
+			    2 + sizeof(struct ieee80211_meshconf_ie) +
+			    2 + 8 + /* peering IE */
+			    sdata->u.mesh.ie_len);
 	if (!skb)
 		return -1;
 	skb_reserve(skb, local->hw.extra_tx_headroom);
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 0107263..ba1956a 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -2278,9 +2278,15 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
 			goto out;
 #endif
 
-		/* headroom, head length, tail length and maximum TIM length */
-		skb = dev_alloc_skb(local->tx_headroom + 400 +
-				sdata->u.mesh.ie_len);
+		skb = dev_alloc_skb(local->tx_headroom +
+				    24 + sizeof(mgmt->u.beacon) +
+				    2 + /* NULL SSID */
+				    2 + 8 + /* supported rates */
+				    2 + 3 + /* DS params */
+				    2 + (IEEE80211_MAX_SUPP_RATES - 8) +
+				    2 + sdata->u.mesh.mesh_id_len +
+				    2 + sizeof(struct ieee80211_meshconf_ie) +
+				    sdata->u.mesh.ie_len);
 		if (!skb)
 			goto out;
 
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [RFC 2/3] mac80211: add HT IEs to mesh frames
  2011-08-24 19:02 [RFC 0/3] enable HT in a mesh Thomas Pedersen
  2011-08-24 19:02 ` [RFC 1/3] mac80211: comment allocation of mesh frames Thomas Pedersen
@ 2011-08-24 19:02 ` Thomas Pedersen
  2011-08-24 19:02 ` [RFC 3/3] mac80211: set HT capabilities for mesh peer Thomas Pedersen
  2011-08-29 13:54 ` [RFC 0/3] enable HT in a mesh Johannes Berg
  3 siblings, 0 replies; 6+ messages in thread
From: Thomas Pedersen @ 2011-08-24 19:02 UTC (permalink / raw)
  To: linux-wireless; +Cc: Thomas Pedersen, johannes, linville

Signed-off-by: Thomas Pedersen <thomas@cozybit.com>
---
 net/mac80211/mesh.c       |   43 +++++++++++++++++++++++++++++++++++++++++++
 net/mac80211/mesh.h       |    4 ++++
 net/mac80211/mesh_plink.c |    9 +++++++++
 net/mac80211/tx.c         |    4 ++++
 4 files changed, 60 insertions(+), 0 deletions(-)

diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 28ab510..6ed233d 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -400,6 +400,49 @@ int mesh_add_ds_params_ie(struct sk_buff *skb,
 	return 0;
 }
 
+int mesh_add_ht_cap_ie(struct sk_buff *skb,
+		       struct ieee80211_sub_if_data *sdata)
+{
+	struct ieee80211_local *local = sdata->local;
+	struct ieee80211_supported_band *sband;
+	u8 *pos;
+
+	sband = local->hw.wiphy->bands[local->oper_channel->band];
+	if (!sband->ht_cap.ht_supported ||
+	    local->_oper_channel_type == NL80211_CHAN_NO_HT)
+		return 0;
+
+	if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_cap))
+		return -ENOMEM;
+
+	pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_cap));
+	ieee80211_ie_build_ht_cap(pos, sband, sband->ht_cap.cap);
+
+	return 0;
+}
+
+int mesh_add_ht_info_ie(struct sk_buff *skb,
+			struct ieee80211_sub_if_data *sdata)
+{
+	struct ieee80211_local *local = sdata->local;
+	struct ieee80211_channel *channel = local->oper_channel;
+	enum nl80211_channel_type channel_type = local->_oper_channel_type;
+	struct ieee80211_supported_band *sband =
+				local->hw.wiphy->bands[channel->band];
+	struct ieee80211_sta_ht_cap *ht_cap = &sband->ht_cap;
+	u8 *pos;
+
+	if (!ht_cap->ht_supported || channel_type == NL80211_CHAN_NO_HT)
+		return 0;
+
+	if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_info))
+		return -ENOMEM;
+
+	pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_info));
+	ieee80211_ie_build_ht_info(pos, ht_cap, channel, channel_type);
+
+	return 0;
+}
 static void ieee80211_mesh_path_timer(unsigned long data)
 {
 	struct ieee80211_sub_if_data *sdata =
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index 42536a4..334c392 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -221,6 +221,10 @@ int mesh_add_ext_srates_ie(struct sk_buff *skb,
 			   struct ieee80211_sub_if_data *sdata);
 int mesh_add_ds_params_ie(struct sk_buff *skb,
 			  struct ieee80211_sub_if_data *sdata);
+int mesh_add_ht_cap_ie(struct sk_buff *skb,
+		       struct ieee80211_sub_if_data *sdata);
+int mesh_add_ht_info_ie(struct sk_buff *skb,
+			struct ieee80211_sub_if_data *sdata);
 void mesh_rmc_free(struct ieee80211_sub_if_data *sdata);
 int mesh_rmc_init(struct ieee80211_sub_if_data *sdata);
 void ieee80211s_init(void);
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index f8c9666..8f068b1 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -158,6 +158,8 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
 			    2 + (IEEE80211_MAX_SUPP_RATES - 8) +
 			    2 + sdata->u.mesh.mesh_id_len +
 			    2 + sizeof(struct ieee80211_meshconf_ie) +
+			    2 + sizeof(struct ieee80211_ht_cap) +
+			    2 + sizeof(struct ieee80211_ht_info) +
 			    2 + 8 + /* peering IE */
 			    sdata->u.mesh.ie_len);
 	if (!skb)
@@ -234,6 +236,13 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
 		memcpy(pos, &reason, 2);
 		pos += 2;
 	}
+
+	if (action != WLAN_SP_MESH_PEERING_CLOSE) {
+		if (mesh_add_ht_cap_ie(skb, sdata) ||
+		    mesh_add_ht_info_ie(skb, sdata))
+			return -1;
+	}
+
 	if (mesh_add_vendor_ies(skb, sdata))
 		return -1;
 
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index ba1956a..173b40b 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -2284,6 +2284,8 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
 				    2 + 8 + /* supported rates */
 				    2 + 3 + /* DS params */
 				    2 + (IEEE80211_MAX_SUPP_RATES - 8) +
+				    2 + sizeof(struct ieee80211_ht_cap) +
+				    2 + sizeof(struct ieee80211_ht_info) +
 				    2 + sdata->u.mesh.mesh_id_len +
 				    2 + sizeof(struct ieee80211_meshconf_ie) +
 				    sdata->u.mesh.ie_len);
@@ -2312,6 +2314,8 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
 		    mesh_add_ds_params_ie(skb, sdata) ||
 		    mesh_add_ext_srates_ie(skb, sdata) ||
 		    mesh_add_rsn_ie(skb, sdata) ||
+		    mesh_add_ht_cap_ie(skb, sdata) ||
+		    mesh_add_ht_info_ie(skb, sdata) ||
 		    mesh_add_meshid_ie(skb, sdata) ||
 		    mesh_add_meshconf_ie(skb, sdata) ||
 		    mesh_add_vendor_ies(skb, sdata)) {
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [RFC 3/3] mac80211: set HT capabilities for mesh peer
  2011-08-24 19:02 [RFC 0/3] enable HT in a mesh Thomas Pedersen
  2011-08-24 19:02 ` [RFC 1/3] mac80211: comment allocation of mesh frames Thomas Pedersen
  2011-08-24 19:02 ` [RFC 2/3] mac80211: add HT IEs to " Thomas Pedersen
@ 2011-08-24 19:02 ` Thomas Pedersen
  2011-08-29 13:54 ` [RFC 0/3] enable HT in a mesh Johannes Berg
  3 siblings, 0 replies; 6+ messages in thread
From: Thomas Pedersen @ 2011-08-24 19:02 UTC (permalink / raw)
  To: linux-wireless; +Cc: Thomas Pedersen, johannes, linville

Signed-off-by: Thomas Pedersen <thomas@cozybit.com>
---
 net/mac80211/mesh_plink.c |   17 ++++++++++++-----
 1 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 8f068b1..e9dd761 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -76,11 +76,15 @@ static inline void mesh_plink_fsm_restart(struct sta_info *sta)
  *       on it in the lifecycle management section!
  */
 static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
-					 u8 *hw_addr, u32 rates)
+					 u8 *hw_addr, u32 rates,
+					 struct ieee802_11_elems *elems)
 {
 	struct ieee80211_local *local = sdata->local;
+	struct ieee80211_supported_band *sband;
 	struct sta_info *sta;
 
+	sband = local->hw.wiphy->bands[local->oper_channel->band];
+
 	if (local->num_sta >= MESH_MAX_PLINKS)
 		return NULL;
 
@@ -90,6 +94,9 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
 
 	sta->flags = WLAN_STA_AUTHORIZED | WLAN_STA_AUTH;
 	sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
+	if (elems->ht_cap_elem)
+		ieee80211_ht_cap_ie_to_sta_ht_cap(sband, elems->ht_cap_elem,
+						  &sta->sta.ht_cap);
 	rate_control_rate_init(sta);
 
 	return sta;
@@ -251,8 +258,8 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
 }
 
 void mesh_neighbour_update(u8 *hw_addr, u32 rates,
-		struct ieee80211_sub_if_data *sdata,
-		struct ieee802_11_elems *elems)
+			   struct ieee80211_sub_if_data *sdata,
+			   struct ieee802_11_elems *elems)
 {
 	struct ieee80211_local *local = sdata->local;
 	struct sta_info *sta;
@@ -269,7 +276,7 @@ void mesh_neighbour_update(u8 *hw_addr, u32 rates,
 					elems->ie_start, elems->total_len,
 					GFP_KERNEL);
 		else
-			sta = mesh_plink_alloc(sdata, hw_addr, rates);
+			sta = mesh_plink_alloc(sdata, hw_addr, rates, elems);
 		if (!sta)
 			return;
 		if (sta_info_insert_rcu(sta)) {
@@ -560,7 +567,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
 		}
 
 		rates = ieee80211_sta_get_rates(local, &elems, rx_status->band);
-		sta = mesh_plink_alloc(sdata, mgmt->sa, rates);
+		sta = mesh_plink_alloc(sdata, mgmt->sa, rates, &elems);
 		if (!sta) {
 			mpl_dbg("Mesh plink error: plink table full\n");
 			return;
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [RFC 1/3] mac80211: comment allocation of mesh frames
  2011-08-24 19:02 ` [RFC 1/3] mac80211: comment allocation of mesh frames Thomas Pedersen
@ 2011-08-29 13:52   ` Johannes Berg
  0 siblings, 0 replies; 6+ messages in thread
From: Johannes Berg @ 2011-08-29 13:52 UTC (permalink / raw)
  To: Thomas Pedersen; +Cc: linux-wireless, linville

On Wed, 2011-08-24 at 12:02 -0700, Thomas Pedersen wrote:

> diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
> index f09e5e8..d5f4a41 100644
> --- a/net/mac80211/mesh_hwmp.c
> +++ b/net/mac80211/mesh_hwmp.c
> @@ -129,11 +129,14 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
>  		struct ieee80211_sub_if_data *sdata)
>  {
>  	struct ieee80211_local *local = sdata->local;
> -	struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400);
> +	struct sk_buff *skb = NULL;

No need for = NULL.


> +	skb = dev_alloc_skb(local->hw.extra_tx_headroom +
> +			    25 + sizeof(mgmt->u.action.u.mesh_action) +
> +			    2 + 37); /* HWMP IEs */

IEs? Should that be singular, or is the 2 wrong? Is there a struct that
you can take sizeof() for 37? Maybe not yet?

johannes


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [RFC 0/3] enable HT in a mesh
  2011-08-24 19:02 [RFC 0/3] enable HT in a mesh Thomas Pedersen
                   ` (2 preceding siblings ...)
  2011-08-24 19:02 ` [RFC 3/3] mac80211: set HT capabilities for mesh peer Thomas Pedersen
@ 2011-08-29 13:54 ` Johannes Berg
  3 siblings, 0 replies; 6+ messages in thread
From: Johannes Berg @ 2011-08-29 13:54 UTC (permalink / raw)
  To: Thomas Pedersen; +Cc: linux-wireless, linville

On Wed, 2011-08-24 at 12:02 -0700, Thomas Pedersen wrote:
> Hi I'm adding HT support for mesh.
> 
> This patchset is pretty basic, and relies on Alexander Simon's HT IE helper
> funtions.

Ok. I'm pretty happy with those, but haven't seen the latest version of
the IBSS parts.

> No channel type negotiation takes place, and the HT info IE from the
> peer is not even read.

That seems odd.

> In practice, nodes with mismatched channel types seem to communicate fine,
> although throughput is affected (TX from HT40 -> HT20 is the worst case).

That would highly depend on rate control? Or do we do some HT
capability/operation IE stuff and figure this out? Still seems a little
strange.

> We measured these data rates in our (widely uncontrolled) office environment
> using the ath9k_htc driver:
> 
>         A\B           NO HT             HT20                  HT40+           
>        NO HT        r: 54Mb/s         r: MCS 13             r: MCS 13         
>                     D: 20Mb/s         D: 16Mb/s             D: 16Mb/s         
>        HT20         r: 54Mb/s         r: MCS 13             r: MCS 13         
>                    D: 22.5Mb/s       D: 18.5Mb/s            D: 15Mb/s         
>        HT40+        r: 54Mb/s         r: MCS 0          r: MCS 12 @ 40Mhz     
>                     D: 22Mb/s        D: 5.1Mb/s             D: 20Mb/s  
> 
> 	r: rate reported by minstrel.
> 	D: TX throughput (A -> B using 'iperf -c <B> -u -b400M')
> 
> Is it odd that even HT40+ -> HT40+ is not any better than the non-HT case? Are
> we doing something wrong? Are you surprised that mismatched channel types work
> at all?

Not surprised, but won't be efficient, especially when some device uses
a dumber rate control than minstrel :)

> So currently, our channel type is always just whatever the user configured
> through iw. The path selection algorithm should be able to compensate by
> detecting faster links and adjusting the respective mpaths accordingly.
> 
> If this is completely wrong, I would appreciate any suggestions on the right
> way to handle mesh peers with different channel types.

I have no idea. The channel type stuff seems a little fishy though.

johannes


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2011-08-29 13:54 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-08-24 19:02 [RFC 0/3] enable HT in a mesh Thomas Pedersen
2011-08-24 19:02 ` [RFC 1/3] mac80211: comment allocation of mesh frames Thomas Pedersen
2011-08-29 13:52   ` Johannes Berg
2011-08-24 19:02 ` [RFC 2/3] mac80211: add HT IEs to " Thomas Pedersen
2011-08-24 19:02 ` [RFC 3/3] mac80211: set HT capabilities for mesh peer Thomas Pedersen
2011-08-29 13:54 ` [RFC 0/3] enable HT in a mesh Johannes Berg

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.