loader-logo

Updates to Meraki Client Balancing

A change to Meraki’s underlying algorithm for Client Balancing is getting an overhaul in version MR29.1.

In early July 2022, Meraki released a public beta of MR29.1 which includes a change in the way Client Balancing is handled.

At Packet6, we’ve always recommended disabling Client Balancing due to how devices negatively reacted.

Prior to MR29.1, a Meraki access point would reject a device association. As a result, the user experience would be poor – often considered as Wi-Fi not working or experiencing long times to connect.

In this blog post, we’ll discuss what’s different in Client Balancing and how it might be useful.

What is Client Balancing?

Client Balancing is a method of steering devices to an access point with less load (or number of devices associated).

There are a few metrics taken into consideration for Client Balancing:

  • Load
  • Best AP
  • Best AP Load
  • Best AP RSSI

Note

You can view the Meraki logs to see if devices are being rejected due to Client Balancing by filtering the event log to “802.11 association rejected for client balancing”.

Meraki logs of association rejections

Load (on the target AP) will identify how many devices are currently associated on the access point. Client Balancing will know the Best AP for a device to associate to, along with how many devices are associated to that AP (called Best AP Load), along with that AP’s RSSI view of the device.

Meraki access points share a database with other nearby Meraki access points containing a list of associated and nearby devices.

Access points form an AP Resource Group for a nearby device, used for Client Balancing. You could consider this as a list of AP neighbors.

Client Balancing MR29.1+

Meraki’s MR29.1 improves the algorithm and operation of Client Balancing.

Previously, devices were steered passively. Starting with MR29.1, Meraki access points will steer passively and actively (using 802.11v).

That means at association and post-association to Wi-Fi, steering can occur.

Because devices ultimately decide where they want to join, having a denied association request could place an SSID on a device blocklist which is used to prevent association to a problematic SSID.

MR29.1 will reject a device association twice before accepting the request.

Wireless standards, such as 802.11v, have been around for many years to help improve roaming to nearby access points. Meraki will now implement 802.11v (for 802.11 compatible devices) as a way to transition devices to another access point.

Using a standardized method is a better improvement than proprietary vendor technology. The implementation can be compatible across vendors and device manufacturers.

An example of Client Balancing
Client Balancing example

How Will This Impact You?

Further testing and device support will help us determine if this is a good improvement to Client Balancing.

The number of denied associations should help prevent devices from hanging in limbo and creating a poor Wi-Fi user experience.

Before relying on proprietary vendor technology to steer devices to a more preferred access point, review your Wi-Fi design.

A well planned Wi-Fi design can help mitigate the need for features such as Client Balancing. On the contrary, these features can help mitigate the load with an influx of devices in a high density environment.

But we must remember.. the devices decide which access point they want to associate to.

Do you have 802.11v enabled on your Meraki network? There isn’t a checkbox that specifically states “enable 802.11v”.

A wireless frame capture can identify if 802.11v, BSS Transition, is enabled as seen in the screenshot below.

BSS Transition enabled

Client Balancing can be enabled per RF Profile. Test Client Balancing out on a smaller scale before rolling it out to every environment.

Previous Article


Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.


[gravityforms id=16 title=false description=false]
<script type="text/javascript">var gform;gform||(document.addEventListener("gform_main_scripts_loaded",function(){gform.scriptsLoaded=!0}),window.addEventListener("DOMContentLoaded",function(){gform.domLoaded=!0}),gform={domLoaded:!1,scriptsLoaded:!1,initializeOnLoaded:function(o){gform.domLoaded&&gform.scriptsLoaded?o():!gform.domLoaded&&gform.scriptsLoaded?window.addEventListener("DOMContentLoaded",o):document.addEventListener("gform_main_scripts_loaded",o)},hooks:{action:{},filter:{}},addAction:function(o,n,r,t){gform.addHook("action",o,n,r,t)},addFilter:function(o,n,r,t){gform.addHook("filter",o,n,r,t)},doAction:function(o){gform.doHook("action",o,arguments)},applyFilters:function(o){return gform.doHook("filter",o,arguments)},removeAction:function(o,n){gform.removeHook("action",o,n)},removeFilter:function(o,n,r){gform.removeHook("filter",o,n,r)},addHook:function(o,n,r,t,i){null==gform.hooks[o][n]&&(gform.hooks[o][n]=[]);var e=gform.hooks[o][n];null==i&&(i=n+"_"+e.length),gform.hooks[o][n].push({tag:i,callable:r,priority:t=null==t?10:t})},doHook:function(n,o,r){var t;if(r=Array.prototype.slice.call(r,1),null!=gform.hooks[n][o]&&((o=gform.hooks[n][o]).sort(function(o,n){return o.priority-n.priority}),o.forEach(function(o){"function"!=typeof(t=o.callable)&&(t=window[t]),"action"==n?t.apply(null,r):r[0]=t.apply(null,r)})),"filter"==n)return r[0]},removeHook:function(o,n,t,i){var r;null!=gform.hooks[o][n]&&(r=(r=gform.hooks[o][n]).filter(function(o,n,r){return!!(null!=i&&i!=o.tag||null!=t&&t!=o.priority)}),gform.hooks[o][n]=r)}});</script> <div class='gf_browser_chrome gform_wrapper gravity-theme' id='gform_wrapper_16' ><form method='post' enctype='multipart/form-data' id='gform_16' action='/updates-meraki-client-balancing/' > <div class='gform_body gform-body'><div id='gform_fields_16' class='gform_fields top_label form_sublabel_below description_below'><fieldset id="field_16_1" class="gfield gfield_contains_required field_sublabel_below field_description_below gfield_visibility_visible" data-js-reload="field_16_1"><legend class='gfield_label gfield_label_before_complex' >Name<span class="gfield_required"><span class="gfield_required gfield_required_text">(Required)</span></span></legend><div class='ginput_complex ginput_container no_prefix has_first_name no_middle_name no_last_name no_suffix gf_name_has_1 ginput_container_name' id='input_16_1'> <span id='input_16_1_3_container' class='name_first' > <input type='text' name='input_1.3' id='input_16_1_3' value='' aria-required='true' placeholder='First Name' /> <label for='input_16_1_3' >First</label> </span> </div></fieldset><div id="field_16_2" class="gfield gfield--width-full gfield_contains_required field_sublabel_below field_description_below gfield_visibility_visible" data-js-reload="field_16_2"><label class='gfield_label' for='input_16_2' >Email<span class="gfield_required"><span class="gfield_required gfield_required_text">(Required)</span></span></label><div class='ginput_container ginput_container_email'> <input name='input_2' id='input_16_2' type='text' value='' class='large' placeholder='Business email address' aria-required="true" aria-invalid="false" /> </div></div><fieldset id="field_16_3" class="gfield gfield_contains_required field_sublabel_below field_description_below gfield_visibility_visible" data-js-reload="field_16_3"><legend class='gfield_label gfield_label_before_complex' >Consent<span class="gfield_required"><span class="gfield_required gfield_required_text">(Required)</span></span></legend><div class='ginput_container ginput_container_checkbox'><div class='gfield_checkbox' id='input_16_3'><div class='gchoice gchoice_16_3_1'> <input class='gfield-choice-input' name='input_3.1' type='checkbox' value='I consent to the processing and sharing with partners of the personal data that I provide Packet 6 for this activity in accordance with and as described in the &lt;a href=&quot;https://packet6.com/privacy-policy&quot; target=&quot;_new&quot;&gt;Privacy Policy&lt;/a&gt;' id='choice_16_3_1' /> <label for='choice_16_3_1' id='label_16_3_1'>I consent to the processing and sharing with partners of the personal data that I provide Packet 6 for this activity in accordance with and as described in the <a href="https://packet6.com/privacy-policy" target="_new">Privacy Policy</a></label> </div></div></div></fieldset><div id="field_16_4" class="gfield gform_validation_container field_sublabel_below field_description_below gfield_visibility_visible" data-js-reload="field_16_4"><label class='gfield_label' for='input_16_4' >Phone</label><div class='ginput_container'><input name='input_4' id='input_16_4' type='text' value='' /></div><div class='gfield_description' id='gfield_description_16_4'>This field is for validation purposes and should be left unchanged.</div></div></div></div> <div class='gform_footer top_label'> <input type='submit' id='gform_submit_button_16' class='gform_button button' value='Get the report' onclick='if(window["gf_submitting_16"]){return false;} window["gf_submitting_16"]=true; ' onkeypress='if( event.keyCode == 13 ){ if(window["gf_submitting_16"]){return false;} window["gf_submitting_16"]=true; jQuery("#gform_16").trigger("submit",[true]); }' /> <input type='hidden' class='gform_hidden' name='is_submit_16' value='1' /> <input type='hidden' class='gform_hidden' name='gform_submit' value='16' /> <input type='hidden' class='gform_hidden' name='gform_unique_id' value='' /> <input type='hidden' class='gform_hidden' name='state_16' value='WyJbXSIsImY4MGVlNTA5MGVjMWYzYzU5NzUyOGFhOWE3ZGFiMzRlIl0=' /> <input type='hidden' class='gform_hidden' name='gform_target_page_number_16' id='gform_target_page_number_16' value='0' /> <input type='hidden' class='gform_hidden' name='gform_source_page_number_16' id='gform_source_page_number_16' value='1' /> <input type='hidden' name='gform_field_values' value='' /> </div> <p style="display: none !important;"><label>&#916;<textarea name="ak_hp_textarea" cols="45" rows="8" maxlength="100"></textarea></label><input type="hidden" id="ak_js_2" name="ak_js" value="230"/><script>document.getElementById( "ak_js_2" ).setAttribute( "value", ( new Date() ).getTime() );</script></p></form> </div>