| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097 |
- /******************************************************************************
- *
- * Copyright(c) 2007 - 2017 Realtek Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- *****************************************************************************/
- #define _RTW_MESH_C_
- #ifdef CONFIG_RTW_MESH
- #include <drv_types.h>
- const char *_rtw_mesh_plink_str[] = {
- "UNKNOWN",
- "LISTEN",
- "OPN_SNT",
- "OPN_RCVD",
- "CNF_RCVD",
- "ESTAB",
- "HOLDING",
- "BLOCKED",
- };
- const char *_rtw_mesh_ps_str[] = {
- "UNKNOWN",
- "ACTIVE",
- "LSLEEP",
- "DSLEEP",
- };
- const char *_action_self_protected_str[] = {
- "ACT_SELF_PROTECTED_RSVD",
- "MESH_OPEN",
- "MESH_CONF",
- "MESH_CLOSE",
- "MESH_GK_INFORM",
- "MESH_GK_ACK",
- };
- inline u8 *rtw_set_ie_mesh_id(u8 *buf, u32 *buf_len, const char *mesh_id, u8 id_len)
- {
- return rtw_set_ie(buf, WLAN_EID_MESH_ID, id_len, mesh_id, buf_len);
- }
- inline u8 *rtw_set_ie_mesh_config(u8 *buf, u32 *buf_len
- , u8 path_sel_proto, u8 path_sel_metric, u8 congest_ctl_mode, u8 sync_method, u8 auth_proto
- , u8 num_of_peerings, bool cto_mgate, bool cto_as
- , bool accept_peerings, bool mcca_sup, bool mcca_en, bool forwarding
- , bool mbca_en, bool tbtt_adj, bool ps_level)
- {
- u8 conf[7] = {0};
- SET_MESH_CONF_ELE_PATH_SEL_PROTO_ID(conf, path_sel_proto);
- SET_MESH_CONF_ELE_PATH_SEL_METRIC_ID(conf, path_sel_metric);
- SET_MESH_CONF_ELE_CONGEST_CTRL_MODE_ID(conf, congest_ctl_mode);
- SET_MESH_CONF_ELE_SYNC_METHOD_ID(conf, sync_method);
- SET_MESH_CONF_ELE_AUTH_PROTO_ID(conf, auth_proto);
- SET_MESH_CONF_ELE_CTO_MGATE(conf, cto_mgate);
- SET_MESH_CONF_ELE_NUM_OF_PEERINGS(conf, num_of_peerings);
- SET_MESH_CONF_ELE_CTO_AS(conf, cto_as);
- SET_MESH_CONF_ELE_ACCEPT_PEERINGS(conf, accept_peerings);
- SET_MESH_CONF_ELE_MCCA_SUP(conf, mcca_sup);
- SET_MESH_CONF_ELE_MCCA_EN(conf, mcca_en);
- SET_MESH_CONF_ELE_FORWARDING(conf, forwarding);
- SET_MESH_CONF_ELE_MBCA_EN(conf, mbca_en);
- SET_MESH_CONF_ELE_TBTT_ADJ(conf, tbtt_adj);
- SET_MESH_CONF_ELE_PS_LEVEL(conf, ps_level);
- return rtw_set_ie(buf, WLAN_EID_MESH_CONFIG, 7, conf, buf_len);
- }
- inline u8 *rtw_set_ie_mpm(u8 *buf, u32 *buf_len
- , u8 proto_id, u16 llid, u16 *plid, u16 *reason, u8 *chosen_pmk)
- {
- u8 data[24] = {0};
- u8 *pos = data;
- RTW_PUT_LE16(pos, proto_id);
- pos += 2;
- RTW_PUT_LE16(pos, llid);
- pos += 2;
- if (plid) {
- RTW_PUT_LE16(pos, *plid);
- pos += 2;
- }
- if (reason) {
- RTW_PUT_LE16(pos, *reason);
- pos += 2;
- }
- if (chosen_pmk) {
- _rtw_memcpy(pos, chosen_pmk, 16);
- pos += 16;
- }
- return rtw_set_ie(buf, WLAN_EID_MPM, pos - data, data, buf_len);
- }
- bool rtw_bss_is_forwarding(WLAN_BSSID_EX *bss)
- {
- u8 *ie;
- int ie_len;
- bool ret = 0;
- ie = rtw_get_ie(BSS_EX_TLV_IES(bss), WLAN_EID_MESH_CONFIG, &ie_len,
- BSS_EX_TLV_IES_LEN(bss));
- if (!ie || ie_len != 7)
- goto exit;
- ret = GET_MESH_CONF_ELE_FORWARDING(ie + 2);
- exit:
- return ret;
- }
- bool rtw_bss_is_cto_mgate(WLAN_BSSID_EX *bss)
- {
- u8 *ie;
- int ie_len;
- bool ret = 0;
- ie = rtw_get_ie(BSS_EX_TLV_IES(bss), WLAN_EID_MESH_CONFIG, &ie_len,
- BSS_EX_TLV_IES_LEN(bss));
- if (!ie || ie_len != 7)
- goto exit;
- ret = GET_MESH_CONF_ELE_CTO_MGATE(ie + 2);
- exit:
- return ret;
- }
- int rtw_bss_is_same_mbss(WLAN_BSSID_EX *a, WLAN_BSSID_EX *b)
- {
- int ret = 0;
- u8 *a_mconf_ie, *b_mconf_ie;
- sint a_mconf_ie_len, b_mconf_ie_len;
- if (a->InfrastructureMode != Ndis802_11_mesh)
- goto exit;
- a_mconf_ie = rtw_get_ie(BSS_EX_TLV_IES(a), WLAN_EID_MESH_CONFIG, &a_mconf_ie_len, BSS_EX_TLV_IES_LEN(a));
- if (!a_mconf_ie || a_mconf_ie_len != 7)
- goto exit;
- if (b->InfrastructureMode != Ndis802_11_mesh)
- goto exit;
- b_mconf_ie = rtw_get_ie(BSS_EX_TLV_IES(b), WLAN_EID_MESH_CONFIG, &b_mconf_ie_len, BSS_EX_TLV_IES_LEN(b));
- if (!b_mconf_ie || b_mconf_ie_len != 7)
- goto exit;
- if (a->mesh_id.SsidLength != b->mesh_id.SsidLength
- || _rtw_memcmp(a->mesh_id.Ssid, b->mesh_id.Ssid, a->mesh_id.SsidLength) == _FALSE)
- goto exit;
- if (_rtw_memcmp(a_mconf_ie + 2, b_mconf_ie + 2, 5) == _FALSE)
- goto exit;
- ret = 1;
- exit:
- return ret;
- }
- int rtw_bss_is_candidate_mesh_peer(WLAN_BSSID_EX *self, WLAN_BSSID_EX *target, u8 ch, u8 add_peer)
- {
- int ret = 0;
- u8 *mconf_ie;
- sint mconf_ie_len;
- int i, j;
- if (!rtw_bss_is_same_mbss(self, target))
- goto exit;
- if (ch && self->Configuration.DSConfig != target->Configuration.DSConfig)
- goto exit;
- if (add_peer) {
- /* Accept additional mesh peerings */
- mconf_ie = rtw_get_ie(BSS_EX_TLV_IES(target), WLAN_EID_MESH_CONFIG, &mconf_ie_len, BSS_EX_TLV_IES_LEN(target));
- if (!mconf_ie || mconf_ie_len != 7)
- goto exit;
- if (GET_MESH_CONF_ELE_ACCEPT_PEERINGS(mconf_ie + 2) == 0)
- goto exit;
- }
- /* BSSBasicRateSet */
- for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
- if (target->SupportedRates[i] == 0)
- break;
- if (target->SupportedRates[i] & 0x80) {
- u8 match = 0;
- if (!ch) {
- /* off-channel, check target with our hardcode capability */
- if (target->Configuration.DSConfig > 14)
- match = rtw_is_basic_rate_ofdm(target->SupportedRates[i]);
- else
- match = rtw_is_basic_rate_mix(target->SupportedRates[i]);
- } else {
- for (j = 0; j < NDIS_802_11_LENGTH_RATES_EX; j++) {
- if (self->SupportedRates[j] == 0)
- break;
- if (self->SupportedRates[j] == target->SupportedRates[i]) {
- match = 1;
- break;
- }
- }
- }
- if (!match)
- goto exit;
- }
- }
- /* BSSBasicMCSSet */
- /* 802.1X connected to AS ? */
- ret = 1;
- exit:
- return ret;
- }
- void rtw_mesh_bss_peering_status(WLAN_BSSID_EX *bss, u8 *nop, u8 *accept)
- {
- u8 *ie;
- int ie_len;
- if (nop)
- *nop = 0;
- if (accept)
- *accept = 0;
- ie = rtw_get_ie(BSS_EX_TLV_IES(bss), WLAN_EID_MESH_CONFIG, &ie_len,
- BSS_EX_TLV_IES_LEN(bss));
- if (!ie || ie_len != 7)
- goto exit;
- if (nop)
- *nop = GET_MESH_CONF_ELE_NUM_OF_PEERINGS(ie + 2);
- if (accept)
- *accept = GET_MESH_CONF_ELE_ACCEPT_PEERINGS(ie + 2);
- exit:
- return;
- }
- #if CONFIG_RTW_MESH_ACNODE_PREVENT
- void rtw_mesh_update_scanned_acnode_status(_adapter *adapter, struct wlan_network *scanned)
- {
- bool acnode;
- u8 nop, accept;
- rtw_mesh_bss_peering_status(&scanned->network, &nop, &accept);
- acnode = !nop && accept;
- if (acnode && scanned->acnode_stime == 0) {
- scanned->acnode_stime = rtw_get_current_time();
- if (scanned->acnode_stime == 0)
- scanned->acnode_stime++;
- } else if (!acnode) {
- scanned->acnode_stime = 0;
- scanned->acnode_notify_etime = 0;
- }
- }
- bool rtw_mesh_scanned_is_acnode_confirmed(_adapter *adapter, struct wlan_network *scanned)
- {
- return scanned->acnode_stime
- && rtw_get_passing_time_ms(scanned->acnode_stime)
- > adapter->mesh_cfg.peer_sel_policy.acnode_conf_timeout_ms;
- }
- static bool rtw_mesh_scanned_is_acnode_allow_notify(_adapter *adapter, struct wlan_network *scanned)
- {
- return scanned->acnode_notify_etime
- && rtw_time_after(scanned->acnode_notify_etime, rtw_get_current_time());
- }
- bool rtw_mesh_acnode_prevent_allow_sacrifice(_adapter *adapter)
- {
- struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
- struct sta_priv *stapriv = &adapter->stapriv;
- bool allow = 0;
- if (!mcfg->peer_sel_policy.acnode_prevent
- || mcfg->max_peer_links <= 1
- || stapriv->asoc_list_cnt < mcfg->max_peer_links)
- goto exit;
- #if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
- if (rtw_mesh_cto_mgate_required(adapter))
- goto exit;
- #endif
- allow = 1;
- exit:
- return allow;
- }
- static bool rtw_mesh_acnode_candidate_exist(_adapter *adapter)
- {
- struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
- struct sta_priv *stapriv = &adapter->stapriv;
- struct mlme_priv *mlme = &adapter->mlmepriv;
- _queue *queue = &(mlme->scanned_queue);
- _list *head, *list;
- _irqL irqL;
- struct wlan_network *scanned = NULL;
- struct sta_info *sta = NULL;
- bool need = 0;
- _enter_critical_bh(&(mlme->scanned_queue.lock), &irqL);
- head = get_list_head(queue);
- list = get_next(head);
- while (!rtw_end_of_queue_search(head, list)) {
- scanned = LIST_CONTAINOR(list, struct wlan_network, list);
- list = get_next(list);
- if (rtw_get_passing_time_ms(scanned->last_scanned) < mcfg->peer_sel_policy.scanr_exp_ms
- && rtw_mesh_scanned_is_acnode_confirmed(adapter, scanned)
- && (!mcfg->rssi_threshold || mcfg->rssi_threshold <= scanned->network.Rssi)
- #if CONFIG_RTW_MACADDR_ACL
- && rtw_access_ctrl(adapter, scanned->network.MacAddress) == _TRUE
- #endif
- && rtw_bss_is_candidate_mesh_peer(&mlme->cur_network.network, &scanned->network, 1, 1)
- #if CONFIG_RTW_MESH_PEER_BLACKLIST
- && !rtw_mesh_peer_blacklist_search(adapter, scanned->network.MacAddress)
- #endif
- #if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
- && rtw_mesh_cto_mgate_network_filter(adapter, scanned)
- #endif
- ) {
- need = 1;
- break;
- }
- }
- _exit_critical_bh(&(mlme->scanned_queue.lock), &irqL);
- exit:
- return need;
- }
- static int rtw_mesh_acnode_prevent_sacrifice_chk(_adapter *adapter, struct sta_info **sac, struct sta_info *com)
- {
- struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
- int updated = 0;
- /*
- * TODO: compare next_hop reference cnt of forwarding info
- * don't sacrifice working next_hop or choose sta with least cnt
- */
- if (*sac == NULL) {
- updated = 1;
- goto exit;
- }
- #if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
- if (mcfg->peer_sel_policy.cto_mgate_require
- && !mcfg->dot11MeshGateAnnouncementProtocol
- ) {
- if (IS_CTO_MGATE_CONF_TIMEOUT(com->plink)) {
- if (!IS_CTO_MGATE_CONF_TIMEOUT((*sac)->plink)) {
- /* blacklist > not blacklist */
- updated = 1;
- goto exit;
- }
- } else if (!IS_CTO_MGATE_CONF_DISABLED(com->plink)) {
- if (IS_CTO_MGATE_CONF_DISABLED((*sac)->plink)) {
- /* confirming > disabled */
- updated = 1;
- goto exit;
- }
- }
- }
- #endif
- exit:
- if (updated)
- *sac = com;
- return updated;
- }
- struct sta_info *_rtw_mesh_acnode_prevent_pick_sacrifice(_adapter *adapter)
- {
- struct sta_priv *stapriv = &adapter->stapriv;
- _list *head, *list;
- struct sta_info *sta, *sacrifice = NULL;
- u8 nop;
- head = &stapriv->asoc_list;
- list = get_next(head);
- while (rtw_end_of_queue_search(head, list) == _FALSE) {
- sta = LIST_CONTAINOR(list, struct sta_info, asoc_list);
- list = get_next(list);
- if (!sta->plink || !sta->plink->scanned) {
- rtw_warn_on(1);
- continue;
- }
- rtw_mesh_bss_peering_status(&sta->plink->scanned->network, &nop, NULL);
- if (nop < 2)
- continue;
- rtw_mesh_acnode_prevent_sacrifice_chk(adapter, &sacrifice, sta);
- }
- return sacrifice;
- }
- struct sta_info *rtw_mesh_acnode_prevent_pick_sacrifice(_adapter *adapter)
- {
- struct sta_priv *stapriv = &adapter->stapriv;
- struct sta_info *sacrifice = NULL;
- enter_critical_bh(&stapriv->asoc_list_lock);
- sacrifice = _rtw_mesh_acnode_prevent_pick_sacrifice(adapter);
- exit_critical_bh(&stapriv->asoc_list_lock);
- return sacrifice;
- }
- static void rtw_mesh_acnode_rsvd_chk(_adapter *adapter)
- {
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
- u8 acnode_rsvd = 0;
- if (rtw_mesh_acnode_prevent_allow_sacrifice(adapter)
- && rtw_mesh_acnode_prevent_pick_sacrifice(adapter)
- && rtw_mesh_acnode_candidate_exist(adapter))
- acnode_rsvd = 1;
- if (plink_ctl->acnode_rsvd != acnode_rsvd) {
- plink_ctl->acnode_rsvd = acnode_rsvd;
- RTW_INFO(FUNC_ADPT_FMT" acnode_rsvd = %d\n", FUNC_ADPT_ARG(adapter), plink_ctl->acnode_rsvd);
- update_beacon(adapter, WLAN_EID_MESH_CONFIG, NULL, 1);
- }
- }
- static void rtw_mesh_acnode_set_notify_etime(_adapter *adapter, u8 *rframe_whdr)
- {
- if (adapter->mesh_info.plink_ctl.acnode_rsvd) {
- struct wlan_network *scanned = rtw_find_network(&adapter->mlmepriv.scanned_queue, get_addr2_ptr(rframe_whdr));
- if (rtw_mesh_scanned_is_acnode_confirmed(adapter, scanned)) {
- scanned->acnode_notify_etime = rtw_get_current_time()
- + rtw_ms_to_systime(adapter->mesh_cfg.peer_sel_policy.acnode_notify_timeout_ms);
- if (scanned->acnode_notify_etime == 0)
- scanned->acnode_notify_etime++;
- }
- }
- }
- void dump_mesh_acnode_prevent_settings(void *sel, _adapter *adapter)
- {
- struct mesh_peer_sel_policy *peer_sel_policy = &adapter->mesh_cfg.peer_sel_policy;
- RTW_PRINT_SEL(sel, "%-6s %-12s %-14s\n"
- , "enable", "conf_timeout", "nofity_timeout");
- RTW_PRINT_SEL(sel, "%6u %12u %14u\n"
- , peer_sel_policy->acnode_prevent
- , peer_sel_policy->acnode_conf_timeout_ms
- , peer_sel_policy->acnode_notify_timeout_ms);
- }
- #endif /* CONFIG_RTW_MESH_ACNODE_PREVENT */
- #if CONFIG_RTW_MESH_PEER_BLACKLIST
- int rtw_mesh_peer_blacklist_add(_adapter *adapter, const u8 *addr)
- {
- struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
- return rtw_blacklist_add(&plink_ctl->peer_blacklist, addr
- , mcfg->peer_sel_policy.peer_blacklist_timeout_ms);
- }
- int rtw_mesh_peer_blacklist_del(_adapter *adapter, const u8 *addr)
- {
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
- return rtw_blacklist_del(&plink_ctl->peer_blacklist, addr);
- }
- int rtw_mesh_peer_blacklist_search(_adapter *adapter, const u8 *addr)
- {
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
- return rtw_blacklist_search(&plink_ctl->peer_blacklist, addr);
- }
- void rtw_mesh_peer_blacklist_flush(_adapter *adapter)
- {
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
- rtw_blacklist_flush(&plink_ctl->peer_blacklist);
- }
- void dump_mesh_peer_blacklist(void *sel, _adapter *adapter)
- {
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
- dump_blacklist(sel, &plink_ctl->peer_blacklist, "blacklist");
- }
- void dump_mesh_peer_blacklist_settings(void *sel, _adapter *adapter)
- {
- struct mesh_peer_sel_policy *peer_sel_policy = &adapter->mesh_cfg.peer_sel_policy;
- RTW_PRINT_SEL(sel, "%-12s %-17s\n"
- , "conf_timeout", "blacklist_timeout");
- RTW_PRINT_SEL(sel, "%12u %17u\n"
- , peer_sel_policy->peer_conf_timeout_ms
- , peer_sel_policy->peer_blacklist_timeout_ms);
- }
- #endif /* CONFIG_RTW_MESH_PEER_BLACKLIST */
- #if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
- u8 rtw_mesh_cto_mgate_required(_adapter *adapter)
- {
- struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
- struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
- return mcfg->peer_sel_policy.cto_mgate_require
- && !rtw_bss_is_cto_mgate(&(mlmeext->mlmext_info.network));
- }
- u8 rtw_mesh_cto_mgate_network_filter(_adapter *adapter, struct wlan_network *scanned)
- {
- struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
- struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
- return !rtw_mesh_cto_mgate_required(adapter)
- || (rtw_bss_is_cto_mgate(&scanned->network)
- && !rtw_mesh_cto_mgate_blacklist_search(adapter, scanned->network.MacAddress));
- }
- int rtw_mesh_cto_mgate_blacklist_add(_adapter *adapter, const u8 *addr)
- {
- struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
- return rtw_blacklist_add(&plink_ctl->cto_mgate_blacklist, addr
- , mcfg->peer_sel_policy.cto_mgate_blacklist_timeout_ms);
- }
- int rtw_mesh_cto_mgate_blacklist_del(_adapter *adapter, const u8 *addr)
- {
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
- return rtw_blacklist_del(&plink_ctl->cto_mgate_blacklist, addr);
- }
- int rtw_mesh_cto_mgate_blacklist_search(_adapter *adapter, const u8 *addr)
- {
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
- return rtw_blacklist_search(&plink_ctl->cto_mgate_blacklist, addr);
- }
- void rtw_mesh_cto_mgate_blacklist_flush(_adapter *adapter)
- {
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
- rtw_blacklist_flush(&plink_ctl->cto_mgate_blacklist);
- }
- void dump_mesh_cto_mgate_blacklist(void *sel, _adapter *adapter)
- {
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
- dump_blacklist(sel, &plink_ctl->cto_mgate_blacklist, "blacklist");
- }
- void dump_mesh_cto_mgate_blacklist_settings(void *sel, _adapter *adapter)
- {
- struct mesh_peer_sel_policy *peer_sel_policy = &adapter->mesh_cfg.peer_sel_policy;
- RTW_PRINT_SEL(sel, "%-12s %-17s\n"
- , "conf_timeout", "blacklist_timeout");
- RTW_PRINT_SEL(sel, "%12u %17u\n"
- , peer_sel_policy->cto_mgate_conf_timeout_ms
- , peer_sel_policy->cto_mgate_blacklist_timeout_ms);
- }
- static void rtw_mesh_cto_mgate_blacklist_chk(_adapter *adapter)
- {
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
- _queue *blist = &plink_ctl->cto_mgate_blacklist;
- _list *list, *head;
- struct blacklist_ent *ent = NULL;
- struct wlan_network *scanned = NULL;
- enter_critical_bh(&blist->lock);
- head = &blist->queue;
- list = get_next(head);
- while (rtw_end_of_queue_search(head, list) == _FALSE) {
- ent = LIST_CONTAINOR(list, struct blacklist_ent, list);
- list = get_next(list);
- if (rtw_time_after(rtw_get_current_time(), ent->exp_time)) {
- rtw_list_delete(&ent->list);
- rtw_mfree(ent, sizeof(struct blacklist_ent));
- continue;
- }
- scanned = rtw_find_network(&adapter->mlmepriv.scanned_queue, ent->addr);
- if (!scanned)
- continue;
- if (rtw_bss_is_forwarding(&scanned->network)) {
- rtw_list_delete(&ent->list);
- rtw_mfree(ent, sizeof(struct blacklist_ent));
- }
- }
- exit_critical_bh(&blist->lock);
- }
- #endif /* CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST */
- void rtw_chk_candidate_peer_notify(_adapter *adapter, struct wlan_network *scanned)
- {
- struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
- struct mlme_priv *mlme = &adapter->mlmepriv;
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
- struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
- bool acnode = 0;
- if (IS_CH_WAITING(rfctl) && !IS_UNDER_CAC(rfctl))
- goto exit;
- if (plink_ctl->num >= RTW_MESH_MAX_PEER_CANDIDATES)
- goto exit;
- #if CONFIG_RTW_MESH_ACNODE_PREVENT
- if (plink_ctl->acnode_rsvd) {
- acnode = rtw_mesh_scanned_is_acnode_confirmed(adapter, scanned);
- if (acnode && !rtw_mesh_scanned_is_acnode_allow_notify(adapter, scanned))
- goto exit;
- }
- #endif
- /* wpa_supplicant's auto peer will initiate peering when candidate peer is reported without max_peer_links consideration */
- if (plink_ctl->num >= mcfg->max_peer_links + acnode ? 1 : 0)
- goto exit;
- if (rtw_get_passing_time_ms(scanned->last_scanned) >= mcfg->peer_sel_policy.scanr_exp_ms
- || (mcfg->rssi_threshold && mcfg->rssi_threshold > scanned->network.Rssi)
- || !rtw_bss_is_candidate_mesh_peer(&mlme->cur_network.network, &scanned->network, 1, 1)
- #if CONFIG_RTW_MACADDR_ACL
- || rtw_access_ctrl(adapter, scanned->network.MacAddress) == _FALSE
- #endif
- || rtw_mesh_plink_get(adapter, scanned->network.MacAddress)
- #if CONFIG_RTW_MESH_PEER_BLACKLIST
- || rtw_mesh_peer_blacklist_search(adapter, scanned->network.MacAddress)
- #endif
- #if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
- || !rtw_mesh_cto_mgate_network_filter(adapter, scanned)
- #endif
- )
- goto exit;
- #if CONFIG_RTW_MESH_ACNODE_PREVENT
- if (acnode) {
- scanned->acnode_notify_etime = 0;
- RTW_INFO(FUNC_ADPT_FMT" acnode "MAC_FMT"\n"
- , FUNC_ADPT_ARG(adapter), MAC_ARG(scanned->network.MacAddress));
- }
- #endif
- #ifdef CONFIG_IOCTL_CFG80211
- rtw_cfg80211_notify_new_peer_candidate(adapter->rtw_wdev
- , scanned->network.MacAddress
- , BSS_EX_TLV_IES(&scanned->network)
- , BSS_EX_TLV_IES_LEN(&scanned->network)
- , GFP_ATOMIC
- );
- #endif
- exit:
- return;
- }
- void rtw_mesh_peer_status_chk(_adapter *adapter)
- {
- struct mlme_priv *mlme = &adapter->mlmepriv;
- struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
- struct mesh_plink_ent *plink;
- _list *head, *list;
- struct sta_info *sta = NULL;
- struct sta_priv *stapriv = &adapter->stapriv;
- int stainfo_offset;
- #if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
- u8 cto_mgate, forwarding, mgate;
- #endif
- u8 flush;
- s8 flush_list[NUM_STA];
- u8 flush_num = 0;
- int i;
- #if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
- if (rtw_mesh_cto_mgate_required(adapter)) {
- /* active scan on operating channel */
- issue_probereq_ex(adapter, &adapter->mlmepriv.cur_network.network.mesh_id, NULL, 0, 0, 0, 0);
- }
- #endif
- enter_critical_bh(&(plink_ctl->lock));
- /* check established peers */
- enter_critical_bh(&stapriv->asoc_list_lock);
- head = &stapriv->asoc_list;
- list = get_next(head);
- while (rtw_end_of_queue_search(head, list) == _FALSE) {
- sta = LIST_CONTAINOR(list, struct sta_info, asoc_list);
- list = get_next(list);
- if (!sta->plink || !sta->plink->scanned) {
- rtw_warn_on(1);
- continue;
- }
- plink = sta->plink;
- flush = 0;
- /* remove unsuitable peer */
- if (!rtw_bss_is_candidate_mesh_peer(&mlme->cur_network.network, &plink->scanned->network, 1, 0)
- #if CONFIG_RTW_MACADDR_ACL
- || rtw_access_ctrl(adapter, plink->addr) == _FALSE
- #endif
- ) {
- flush = 1;
- goto flush_add;
- }
- #if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
- cto_mgate = rtw_bss_is_cto_mgate(&(plink->scanned->network));
- forwarding = rtw_bss_is_forwarding(&(plink->scanned->network));
- mgate = rtw_mesh_gate_search(minfo->mesh_paths, sta->cmn.mac_addr);
- /* CTO_MGATE required, remove peer without CTO_MGATE */
- if (rtw_mesh_cto_mgate_required(adapter) && !cto_mgate) {
- flush = 1;
- goto flush_add;
- }
- /* cto_mgate_conf status update */
- if (IS_CTO_MGATE_CONF_DISABLED(plink)) {
- if (cto_mgate && !forwarding && !mgate)
- SET_CTO_MGATE_CONF_END_TIME(plink, mcfg->peer_sel_policy.cto_mgate_conf_timeout_ms);
- else
- rtw_mesh_cto_mgate_blacklist_del(adapter, sta->cmn.mac_addr);
- } else {
- /* cto_mgate_conf ongoing */
- if (cto_mgate && !forwarding && !mgate) {
- if (IS_CTO_MGATE_CONF_TIMEOUT(plink)) {
- rtw_mesh_cto_mgate_blacklist_add(adapter, sta->cmn.mac_addr);
- /* CTO_MGATE required, remove peering can't achieve CTO_MGATE */
- if (rtw_mesh_cto_mgate_required(adapter)) {
- flush = 1;
- goto flush_add;
- }
- }
- } else {
- SET_CTO_MGATE_CONF_DISABLED(plink);
- rtw_mesh_cto_mgate_blacklist_del(adapter, sta->cmn.mac_addr);
- }
- }
- #endif /* CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST */
- flush_add:
- if (flush) {
- rtw_list_delete(&sta->asoc_list);
- stapriv->asoc_list_cnt--;
- STA_SET_MESH_PLINK(sta, NULL);
- stainfo_offset = rtw_stainfo_offset(stapriv, sta);
- if (stainfo_offset_valid(stainfo_offset))
- flush_list[flush_num++] = stainfo_offset;
- else
- rtw_warn_on(1);
- }
- }
- exit_critical_bh(&stapriv->asoc_list_lock);
- /* check non-established peers */
- for (i = 0; i < RTW_MESH_MAX_PEER_CANDIDATES; i++) {
- plink = &plink_ctl->ent[i];
- if (plink->valid != _TRUE || plink->plink_state == RTW_MESH_PLINK_ESTAB)
- continue;
- /* remove unsuitable peer */
- if (!rtw_bss_is_candidate_mesh_peer(&mlme->cur_network.network, &plink->scanned->network, 1, 1)
- #if CONFIG_RTW_MACADDR_ACL
- || rtw_access_ctrl(adapter, plink->addr) == _FALSE
- #endif
- ) {
- _rtw_mesh_expire_peer_ent(adapter, plink);
- continue;
- }
- #if CONFIG_RTW_MESH_PEER_BLACKLIST
- /* peer confirm check timeout, add to black list */
- if (IS_PEER_CONF_TIMEOUT(plink)) {
- rtw_mesh_peer_blacklist_add(adapter, plink->addr);
- _rtw_mesh_expire_peer_ent(adapter, plink);
- }
- #endif
- }
- exit_critical_bh(&(plink_ctl->lock));
- if (flush_num) {
- u8 sta_addr[ETH_ALEN];
- u8 updated = _FALSE;
- for (i = 0; i < flush_num; i++) {
- sta = rtw_get_stainfo_by_offset(stapriv, flush_list[i]);
- _rtw_memcpy(sta_addr, sta->cmn.mac_addr, ETH_ALEN);
- updated |= ap_free_sta(adapter, sta, _TRUE, WLAN_REASON_DEAUTH_LEAVING, _FALSE);
- rtw_mesh_expire_peer(adapter, sta_addr);
- }
- associated_clients_update(adapter, updated, STA_INFO_UPDATE_ALL);
- }
- #if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
- /* loop cto_mgate_blacklist to remove ent according to scan_r */
- rtw_mesh_cto_mgate_blacklist_chk(adapter);
- #endif
- #if CONFIG_RTW_MESH_ACNODE_PREVENT
- rtw_mesh_acnode_rsvd_chk(adapter);
- #endif
- return;
- }
- #if CONFIG_RTW_MESH_OFFCH_CAND
- static u8 rtw_mesh_offch_cto_mgate_required(_adapter *adapter)
- {
- #if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
- struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
- struct mlme_priv *mlme = &adapter->mlmepriv;
- _queue *queue = &(mlme->scanned_queue);
- _list *head, *pos;
- struct wlan_network *scanned = NULL;
- u8 ret = 0;
- if (!rtw_mesh_cto_mgate_required(adapter))
- goto exit;
- enter_critical_bh(&(mlme->scanned_queue.lock));
- head = get_list_head(queue);
- pos = get_next(head);
- while (!rtw_end_of_queue_search(head, pos)) {
- scanned = LIST_CONTAINOR(pos, struct wlan_network, list);
- if (rtw_get_passing_time_ms(scanned->last_scanned) < mcfg->peer_sel_policy.scanr_exp_ms
- && (!mcfg->rssi_threshold || mcfg->rssi_threshold <= scanned->network.Rssi)
- #if CONFIG_RTW_MACADDR_ACL
- && rtw_access_ctrl(adapter, scanned->network.MacAddress) == _TRUE
- #endif
- && rtw_bss_is_candidate_mesh_peer(&mlme->cur_network.network, &scanned->network, 1, 1)
- && rtw_bss_is_cto_mgate(&scanned->network)
- #if CONFIG_RTW_MESH_PEER_BLACKLIST
- && !rtw_mesh_peer_blacklist_search(adapter, scanned->network.MacAddress)
- #endif
- && !rtw_mesh_cto_mgate_blacklist_search(adapter, scanned->network.MacAddress)
- )
- break;
- pos = get_next(pos);
- }
- if (rtw_end_of_queue_search(head, pos))
- ret = 1;
- exit_critical_bh(&(mlme->scanned_queue.lock));
- exit:
- return ret;
- #else
- return 0;
- #endif /* CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST */
- }
- u8 rtw_mesh_offch_candidate_accepted(_adapter *adapter)
- {
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
- u8 ret = 0;
- if (!adapter->mesh_cfg.peer_sel_policy.offch_cand)
- goto exit;
- ret = MLME_IS_MESH(adapter) && MLME_IS_ASOC(adapter)
- && (!plink_ctl->num || rtw_mesh_offch_cto_mgate_required(adapter))
- ;
- #ifdef CONFIG_CONCURRENT_MODE
- if (ret) {
- struct mi_state mstate_no_self;
- rtw_mi_status_no_self(adapter, &mstate_no_self);
- if (MSTATE_STA_LD_NUM(&mstate_no_self))
- ret = 0;
- }
- #endif
- exit:
- return ret;
- }
- /*
- * this function is called under off channel candidate is required
- * the channel with maximum candidate count is selected
- */
- u8 rtw_mesh_select_operating_ch(_adapter *adapter)
- {
- struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
- struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
- struct mlme_priv *mlme = &adapter->mlmepriv;
- _queue *queue = &(mlme->scanned_queue);
- _list *head, *pos;
- _irqL irqL;
- struct wlan_network *scanned = NULL;
- int i;
- /* statistics for candidate accept peering */
- u8 cand_ap_cnt[MAX_CHANNEL_NUM] = {0};
- u8 max_cand_ap_ch = 0;
- u8 max_cand_ap_cnt = 0;
- /* statistics for candidate including not accept peering */
- u8 cand_cnt[MAX_CHANNEL_NUM] = {0};
- u8 max_cand_ch = 0;
- u8 max_cand_cnt = 0;
- _enter_critical_bh(&(mlme->scanned_queue.lock), &irqL);
- head = get_list_head(queue);
- pos = get_next(head);
- while (!rtw_end_of_queue_search(head, pos)) {
- scanned = LIST_CONTAINOR(pos, struct wlan_network, list);
- pos = get_next(pos);
- if (rtw_get_passing_time_ms(scanned->last_scanned) < mcfg->peer_sel_policy.scanr_exp_ms
- && (!mcfg->rssi_threshold || mcfg->rssi_threshold <= scanned->network.Rssi)
- #if CONFIG_RTW_MACADDR_ACL
- && rtw_access_ctrl(adapter, scanned->network.MacAddress) == _TRUE
- #endif
- && rtw_bss_is_candidate_mesh_peer(&mlme->cur_network.network, &scanned->network, 0, 0)
- #if CONFIG_RTW_MESH_PEER_BLACKLIST
- && !rtw_mesh_peer_blacklist_search(adapter, scanned->network.MacAddress)
- #endif
- #if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
- && rtw_mesh_cto_mgate_network_filter(adapter, scanned)
- #endif
- ) {
- int ch_set_idx = rtw_chset_search_ch(rfctl->channel_set, scanned->network.Configuration.DSConfig);
- if (ch_set_idx >= 0
- && !CH_IS_NON_OCP(&rfctl->channel_set[ch_set_idx])
- ) {
- u8 nop, accept;
- rtw_mesh_bss_peering_status(&scanned->network, &nop, &accept);
- cand_cnt[ch_set_idx]++;
- if (max_cand_cnt < cand_cnt[ch_set_idx]) {
- max_cand_cnt = cand_cnt[ch_set_idx];
- max_cand_ch = rfctl->channel_set[ch_set_idx].ChannelNum;
- }
- if (accept) {
- cand_ap_cnt[ch_set_idx]++;
- if (max_cand_ap_cnt < cand_ap_cnt[ch_set_idx]) {
- max_cand_ap_cnt = cand_ap_cnt[ch_set_idx];
- max_cand_ap_ch = rfctl->channel_set[ch_set_idx].ChannelNum;
- }
- }
- }
- }
- }
- _exit_critical_bh(&(mlme->scanned_queue.lock), &irqL);
- return max_cand_ap_ch ? max_cand_ap_ch : max_cand_ch;
- }
- void dump_mesh_offch_cand_settings(void *sel, _adapter *adapter)
- {
- struct mesh_peer_sel_policy *peer_sel_policy = &adapter->mesh_cfg.peer_sel_policy;
- RTW_PRINT_SEL(sel, "%-6s %-11s\n"
- , "enable", "find_int_ms");
- RTW_PRINT_SEL(sel, "%6u %11u\n"
- , peer_sel_policy->offch_cand, peer_sel_policy->offch_find_int_ms);
- }
- #endif /* CONFIG_RTW_MESH_OFFCH_CAND */
- void dump_mesh_peer_sel_policy(void *sel, _adapter *adapter)
- {
- struct mesh_peer_sel_policy *peer_sel_policy = &adapter->mesh_cfg.peer_sel_policy;
- RTW_PRINT_SEL(sel, "%-12s\n", "scanr_exp_ms");
- RTW_PRINT_SEL(sel, "%12u\n", peer_sel_policy->scanr_exp_ms);
- }
- void dump_mesh_networks(void *sel, _adapter *adapter)
- {
- #if CONFIG_RTW_MESH_ACNODE_PREVENT
- #define NSTATE_TITLE_FMT_ACN " %-5s"
- #define NSTATE_VALUE_FMT_ACN " %5d"
- #define NSTATE_TITLE_ARG_ACN , "acn"
- #define NSTATE_VALUE_ARG_ACN , (acn_ms < 99999 ? acn_ms : 99999)
- #else
- #define NSTATE_TITLE_FMT_ACN ""
- #define NSTATE_VALUE_FMT_ACN ""
- #define NSTATE_TITLE_ARG_ACN
- #define NSTATE_VALUE_ARG_ACN
- #endif
- struct mlme_priv *mlme = &(adapter->mlmepriv);
- _queue *queue = &(mlme->scanned_queue);
- struct wlan_network *network;
- _list *list, *head;
- u8 same_mbss;
- u8 candidate;
- struct mesh_plink_ent *plink;
- u8 blocked;
- u8 established;
- s32 age_ms;
- #if CONFIG_RTW_MESH_ACNODE_PREVENT
- s32 acn_ms;
- #endif
- u8 *mesh_conf_ie;
- sint mesh_conf_ie_len;
- struct wlan_network **mesh_networks;
- u8 mesh_network_cnt = 0;
- int i;
- mesh_networks = rtw_zvmalloc(mlme->max_bss_cnt * sizeof(struct wlan_network *));
- if (!mesh_networks)
- return;
- enter_critical_bh(&queue->lock);
- head = get_list_head(queue);
- list = get_next(head);
- while (rtw_end_of_queue_search(head, list) == _FALSE) {
- network = LIST_CONTAINOR(list, struct wlan_network, list);
- list = get_next(list);
- if (network->network.InfrastructureMode != Ndis802_11_mesh)
- continue;
- mesh_conf_ie = rtw_get_ie(BSS_EX_TLV_IES(&network->network), WLAN_EID_MESH_CONFIG
- , &mesh_conf_ie_len, BSS_EX_TLV_IES_LEN(&network->network));
- if (!mesh_conf_ie || mesh_conf_ie_len != 7)
- continue;
- mesh_networks[mesh_network_cnt++] = network;
- }
- exit_critical_bh(&queue->lock);
- RTW_PRINT_SEL(sel, " %-17s %-3s %-4s %-5s %-32s %-3s %-3s %-3s"
- NSTATE_TITLE_FMT_ACN
- "\n"
- , "bssid", "ch", "rssi", "age", "mesh_id", "nop", "fwd", "cto"
- NSTATE_TITLE_ARG_ACN
- );
- for (i = 0; i < mesh_network_cnt; i++) {
- network = mesh_networks[i];
- if (network->network.InfrastructureMode != Ndis802_11_mesh)
- continue;
- mesh_conf_ie = rtw_get_ie(BSS_EX_TLV_IES(&network->network), WLAN_EID_MESH_CONFIG
- , &mesh_conf_ie_len, BSS_EX_TLV_IES_LEN(&network->network));
- if (!mesh_conf_ie || mesh_conf_ie_len != 7)
- continue;
- age_ms = rtw_get_passing_time_ms(network->last_scanned);
- #if CONFIG_RTW_MESH_ACNODE_PREVENT
- if (network->acnode_stime == 0)
- acn_ms = 0;
- else
- acn_ms = rtw_get_passing_time_ms(network->acnode_stime);
- #endif
- same_mbss = 0;
- candidate = 0;
- plink = NULL;
- blocked = 0;
- established = 0;
- if (MLME_IS_MESH(adapter) && MLME_IS_ASOC(adapter)) {
- plink = rtw_mesh_plink_get(adapter, network->network.MacAddress);
- if (plink && plink->plink_state == RTW_MESH_PLINK_ESTAB)
- established = 1;
- else if (plink && plink->plink_state == RTW_MESH_PLINK_BLOCKED)
- blocked = 1;
- else if (plink)
- ;
- else if (rtw_bss_is_candidate_mesh_peer(&mlme->cur_network.network, &network->network, 0, 1))
- candidate = 1;
- else if (rtw_bss_is_same_mbss(&mlme->cur_network.network, &network->network))
- same_mbss = 1;
- }
- RTW_PRINT_SEL(sel, "%c "MAC_FMT" %3d %4ld %5d %-32s %c%2u %3u %c%c "
- NSTATE_VALUE_FMT_ACN
- "\n"
- , established ? 'E' : (blocked ? 'B' : (plink ? 'N' : (candidate ? 'C' : (same_mbss ? 'S' : ' '))))
- , MAC_ARG(network->network.MacAddress)
- , network->network.Configuration.DSConfig
- , network->network.Rssi
- , age_ms < 99999 ? age_ms : 99999
- , network->network.mesh_id.Ssid
- , GET_MESH_CONF_ELE_ACCEPT_PEERINGS(mesh_conf_ie + 2) ? '+' : ' '
- , GET_MESH_CONF_ELE_NUM_OF_PEERINGS(mesh_conf_ie + 2)
- , GET_MESH_CONF_ELE_FORWARDING(mesh_conf_ie + 2)
- , GET_MESH_CONF_ELE_CTO_MGATE(mesh_conf_ie + 2) ? 'G' : ' '
- , GET_MESH_CONF_ELE_CTO_AS(mesh_conf_ie + 2) ? 'A' : ' '
- NSTATE_VALUE_ARG_ACN
- );
- }
- rtw_vmfree(mesh_networks, mlme->max_bss_cnt * sizeof(struct wlan_network *));
- }
- void rtw_mesh_adjust_chbw(u8 req_ch, u8 *req_bw, u8 *req_offset)
- {
- if (req_ch >= 5 && req_ch <= 9) {
- /* prevent secondary channel offset mismatch */
- if (*req_bw > CHANNEL_WIDTH_20) {
- *req_bw = CHANNEL_WIDTH_20;
- *req_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
- }
- }
- }
- int rtw_sae_check_frames(_adapter *adapter, const u8 *buf, u32 len, u8 tx)
- {
- const u8 *frame_body = buf + sizeof(struct rtw_ieee80211_hdr_3addr);
- u16 alg;
- u16 seq;
- u16 status;
- int ret = 0;
- alg = RTW_GET_LE16(frame_body);
- if (alg != 3)
- goto exit;
- seq = RTW_GET_LE16(frame_body + 2);
- status = RTW_GET_LE16(frame_body + 4);
- RTW_INFO("RTW_%s:AUTH alg:0x%04x, seq:0x%04x, status:0x%04x\n"
- , (tx == _TRUE) ? "Tx" : "Rx", alg, seq, status);
- ret = 1;
- #if CONFIG_RTW_MESH_PEER_BLACKLIST
- if (tx && seq == 1)
- rtw_mesh_plink_set_peer_conf_timeout(adapter, GetAddr1Ptr(buf));
- #endif
- exit:
- return ret;
- }
- #if CONFIG_RTW_MPM_TX_IES_SYNC_BSS
- #ifdef CONFIG_RTW_MESH_AEK
- static int rtw_mpm_ampe_dec(_adapter *adapter, struct mesh_plink_ent *plink
- , u8 *fhead, size_t flen, u8* fbody, u8 *mic_ie, u8 *ampe_buf)
- {
- int ret = _FAIL, verify_ret;
- const u8 *aad[] = {adapter_mac_addr(adapter), plink->addr, fbody};
- const size_t aad_len[] = {ETH_ALEN, ETH_ALEN, mic_ie - fbody};
- u8 *iv_crypt;
- size_t iv_crypt_len = flen - (mic_ie + 2 - fhead);
- iv_crypt = rtw_malloc(iv_crypt_len);
- if (!iv_crypt)
- goto exit;
- _rtw_memcpy(iv_crypt, mic_ie + 2, iv_crypt_len);
- verify_ret = aes_siv_decrypt(plink->aek, iv_crypt, iv_crypt_len
- , 3, aad, aad_len, ampe_buf);
- rtw_mfree(iv_crypt, iv_crypt_len);
- if (verify_ret) {
- RTW_WARN("verify error, aek_valid=%u\n", plink->aek_valid);
- goto exit;
- } else if (*ampe_buf != WLAN_EID_AMPE) {
- RTW_WARN("plaintext is not AMPE IE\n");
- goto exit;
- } else if (AES_BLOCK_SIZE + 2 + *(ampe_buf + 1) > iv_crypt_len) {
- RTW_WARN("plaintext AMPE IE length is not valid\n");
- goto exit;
- }
- ret = _SUCCESS;
- exit:
- return ret;
- }
- static int rtw_mpm_ampe_enc(_adapter *adapter, struct mesh_plink_ent *plink
- , u8* fbody, u8 *mic_ie, u8 *ampe_buf, bool inverse)
- {
- int ret = _FAIL, protect_ret;
- const u8 *aad[3];
- const size_t aad_len[3] = {ETH_ALEN, ETH_ALEN, mic_ie - fbody};
- u8 *ampe_ie;
- size_t ampe_ie_len = *(ampe_buf + 1) + 2; /* including id & len */
- if (inverse) {
- aad[0] = plink->addr;
- aad[1] = adapter_mac_addr(adapter);
- } else {
- aad[0] = adapter_mac_addr(adapter);
- aad[1] = plink->addr;
- }
- aad[2] = fbody;
- ampe_ie = rtw_malloc(ampe_ie_len);
- if (!ampe_ie)
- goto exit;
- _rtw_memcpy(ampe_ie, ampe_buf, ampe_ie_len);
- protect_ret = aes_siv_encrypt(plink->aek, ampe_ie, ampe_ie_len
- , 3, aad, aad_len, mic_ie + 2);
- rtw_mfree(ampe_ie, ampe_ie_len);
- if (protect_ret) {
- RTW_WARN("protect error, aek_valid=%u\n", plink->aek_valid);
- goto exit;
- }
- ret = _SUCCESS;
- exit:
- return ret;
- }
- #endif /* CONFIG_RTW_MESH_AEK */
- static int rtw_mpm_tx_ies_sync_bss(_adapter *adapter, struct mesh_plink_ent *plink
- , u8 *fhead, size_t flen, u8* fbody, u8 tlv_ies_offset, u8 *mpm_ie, u8 *mic_ie
- , u8 **nbuf, size_t *nlen)
- {
- int ret = _FAIL;
- struct mlme_priv *mlme = &(adapter->mlmepriv);
- struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
- struct mlme_ext_info *mlmeinfo = &(mlmeext->mlmext_info);
- WLAN_BSSID_EX *network = &(mlmeinfo->network);
- uint left;
- u8 *pos;
- uint mpm_ielen = *(mpm_ie + 1);
- u8 *fpos;
- u8 *new_buf = NULL;
- size_t new_len = 0;
- u8 *new_fhead;
- size_t new_flen;
- u8 *new_fbody;
- u8 *new_mic_ie;
- #ifdef CONFIG_RTW_MESH_AEK
- u8 *ampe_buf = NULL;
- size_t ampe_buf_len = 0;
- /* decode */
- if (mic_ie) {
- ampe_buf_len = flen - (mic_ie + 2 + AES_BLOCK_SIZE - fhead);
- ampe_buf = rtw_malloc(ampe_buf_len);
- if (!ampe_buf)
- goto exit;
- if (rtw_mpm_ampe_dec(adapter, plink, fhead, flen, fbody, mic_ie, ampe_buf) != _SUCCESS)
- goto exit;
- if (*(ampe_buf + 1) >= 68) {
- _rtw_memcpy(plink->sel_pcs, ampe_buf + 2, 4);
- _rtw_memcpy(plink->l_nonce, ampe_buf + 6, 32);
- _rtw_memcpy(plink->p_nonce, ampe_buf + 38, 32);
- }
- }
- #endif
- /* count for new frame length */
- new_len = sizeof(struct rtw_ieee80211_hdr_3addr) + tlv_ies_offset;
- left = BSS_EX_TLV_IES_LEN(network);
- pos = BSS_EX_TLV_IES(network);
- while (left >= 2) {
- u8 id, elen;
-
- id = *pos++;
- elen = *pos++;
- left -= 2;
- if (elen > left)
- break;
- switch (id) {
- case WLAN_EID_SSID:
- case WLAN_EID_DS_PARAMS:
- case WLAN_EID_TIM:
- break;
- default:
- new_len += 2 + elen;
- }
- left -= elen;
- pos += elen;
- }
- new_len += mpm_ielen + 2;
- if (mic_ie)
- new_len += AES_BLOCK_SIZE + 2 + ampe_buf_len;
- /* alloc new frame */
- new_buf = rtw_malloc(new_len);
- if (!new_buf) {
- rtw_warn_on(1);
- goto exit;
- }
- /* build new frame */
- _rtw_memcpy(new_buf, fhead, sizeof(struct rtw_ieee80211_hdr_3addr) + tlv_ies_offset);
- new_fhead = new_buf;
- new_flen = new_len;
- new_fbody = new_fhead + sizeof(struct rtw_ieee80211_hdr_3addr);
- fpos = new_fbody + tlv_ies_offset;
- left = BSS_EX_TLV_IES_LEN(network);
- pos = BSS_EX_TLV_IES(network);
- while (left >= 2) {
- u8 id, elen;
-
- id = *pos++;
- elen = *pos++;
- left -= 2;
- if (elen > left)
- break;
- switch (id) {
- case WLAN_EID_SSID:
- case WLAN_EID_DS_PARAMS:
- case WLAN_EID_TIM:
- break;
- default:
- fpos = rtw_set_ie(fpos, id, elen, pos, NULL);
- if (id == WLAN_EID_MESH_CONFIG)
- fpos = rtw_set_ie(fpos, WLAN_EID_MPM, mpm_ielen, mpm_ie + 2, NULL);
- }
- left -= elen;
- pos += elen;
- }
- if (mic_ie) {
- new_mic_ie = fpos;
- *fpos++ = WLAN_EID_MIC;
- *fpos++ = AES_BLOCK_SIZE;
- }
- #ifdef CONFIG_RTW_MESH_AEK
- /* encode */
- if (mic_ie) {
- int enc_ret = rtw_mpm_ampe_enc(adapter, plink, new_fbody, new_mic_ie, ampe_buf, 0);
- if (enc_ret != _SUCCESS)
- goto exit;
- }
- #endif
- *nlen = new_len;
- *nbuf = new_buf;
- ret = _SUCCESS;
- exit:
- if (ret != _SUCCESS && new_buf)
- rtw_mfree(new_buf, new_len);
- #ifdef CONFIG_RTW_MESH_AEK
- if (ampe_buf)
- rtw_mfree(ampe_buf, ampe_buf_len);
- #endif
- return ret;
- }
- #endif /* CONFIG_RTW_MPM_TX_IES_SYNC_BSS */
- struct mpm_frame_info {
- u8 *aid;
- u16 aid_v;
- u8 *pid;
- u16 pid_v;
- u8 *llid;
- u16 llid_v;
- u8 *plid;
- u16 plid_v;
- u8 *reason;
- u16 reason_v;
- u8 *chosen_pmk;
- };
- /*
- * pid:00000 llid:00000 chosen_pmk:0x00000000000000000000000000000000
- * aid:00000 pid:00000 llid:00000 plid:00000 chosen_pmk:0x00000000000000000000000000000000
- * pid:00000 llid:00000 plid:00000 reason:00000 chosen_pmk:0x00000000000000000000000000000000
- */
- #define MPM_LOG_BUF_LEN 92 /* this length is limited for legal combination */
- static void rtw_mpm_info_msg(struct mpm_frame_info *mpm_info, u8 *mpm_log_buf)
- {
- int cnt = 0;
- if (mpm_info->aid) {
- cnt += snprintf(mpm_log_buf + cnt, MPM_LOG_BUF_LEN - cnt - 1, "aid:%u ", mpm_info->aid_v);
- if (cnt >= MPM_LOG_BUF_LEN - 1)
- goto exit;
- }
- if (mpm_info->pid) {
- cnt += snprintf(mpm_log_buf + cnt, MPM_LOG_BUF_LEN - cnt - 1, "pid:%u ", mpm_info->pid_v);
- if (cnt >= MPM_LOG_BUF_LEN - 1)
- goto exit;
- }
- if (mpm_info->llid) {
- cnt += snprintf(mpm_log_buf + cnt, MPM_LOG_BUF_LEN - cnt - 1, "llid:%u ", mpm_info->llid_v);
- if (cnt >= MPM_LOG_BUF_LEN - 1)
- goto exit;
- }
- if (mpm_info->plid) {
- cnt += snprintf(mpm_log_buf + cnt, MPM_LOG_BUF_LEN - cnt - 1, "plid:%u ", mpm_info->plid_v);
- if (cnt >= MPM_LOG_BUF_LEN - 1)
- goto exit;
- }
- if (mpm_info->reason) {
- cnt += snprintf(mpm_log_buf + cnt, MPM_LOG_BUF_LEN - cnt - 1, "reason:%u ", mpm_info->reason_v);
- if (cnt >= MPM_LOG_BUF_LEN - 1)
- goto exit;
- }
- if (mpm_info->chosen_pmk) {
- cnt += snprintf(mpm_log_buf + cnt, MPM_LOG_BUF_LEN - cnt - 1, "chosen_pmk:0x"KEY_FMT, KEY_ARG(mpm_info->chosen_pmk));
- if (cnt >= MPM_LOG_BUF_LEN - 1)
- goto exit;
- }
- exit:
- return;
- }
- static int rtw_mpm_check_frames(_adapter *adapter, u8 action, const u8 **buf, size_t *len, u8 tx)
- {
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
- struct mesh_plink_ent *plink = NULL;
- u8 *nbuf = NULL;
- size_t nlen = 0;
- u8 *fhead = (u8 *)*buf;
- size_t flen = *len;
- u8 *peer_addr = tx ? GetAddr1Ptr(fhead) : get_addr2_ptr(fhead);
- u8 *frame_body = fhead + sizeof(struct rtw_ieee80211_hdr_3addr);
- struct mpm_frame_info mpm_info;
- u8 tlv_ies_offset;
- u8 *mpm_ie = NULL;
- uint mpm_ielen = 0;
- u8 *mic_ie = NULL;
- uint mic_ielen = 0;
- int ret = 0;
- u8 mpm_log_buf[MPM_LOG_BUF_LEN] = {0};
- if (action == RTW_ACT_SELF_PROTECTED_MESH_OPEN)
- tlv_ies_offset = 4;
- else if (action == RTW_ACT_SELF_PROTECTED_MESH_CONF)
- tlv_ies_offset = 6;
- else if (action == RTW_ACT_SELF_PROTECTED_MESH_CLOSE)
- tlv_ies_offset = 2;
- else {
- rtw_warn_on(1);
- goto exit;
- }
- plink = rtw_mesh_plink_get(adapter, peer_addr);
- if (!plink && (tx == _TRUE || action == RTW_ACT_SELF_PROTECTED_MESH_CONF)) {
- /* warning message if no plink when: 1.TX all MPM or 2.RX CONF */
- RTW_WARN("RTW_%s:%s without plink of "MAC_FMT"\n"
- , (tx == _TRUE) ? "Tx" : "Rx", action_self_protected_str(action), MAC_ARG(peer_addr));
- goto exit;
- }
- _rtw_memset(&mpm_info, 0, sizeof(struct mpm_frame_info));
- if (action == RTW_ACT_SELF_PROTECTED_MESH_CONF) {
- mpm_info.aid = (u8 *)frame_body + 4;
- mpm_info.aid_v = RTW_GET_LE16(mpm_info.aid);
- }
- mpm_ie = rtw_get_ie(fhead + sizeof(struct rtw_ieee80211_hdr_3addr) + tlv_ies_offset
- , WLAN_EID_MPM, &mpm_ielen
- , flen - sizeof(struct rtw_ieee80211_hdr_3addr) - tlv_ies_offset);
- if (!mpm_ie || mpm_ielen < 2 + 2)
- goto exit;
- mpm_info.pid = mpm_ie + 2;
- mpm_info.pid_v = RTW_GET_LE16(mpm_info.pid);
- mpm_info.llid = mpm_info.pid + 2;
- mpm_info.llid_v = RTW_GET_LE16(mpm_info.llid);
- switch (action) {
- case RTW_ACT_SELF_PROTECTED_MESH_OPEN:
- /* pid:2, llid:2, (chosen_pmk:16) */
- if (mpm_info.pid_v == 0 && mpm_ielen == 4)
- ;
- else if (mpm_info.pid_v == 1 && mpm_ielen == 20)
- mpm_info.chosen_pmk = mpm_info.llid + 2;
- else
- goto exit;
- break;
- case RTW_ACT_SELF_PROTECTED_MESH_CONF:
- /* pid:2, llid:2, plid:2, (chosen_pmk:16) */
- mpm_info.plid = mpm_info.llid + 2;
- mpm_info.plid_v = RTW_GET_LE16(mpm_info.plid);
- if (mpm_info.pid_v == 0 && mpm_ielen == 6)
- ;
- else if (mpm_info.pid_v == 1 && mpm_ielen == 22)
- mpm_info.chosen_pmk = mpm_info.plid + 2;
- else
- goto exit;
- break;
- case RTW_ACT_SELF_PROTECTED_MESH_CLOSE:
- /* pid:2, llid:2, (plid:2), reason:2, (chosen_pmk:16) */
- if (mpm_info.pid_v == 0 && mpm_ielen == 6) {
- /* MPM, without plid */
- mpm_info.reason = mpm_info.llid + 2;
- mpm_info.reason_v = RTW_GET_LE16(mpm_info.reason);
- } else if (mpm_info.pid_v == 0 && mpm_ielen == 8) {
- /* MPM, with plid */
- mpm_info.plid = mpm_info.llid + 2;
- mpm_info.plid_v = RTW_GET_LE16(mpm_info.plid);
- mpm_info.reason = mpm_info.plid + 2;
- mpm_info.reason_v = RTW_GET_LE16(mpm_info.reason);
- } else if (mpm_info.pid_v == 1 && mpm_ielen == 22) {
- /* AMPE, without plid */
- mpm_info.reason = mpm_info.llid + 2;
- mpm_info.reason_v = RTW_GET_LE16(mpm_info.reason);
- mpm_info.chosen_pmk = mpm_info.reason + 2;
- } else if (mpm_info.pid_v == 1 && mpm_ielen == 24) {
- /* AMPE, with plid */
- mpm_info.plid = mpm_info.llid + 2;
- mpm_info.plid_v = RTW_GET_LE16(mpm_info.plid);
- mpm_info.reason = mpm_info.plid + 2;
- mpm_info.reason_v = RTW_GET_LE16(mpm_info.reason);
- mpm_info.chosen_pmk = mpm_info.reason + 2;
- } else
- goto exit;
- break;
- };
- if (mpm_info.pid_v == 1) {
- mic_ie = rtw_get_ie(fhead + sizeof(struct rtw_ieee80211_hdr_3addr) + tlv_ies_offset
- , WLAN_EID_MIC, &mic_ielen
- , flen - sizeof(struct rtw_ieee80211_hdr_3addr) - tlv_ies_offset);
- if (!mic_ie || mic_ielen != AES_BLOCK_SIZE)
- goto exit;
- }
- #if CONFIG_RTW_MPM_TX_IES_SYNC_BSS
- if ((action == RTW_ACT_SELF_PROTECTED_MESH_OPEN || action == RTW_ACT_SELF_PROTECTED_MESH_CONF)
- && tx == _TRUE
- ) {
- #define DBG_RTW_MPM_TX_IES_SYNC_BSS 0
- if (mpm_info.pid_v == 1 && (!plink || !MESH_PLINK_AEK_VALID(plink))) {
- RTW_WARN("AEK not ready, IEs can't sync with BSS\n");
- goto bypass_sync_bss;
- }
- if (DBG_RTW_MPM_TX_IES_SYNC_BSS) {
- RTW_INFO(FUNC_ADPT_FMT" before:\n", FUNC_ADPT_ARG(adapter));
- dump_ies(RTW_DBGDUMP
- , fhead + sizeof(struct rtw_ieee80211_hdr_3addr) + tlv_ies_offset
- , flen - sizeof(struct rtw_ieee80211_hdr_3addr) - tlv_ies_offset);
- }
- rtw_mpm_tx_ies_sync_bss(adapter, plink
- , fhead, flen, frame_body, tlv_ies_offset, mpm_ie, mic_ie
- , &nbuf, &nlen);
- if (!nbuf)
- goto exit;
- /* update pointer & len for new frame */
- fhead = nbuf;
- flen = nlen;
- frame_body = fhead + sizeof(struct rtw_ieee80211_hdr_3addr);
- if (mpm_info.pid_v == 1) {
- mic_ie = rtw_get_ie(fhead + sizeof(struct rtw_ieee80211_hdr_3addr) + tlv_ies_offset
- , WLAN_EID_MIC, &mic_ielen
- , flen - sizeof(struct rtw_ieee80211_hdr_3addr) - tlv_ies_offset);
- }
- if (DBG_RTW_MPM_TX_IES_SYNC_BSS) {
- RTW_INFO(FUNC_ADPT_FMT" after:\n", FUNC_ADPT_ARG(adapter));
- dump_ies(RTW_DBGDUMP
- , fhead + sizeof(struct rtw_ieee80211_hdr_3addr) + tlv_ies_offset
- , flen - sizeof(struct rtw_ieee80211_hdr_3addr) - tlv_ies_offset);
- }
- }
- bypass_sync_bss:
- #endif /* CONFIG_RTW_MPM_TX_IES_SYNC_BSS */
- if (!plink)
- goto mpm_log;
- #if CONFIG_RTW_MESH_PEER_BLACKLIST
- if (action == RTW_ACT_SELF_PROTECTED_MESH_OPEN) {
- if (tx)
- rtw_mesh_plink_set_peer_conf_timeout(adapter, peer_addr);
- } else
- #endif
- #if CONFIG_RTW_MESH_ACNODE_PREVENT
- if (action == RTW_ACT_SELF_PROTECTED_MESH_CLOSE) {
- if (tx && mpm_info.reason && mpm_info.reason_v == WLAN_REASON_MESH_MAX_PEERS) {
- if (rtw_mesh_scanned_is_acnode_confirmed(adapter, plink->scanned)
- && rtw_mesh_acnode_prevent_allow_sacrifice(adapter)
- ) {
- struct sta_info *sac = rtw_mesh_acnode_prevent_pick_sacrifice(adapter);
- if (sac) {
- struct sta_priv *stapriv = &adapter->stapriv;
- _irqL irqL;
- u8 sta_addr[ETH_ALEN];
- u8 updated = _FALSE;
- _enter_critical_bh(&stapriv->asoc_list_lock, &irqL);
- if (!rtw_is_list_empty(&sac->asoc_list)) {
- rtw_list_delete(&sac->asoc_list);
- stapriv->asoc_list_cnt--;
- STA_SET_MESH_PLINK(sac, NULL);
- }
- _exit_critical_bh(&stapriv->asoc_list_lock, &irqL);
- RTW_INFO(FUNC_ADPT_FMT" sacrifice "MAC_FMT" for acnode\n"
- , FUNC_ADPT_ARG(adapter), MAC_ARG(sac->cmn.mac_addr));
- _rtw_memcpy(sta_addr, sac->cmn.mac_addr, ETH_ALEN);
- updated = ap_free_sta(adapter, sac, 0, 0, 1);
- rtw_mesh_expire_peer(stapriv->padapter, sta_addr);
- associated_clients_update(adapter, updated, STA_INFO_UPDATE_ALL);
- }
- }
- }
- } else
- #endif
- if (action == RTW_ACT_SELF_PROTECTED_MESH_CONF) {
- _irqL irqL;
- u8 *ies = NULL;
- u16 ies_len = 0;
- _enter_critical_bh(&(plink_ctl->lock), &irqL);
- plink = _rtw_mesh_plink_get(adapter, peer_addr);
- if (!plink)
- goto release_plink_ctl;
- if (tx == _FALSE) {
- ies = plink->rx_conf_ies;
- ies_len = plink->rx_conf_ies_len;
- plink->rx_conf_ies = NULL;
- plink->rx_conf_ies_len = 0;
- plink->llid = mpm_info.plid_v;
- plink->plid = mpm_info.llid_v;
- plink->peer_aid = mpm_info.aid_v;
- if (mpm_info.pid_v == 1)
- _rtw_memcpy(plink->chosen_pmk, mpm_info.chosen_pmk, 16);
- }
- #ifdef CONFIG_RTW_MESH_DRIVER_AID
- else {
- ies = plink->tx_conf_ies;
- ies_len = plink->tx_conf_ies_len;
- plink->tx_conf_ies = NULL;
- plink->tx_conf_ies_len = 0;
- }
- #endif
- if (ies && ies_len)
- rtw_mfree(ies, ies_len);
- #ifndef CONFIG_RTW_MESH_DRIVER_AID
- if (tx == _TRUE)
- goto release_plink_ctl; /* no need to copy tx conf ies */
- #endif
- /* copy mesh confirm IEs */
- if (mpm_info.pid_v == 1) /* not include MIC & encrypted AMPE */
- ies_len = (mic_ie - fhead) - sizeof(struct rtw_ieee80211_hdr_3addr) - 2;
- else
- ies_len = flen - sizeof(struct rtw_ieee80211_hdr_3addr) - 2;
- ies = rtw_zmalloc(ies_len);
- if (ies) {
- _rtw_memcpy(ies, fhead + sizeof(struct rtw_ieee80211_hdr_3addr) + 2, ies_len);
- if (tx == _FALSE) {
- plink->rx_conf_ies = ies;
- plink->rx_conf_ies_len = ies_len;
- }
- #ifdef CONFIG_RTW_MESH_DRIVER_AID
- else {
- plink->tx_conf_ies = ies;
- plink->tx_conf_ies_len = ies_len;
- }
- #endif
- }
- release_plink_ctl:
- _exit_critical_bh(&(plink_ctl->lock), &irqL);
- }
- mpm_log:
- rtw_mpm_info_msg(&mpm_info, mpm_log_buf);
- RTW_INFO("RTW_%s:%s %s\n"
- , (tx == _TRUE) ? "Tx" : "Rx"
- , action_self_protected_str(action)
- , mpm_log_buf
- );
- ret = 1;
- exit:
- if (nbuf) {
- if (ret == 1) {
- *buf = nbuf;
- *len = nlen;
- } else
- rtw_mfree(nbuf, nlen);
- }
- return ret;
- }
- static int rtw_mesh_check_frames(_adapter *adapter, const u8 **buf, size_t *len, u8 tx)
- {
- int is_mesh_frame = -1;
- const u8 *frame_body;
- u8 category, action;
- frame_body = *buf + sizeof(struct rtw_ieee80211_hdr_3addr);
- category = frame_body[0];
- if (category == RTW_WLAN_CATEGORY_SELF_PROTECTED) {
- action = frame_body[1];
- switch (action) {
- case RTW_ACT_SELF_PROTECTED_MESH_OPEN:
- case RTW_ACT_SELF_PROTECTED_MESH_CONF:
- case RTW_ACT_SELF_PROTECTED_MESH_CLOSE:
- rtw_mpm_check_frames(adapter, action, buf, len, tx);
- is_mesh_frame = action;
- break;
- case RTW_ACT_SELF_PROTECTED_MESH_GK_INFORM:
- case RTW_ACT_SELF_PROTECTED_MESH_GK_ACK:
- RTW_INFO("RTW_%s:%s\n", (tx == _TRUE) ? "Tx" : "Rx", action_self_protected_str(action));
- is_mesh_frame = action;
- break;
- default:
- break;
- };
- }
- exit:
- return is_mesh_frame;
- }
- int rtw_mesh_check_frames_tx(_adapter *adapter, const u8 **buf, size_t *len)
- {
- return rtw_mesh_check_frames(adapter, buf, len, _TRUE);
- }
- int rtw_mesh_check_frames_rx(_adapter *adapter, const u8 *buf, size_t len)
- {
- return rtw_mesh_check_frames(adapter, &buf, &len, _FALSE);
- }
- int rtw_mesh_on_auth(_adapter *adapter, union recv_frame *rframe)
- {
- u8 *whdr = rframe->u.hdr.rx_data;
- #if CONFIG_RTW_MACADDR_ACL
- if (rtw_access_ctrl(adapter, get_addr2_ptr(whdr)) == _FALSE)
- return _SUCCESS;
- #endif
- if (!rtw_mesh_plink_get(adapter, get_addr2_ptr(whdr))) {
- #if CONFIG_RTW_MESH_ACNODE_PREVENT
- rtw_mesh_acnode_set_notify_etime(adapter, whdr);
- #endif
- if (adapter_to_rfctl(adapter)->offch_state == OFFCHS_NONE)
- issue_probereq(adapter, &adapter->mlmepriv.cur_network.network.mesh_id, get_addr2_ptr(whdr));
- /* only peer being added (checked by notify conditions) is allowed */
- return _SUCCESS;
- }
- rtw_cfg80211_rx_mframe(adapter, rframe, NULL);
- return _SUCCESS;
- }
- unsigned int on_action_self_protected(_adapter *adapter, union recv_frame *rframe)
- {
- unsigned int ret = _FAIL;
- struct sta_info *sta = NULL;
- u8 *pframe = rframe->u.hdr.rx_data;
- uint frame_len = rframe->u.hdr.len;
- u8 *frame_body = (u8 *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
- u8 category;
- u8 action;
- /* check RA matches or not */
- if (!_rtw_memcmp(adapter_mac_addr(adapter), GetAddr1Ptr(pframe), ETH_ALEN))
- goto exit;
- category = frame_body[0];
- if (category != RTW_WLAN_CATEGORY_SELF_PROTECTED)
- goto exit;
- action = frame_body[1];
- switch (action) {
- case RTW_ACT_SELF_PROTECTED_MESH_OPEN:
- case RTW_ACT_SELF_PROTECTED_MESH_CONF:
- case RTW_ACT_SELF_PROTECTED_MESH_CLOSE:
- case RTW_ACT_SELF_PROTECTED_MESH_GK_INFORM:
- case RTW_ACT_SELF_PROTECTED_MESH_GK_ACK:
- if (!(MLME_IS_MESH(adapter) && MLME_IS_ASOC(adapter)))
- goto exit;
- #ifdef CONFIG_IOCTL_CFG80211
- #if CONFIG_RTW_MACADDR_ACL
- if (rtw_access_ctrl(adapter, get_addr2_ptr(pframe)) == _FALSE)
- goto exit;
- #endif
- #if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
- if (rtw_mesh_cto_mgate_required(adapter)
- /* only peer being added (checked by notify conditions) is allowed */
- && !rtw_mesh_plink_get(adapter, get_addr2_ptr(pframe)))
- goto exit;
- #endif
- rtw_cfg80211_rx_action(adapter, rframe, NULL);
- ret = _SUCCESS;
- #endif /* CONFIG_IOCTL_CFG80211 */
- break;
- default:
- break;
- }
- exit:
- return ret;
- }
- const u8 ae_to_mesh_ctrl_len[] = {
- 6,
- 12, /* MESH_FLAGS_AE_A4 */
- 18, /* MESH_FLAGS_AE_A5_A6 */
- 0,
- };
- unsigned int on_action_mesh(_adapter *adapter, union recv_frame *rframe)
- {
- unsigned int ret = _FAIL;
- struct sta_info *sta = NULL;
- struct sta_priv *stapriv = &adapter->stapriv;
- u8 *pframe = rframe->u.hdr.rx_data;
- uint frame_len = rframe->u.hdr.len;
- u8 *frame_body = (u8 *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
- u8 category;
- u8 action;
- if (!MLME_IS_MESH(adapter))
- goto exit;
- /* check stainfo exist? */
- category = frame_body[0];
- if (category != RTW_WLAN_CATEGORY_MESH)
- goto exit;
- action = frame_body[1];
- switch (action) {
- case RTW_ACT_MESH_HWMP_PATH_SELECTION:
- rtw_mesh_rx_path_sel_frame(adapter, rframe);
- ret = _SUCCESS;
- break;
- default:
- break;
- }
- exit:
- return ret;
- }
- bool rtw_mesh_update_bss_peering_status(_adapter *adapter, WLAN_BSSID_EX *bss)
- {
- struct sta_priv *stapriv = &adapter->stapriv;
- struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
- u8 num_of_peerings = stapriv->asoc_list_cnt;
- bool accept_peerings = stapriv->asoc_list_cnt < mcfg->max_peer_links;
- u8 *ie;
- int ie_len;
- bool updated = 0;
- #if CONFIG_RTW_MESH_ACNODE_PREVENT
- accept_peerings |= plink_ctl->acnode_rsvd;
- #endif
- ie = rtw_get_ie(BSS_EX_TLV_IES(bss), WLAN_EID_MESH_CONFIG, &ie_len, BSS_EX_TLV_IES_LEN(bss));
- if (!ie || ie_len != 7) {
- rtw_warn_on(1);
- goto exit;
- }
- if (GET_MESH_CONF_ELE_NUM_OF_PEERINGS(ie + 2) != num_of_peerings) {
- SET_MESH_CONF_ELE_NUM_OF_PEERINGS(ie + 2, num_of_peerings);
- updated = 1;
- }
- if (GET_MESH_CONF_ELE_ACCEPT_PEERINGS(ie + 2) != accept_peerings) {
- SET_MESH_CONF_ELE_ACCEPT_PEERINGS(ie + 2, accept_peerings);
- updated = 1;
- }
- exit:
- return updated;
- }
- bool rtw_mesh_update_bss_formation_info(_adapter *adapter, WLAN_BSSID_EX *bss)
- {
- struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- u8 cto_mgate = (minfo->num_gates || mcfg->dot11MeshGateAnnouncementProtocol);
- u8 cto_as = 0;
- u8 *ie;
- int ie_len;
- bool updated = 0;
- ie = rtw_get_ie(BSS_EX_TLV_IES(bss), WLAN_EID_MESH_CONFIG, &ie_len,
- BSS_EX_TLV_IES_LEN(bss));
- if (!ie || ie_len != 7) {
- rtw_warn_on(1);
- goto exit;
- }
- if (GET_MESH_CONF_ELE_CTO_MGATE(ie + 2) != cto_mgate) {
- SET_MESH_CONF_ELE_CTO_MGATE(ie + 2, cto_mgate);
- updated = 1;
- }
- if (GET_MESH_CONF_ELE_CTO_AS(ie + 2) != cto_as) {
- SET_MESH_CONF_ELE_CTO_AS(ie + 2, cto_as);
- updated = 1;
- }
- exit:
- return updated;
- }
- bool rtw_mesh_update_bss_forwarding_state(_adapter *adapter, WLAN_BSSID_EX *bss)
- {
- struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
- u8 forward = mcfg->dot11MeshForwarding;
- u8 *ie;
- int ie_len;
- bool updated = 0;
- ie = rtw_get_ie(BSS_EX_TLV_IES(bss), WLAN_EID_MESH_CONFIG, &ie_len,
- BSS_EX_TLV_IES_LEN(bss));
- if (!ie || ie_len != 7) {
- rtw_warn_on(1);
- goto exit;
- }
- if (GET_MESH_CONF_ELE_FORWARDING(ie + 2) != forward) {
- SET_MESH_CONF_ELE_FORWARDING(ie + 2, forward);
- updated = 1;
- }
- exit:
- return updated;
- }
- struct mesh_plink_ent *_rtw_mesh_plink_get(_adapter *adapter, const u8 *hwaddr)
- {
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
- struct mesh_plink_ent *ent = NULL;
- int i;
- for (i = 0; i < RTW_MESH_MAX_PEER_CANDIDATES; i++) {
- if (plink_ctl->ent[i].valid == _TRUE
- && _rtw_memcmp(plink_ctl->ent[i].addr, hwaddr, ETH_ALEN) == _TRUE
- ) {
- ent = &plink_ctl->ent[i];
- break;
- }
- }
- exit:
- return ent;
- }
- struct mesh_plink_ent *rtw_mesh_plink_get(_adapter *adapter, const u8 *hwaddr)
- {
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
- struct mesh_plink_ent *ent = NULL;
- _irqL irqL;
- _enter_critical_bh(&(plink_ctl->lock), &irqL);
- ent = _rtw_mesh_plink_get(adapter, hwaddr);
- _exit_critical_bh(&(plink_ctl->lock), &irqL);
- exit:
- return ent;
- }
- struct mesh_plink_ent *rtw_mesh_plink_get_no_estab_by_idx(_adapter *adapter, u8 idx)
- {
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
- struct mesh_plink_ent *ent = NULL;
- int i, j = 0;
- _irqL irqL;
- _enter_critical_bh(&(plink_ctl->lock), &irqL);
- for (i = 0; i < RTW_MESH_MAX_PEER_CANDIDATES; i++) {
- if (plink_ctl->ent[i].valid == _TRUE
- && plink_ctl->ent[i].plink_state != RTW_MESH_PLINK_ESTAB
- ) {
- if (j == idx) {
- ent = &plink_ctl->ent[i];
- break;
- }
- j++;
- }
- }
- _exit_critical_bh(&(plink_ctl->lock), &irqL);
- return ent;
- }
- int _rtw_mesh_plink_add(_adapter *adapter, const u8 *hwaddr)
- {
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
- struct mesh_plink_ent *ent = NULL;
- u8 exist = _FALSE;
- int i;
- for (i = 0; i < RTW_MESH_MAX_PEER_CANDIDATES; i++) {
- if (plink_ctl->ent[i].valid == _TRUE
- && _rtw_memcmp(plink_ctl->ent[i].addr, hwaddr, ETH_ALEN) == _TRUE
- ) {
- ent = &plink_ctl->ent[i];
- exist = _TRUE;
- break;
- }
- if (ent == NULL && plink_ctl->ent[i].valid == _FALSE)
- ent = &plink_ctl->ent[i];
- }
- if (exist == _FALSE && ent) {
- _rtw_memcpy(ent->addr, hwaddr, ETH_ALEN);
- ent->valid = _TRUE;
- #ifdef CONFIG_RTW_MESH_AEK
- ent->aek_valid = 0;
- #endif
- ent->llid = 0;
- ent->plid = 0;
- _rtw_memset(ent->chosen_pmk, 0, 16);
- #ifdef CONFIG_RTW_MESH_AEK
- _rtw_memset(ent->sel_pcs, 0, 4);
- _rtw_memset(ent->l_nonce, 0, 32);
- _rtw_memset(ent->p_nonce, 0, 32);
- #endif
- ent->plink_state = RTW_MESH_PLINK_LISTEN;
- #ifndef CONFIG_RTW_MESH_DRIVER_AID
- ent->aid = 0;
- #endif
- ent->peer_aid = 0;
- SET_PEER_CONF_DISABLED(ent);
- SET_CTO_MGATE_CONF_DISABLED(ent);
- plink_ctl->num++;
- }
- exit:
- return exist == _TRUE ? RTW_ALREADY : (ent ? _SUCCESS : _FAIL);
- }
- int rtw_mesh_plink_add(_adapter *adapter, const u8 *hwaddr)
- {
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
- _irqL irqL;
- int ret;
- _enter_critical_bh(&(plink_ctl->lock), &irqL);
- ret = _rtw_mesh_plink_add(adapter, hwaddr);
- _exit_critical_bh(&(plink_ctl->lock), &irqL);
- return ret;
- }
- int rtw_mesh_plink_set_state(_adapter *adapter, const u8 *hwaddr, u8 state)
- {
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
- struct mesh_plink_ent *ent = NULL;
- _irqL irqL;
- _enter_critical_bh(&(plink_ctl->lock), &irqL);
- ent = _rtw_mesh_plink_get(adapter, hwaddr);
- if (ent)
- ent->plink_state = state;
- _exit_critical_bh(&(plink_ctl->lock), &irqL);
- exit:
- return ent ? _SUCCESS : _FAIL;
- }
- #ifdef CONFIG_RTW_MESH_AEK
- int rtw_mesh_plink_set_aek(_adapter *adapter, const u8 *hwaddr, const u8 *aek)
- {
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
- struct mesh_plink_ent *ent = NULL;
- _irqL irqL;
- _enter_critical_bh(&(plink_ctl->lock), &irqL);
- ent = _rtw_mesh_plink_get(adapter, hwaddr);
- if (ent) {
- _rtw_memcpy(ent->aek, aek, 32);
- ent->aek_valid = 1;
- }
- _exit_critical_bh(&(plink_ctl->lock), &irqL);
- exit:
- return ent ? _SUCCESS : _FAIL;
- }
- #endif
- #if CONFIG_RTW_MESH_PEER_BLACKLIST
- int rtw_mesh_plink_set_peer_conf_timeout(_adapter *adapter, const u8 *hwaddr)
- {
- struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
- struct mesh_plink_ent *ent = NULL;
- _irqL irqL;
- _enter_critical_bh(&(plink_ctl->lock), &irqL);
- ent = _rtw_mesh_plink_get(adapter, hwaddr);
- if (ent) {
- if (IS_PEER_CONF_DISABLED(ent))
- SET_PEER_CONF_END_TIME(ent, mcfg->peer_sel_policy.peer_conf_timeout_ms);
- }
- _exit_critical_bh(&(plink_ctl->lock), &irqL);
- exit:
- return ent ? _SUCCESS : _FAIL;
- }
- #endif
- void _rtw_mesh_plink_del_ent(_adapter *adapter, struct mesh_plink_ent *ent)
- {
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
- ent->valid = _FALSE;
- #ifdef CONFIG_RTW_MESH_DRIVER_AID
- if (ent->tx_conf_ies && ent->tx_conf_ies_len)
- rtw_mfree(ent->tx_conf_ies, ent->tx_conf_ies_len);
- ent->tx_conf_ies = NULL;
- ent->tx_conf_ies_len = 0;
- #endif
- if (ent->rx_conf_ies && ent->rx_conf_ies_len)
- rtw_mfree(ent->rx_conf_ies, ent->rx_conf_ies_len);
- ent->rx_conf_ies = NULL;
- ent->rx_conf_ies_len = 0;
- if (ent->scanned)
- ent->scanned = NULL;
- plink_ctl->num--;
- }
- int rtw_mesh_plink_del(_adapter *adapter, const u8 *hwaddr)
- {
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
- struct mesh_plink_ent *ent = NULL;
- u8 exist = _FALSE;
- int i;
- _irqL irqL;
- _enter_critical_bh(&(plink_ctl->lock), &irqL);
- for (i = 0; i < RTW_MESH_MAX_PEER_CANDIDATES; i++) {
- if (plink_ctl->ent[i].valid == _TRUE
- && _rtw_memcmp(plink_ctl->ent[i].addr, hwaddr, ETH_ALEN) == _TRUE
- ) {
- ent = &plink_ctl->ent[i];
- exist = _TRUE;
- break;
- }
- }
- if (exist == _TRUE)
- _rtw_mesh_plink_del_ent(adapter, ent);
- _exit_critical_bh(&(plink_ctl->lock), &irqL);
- exit:
- return exist == _TRUE ? _SUCCESS : RTW_ALREADY;
- }
- void rtw_mesh_plink_ctl_init(_adapter *adapter)
- {
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
- int i;
- _rtw_spinlock_init(&plink_ctl->lock);
- plink_ctl->num = 0;
- for (i = 0; i < RTW_MESH_MAX_PEER_CANDIDATES; i++)
- plink_ctl->ent[i].valid = _FALSE;
- #if CONFIG_RTW_MESH_PEER_BLACKLIST
- _rtw_init_queue(&plink_ctl->peer_blacklist);
- #endif
- #if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
- _rtw_init_queue(&plink_ctl->cto_mgate_blacklist);
- #endif
- }
- void rtw_mesh_plink_ctl_deinit(_adapter *adapter)
- {
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
- struct mesh_plink_ent *ent;
- int i;
- _irqL irqL;
- _enter_critical_bh(&(plink_ctl->lock), &irqL);
- for (i = 0; i < RTW_MESH_MAX_PEER_CANDIDATES; i++) {
- ent = &plink_ctl->ent[i];
- #ifdef CONFIG_RTW_MESH_DRIVER_AID
- if (ent->tx_conf_ies && ent->tx_conf_ies_len)
- rtw_mfree(ent->tx_conf_ies, ent->tx_conf_ies_len);
- #endif
- if (ent->rx_conf_ies && ent->rx_conf_ies_len)
- rtw_mfree(ent->rx_conf_ies, ent->rx_conf_ies_len);
- }
- _exit_critical_bh(&(plink_ctl->lock), &irqL);
- _rtw_spinlock_free(&plink_ctl->lock);
- #if CONFIG_RTW_MESH_PEER_BLACKLIST
- rtw_mesh_peer_blacklist_flush(adapter);
- _rtw_deinit_queue(&plink_ctl->peer_blacklist);
- #endif
- #if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
- rtw_mesh_cto_mgate_blacklist_flush(adapter);
- _rtw_deinit_queue(&plink_ctl->cto_mgate_blacklist);
- #endif
- }
- void dump_mesh_plink_ctl(void *sel, _adapter *adapter)
- {
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
- struct mesh_plink_ent *ent;
- int i;
- RTW_PRINT_SEL(sel, "num:%u\n", plink_ctl->num);
- #if CONFIG_RTW_MESH_ACNODE_PREVENT
- RTW_PRINT_SEL(sel, "acnode_rsvd:%u\n", plink_ctl->acnode_rsvd);
- #endif
- for (i = 0; i < RTW_MESH_MAX_PEER_CANDIDATES; i++) {
- ent = &plink_ctl->ent[i];
- if (!ent->valid)
- continue;
- RTW_PRINT_SEL(sel, "\n");
- RTW_PRINT_SEL(sel, "peer:"MAC_FMT"\n", MAC_ARG(ent->addr));
- RTW_PRINT_SEL(sel, "plink_state:%s\n", rtw_mesh_plink_str(ent->plink_state));
- #ifdef CONFIG_RTW_MESH_AEK
- if (ent->aek_valid)
- RTW_PRINT_SEL(sel, "aek:"KEY_FMT KEY_FMT"\n", KEY_ARG(ent->aek), KEY_ARG(ent->aek + 16));
- #endif
- RTW_PRINT_SEL(sel, "llid:%u, plid:%u\n", ent->llid, ent->plid);
- #ifndef CONFIG_RTW_MESH_DRIVER_AID
- RTW_PRINT_SEL(sel, "aid:%u\n", ent->aid);
- #endif
- RTW_PRINT_SEL(sel, "peer_aid:%u\n", ent->peer_aid);
- RTW_PRINT_SEL(sel, "chosen_pmk:"KEY_FMT"\n", KEY_ARG(ent->chosen_pmk));
- #ifdef CONFIG_RTW_MESH_AEK
- RTW_PRINT_SEL(sel, "sel_pcs:%02x%02x%02x%02x\n"
- , ent->sel_pcs[0], ent->sel_pcs[1], ent->sel_pcs[2], ent->sel_pcs[3]);
- RTW_PRINT_SEL(sel, "l_nonce:"KEY_FMT KEY_FMT"\n", KEY_ARG(ent->l_nonce), KEY_ARG(ent->l_nonce + 16));
- RTW_PRINT_SEL(sel, "p_nonce:"KEY_FMT KEY_FMT"\n", KEY_ARG(ent->p_nonce), KEY_ARG(ent->p_nonce + 16));
- #endif
- #ifdef CONFIG_RTW_MESH_DRIVER_AID
- RTW_PRINT_SEL(sel, "tx_conf_ies:%p, len:%u\n", ent->tx_conf_ies, ent->tx_conf_ies_len);
- #endif
- RTW_PRINT_SEL(sel, "rx_conf_ies:%p, len:%u\n", ent->rx_conf_ies, ent->rx_conf_ies_len);
- RTW_PRINT_SEL(sel, "scanned:%p\n", ent->scanned);
- #if CONFIG_RTW_MESH_PEER_BLACKLIST
- if (!IS_PEER_CONF_DISABLED(ent)) {
- if (!IS_PEER_CONF_TIMEOUT(ent))
- RTW_PRINT_SEL(sel, "peer_conf:%d\n", rtw_systime_to_ms(ent->peer_conf_end_time - rtw_get_current_time()));
- else
- RTW_PRINT_SEL(sel, "peer_conf:TIMEOUT\n");
- }
- #endif
- #if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
- if (!IS_CTO_MGATE_CONF_DISABLED(ent)) {
- if (!IS_CTO_MGATE_CONF_TIMEOUT(ent))
- RTW_PRINT_SEL(sel, "cto_mgate_conf:%d\n", rtw_systime_to_ms(ent->cto_mgate_conf_end_time - rtw_get_current_time()));
- else
- RTW_PRINT_SEL(sel, "cto_mgate_conf:TIMEOUT\n");
- }
- #endif
- }
- }
- /* this function is called with plink_ctl being locked */
- int rtw_mesh_peer_establish(_adapter *adapter, struct mesh_plink_ent *plink, struct sta_info *sta)
- {
- #ifndef DBG_RTW_MESH_PEER_ESTABLISH
- #define DBG_RTW_MESH_PEER_ESTABLISH 0
- #endif
- struct sta_priv *stapriv = &adapter->stapriv;
- struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
- u8 *tlv_ies;
- u16 tlv_ieslen;
- struct rtw_ieee802_11_elems elems;
- _irqL irqL;
- int i;
- int ret = _FAIL;
- if (!plink->rx_conf_ies || !plink->rx_conf_ies_len) {
- RTW_INFO(FUNC_ADPT_FMT" no rx confirm from sta "MAC_FMT"\n"
- , FUNC_ADPT_ARG(adapter), MAC_ARG(sta->cmn.mac_addr));
- goto exit;
- }
- if (plink->rx_conf_ies_len < 4) {
- RTW_INFO(FUNC_ADPT_FMT" confirm from sta "MAC_FMT" too short\n"
- , FUNC_ADPT_ARG(adapter), MAC_ARG(sta->cmn.mac_addr));
- goto exit;
- }
- #ifdef CONFIG_RTW_MESH_DRIVER_AID
- if (!plink->tx_conf_ies || !plink->tx_conf_ies_len) {
- RTW_INFO(FUNC_ADPT_FMT" no tx confirm to sta "MAC_FMT"\n"
- , FUNC_ADPT_ARG(adapter), MAC_ARG(sta->cmn.mac_addr));
- goto exit;
- }
- if (plink->tx_conf_ies_len < 4) {
- RTW_INFO(FUNC_ADPT_FMT" confirm to sta "MAC_FMT" too short\n"
- , FUNC_ADPT_ARG(adapter), MAC_ARG(sta->cmn.mac_addr));
- goto exit;
- }
- #endif
- tlv_ies = plink->rx_conf_ies + 4;
- tlv_ieslen = plink->rx_conf_ies_len - 4;
- if (DBG_RTW_MESH_PEER_ESTABLISH)
- dump_ies(RTW_DBGDUMP, tlv_ies, tlv_ieslen);
- if (rtw_ieee802_11_parse_elems(tlv_ies, tlv_ieslen, &elems, 1) == ParseFailed) {
- RTW_INFO(FUNC_ADPT_FMT" sta "MAC_FMT" sent invalid confirm\n"
- , FUNC_ADPT_ARG(adapter), MAC_ARG(sta->cmn.mac_addr));
- goto exit;
- }
- SET_PEER_CONF_DISABLED(plink);
- if (rtw_bss_is_cto_mgate(&plink->scanned->network)
- && !rtw_bss_is_forwarding(&plink->scanned->network))
- SET_CTO_MGATE_CONF_END_TIME(plink, mcfg->peer_sel_policy.cto_mgate_conf_timeout_ms);
- else
- SET_CTO_MGATE_CONF_DISABLED(plink);
- sta->state &= (~WIFI_FW_AUTH_SUCCESS);
- sta->state |= WIFI_FW_ASSOC_STATE;
- rtw_ap_parse_sta_capability(adapter, sta, plink->rx_conf_ies);
- if (rtw_ap_parse_sta_supported_rates(adapter, sta, tlv_ies, tlv_ieslen) != _STATS_SUCCESSFUL_)
- goto exit;
-
- if (rtw_ap_parse_sta_security_ie(adapter, sta, &elems) != _STATS_SUCCESSFUL_)
- goto exit;
- rtw_ap_parse_sta_wmm_ie(adapter, sta, tlv_ies, tlv_ieslen);
- rtw_ap_parse_sta_ht_ie(adapter, sta, &elems);
- rtw_ap_parse_sta_vht_ie(adapter, sta, &elems);
- /* AID */
- #ifdef CONFIG_RTW_MESH_DRIVER_AID
- sta->cmn.aid = RTW_GET_LE16(plink->tx_conf_ies + 2);
- #else
- sta->cmn.aid = plink->aid;
- #endif
- stapriv->sta_aid[sta->cmn.aid - 1] = sta;
- RTW_INFO(FUNC_ADPT_FMT" sta "MAC_FMT" aid:%u\n"
- , FUNC_ADPT_ARG(adapter), MAC_ARG(sta->cmn.mac_addr), sta->cmn.aid);
- sta->state &= (~WIFI_FW_ASSOC_STATE);
- sta->state |= WIFI_FW_ASSOC_SUCCESS;
- sta->local_mps = RTW_MESH_PS_ACTIVE;
- rtw_ewma_err_rate_init(&sta->metrics.err_rate);
- rtw_ewma_err_rate_add(&sta->metrics.err_rate, 1);
- /* init data_rate to 1M */
- sta->metrics.data_rate = 10;
- _enter_critical_bh(&stapriv->asoc_list_lock, &irqL);
- if (rtw_is_list_empty(&sta->asoc_list)) {
- STA_SET_MESH_PLINK(sta, plink);
- /* TBD: up layer timeout mechanism */
- /* sta->expire_to = mcfg->plink_timeout / 2; */
- rtw_list_insert_tail(&sta->asoc_list, &stapriv->asoc_list);
- stapriv->asoc_list_cnt++;
- }
- _exit_critical_bh(&stapriv->asoc_list_lock, &irqL);
- bss_cap_update_on_sta_join(adapter, sta);
- sta_info_update(adapter, sta);
- report_add_sta_event(adapter, sta->cmn.mac_addr);
- ret = _SUCCESS;
- exit:
- return ret;
- }
- void rtw_mesh_expire_peer_notify(_adapter *adapter, const u8 *peer_addr)
- {
- u8 null_ssid[2] = {0, 0};
- #ifdef CONFIG_IOCTL_CFG80211
- rtw_cfg80211_notify_new_peer_candidate(adapter->rtw_wdev
- , peer_addr
- , null_ssid
- , 2
- , GFP_ATOMIC
- );
- #endif
- exit:
- return;
- }
- static u8 *rtw_mesh_construct_peer_mesh_close(_adapter *adapter, struct mesh_plink_ent *plink, u16 reason, u32 *len)
- {
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- u8 *frame = NULL, *pos;
- u32 flen;
- struct rtw_ieee80211_hdr *whdr;
- if (minfo->mesh_auth_id && !MESH_PLINK_AEK_VALID(plink))
- goto exit;
- flen = sizeof(struct rtw_ieee80211_hdr_3addr)
- + 2 /* category, action */
- + 2 + minfo->mesh_id_len /* mesh id */
- + 2 + 8 + (minfo->mesh_auth_id ? 16 : 0) /* mpm */
- + (minfo->mesh_auth_id ? 2 + AES_BLOCK_SIZE : 0) /* mic */
- + (minfo->mesh_auth_id ? 70 : 0) /* ampe */
- ;
- pos = frame = rtw_zmalloc(flen);
- if (!frame)
- goto exit;
- whdr = (struct rtw_ieee80211_hdr *)frame;
- _rtw_memcpy(whdr->addr1, adapter_mac_addr(adapter), ETH_ALEN);
- _rtw_memcpy(whdr->addr2, plink->addr, ETH_ALEN);
- _rtw_memcpy(whdr->addr3, adapter_mac_addr(adapter), ETH_ALEN);
- set_frame_sub_type(frame, WIFI_ACTION);
- pos += sizeof(struct rtw_ieee80211_hdr_3addr);
- *(pos++) = RTW_WLAN_CATEGORY_SELF_PROTECTED;
- *(pos++) = RTW_ACT_SELF_PROTECTED_MESH_CLOSE;
- pos = rtw_set_ie_mesh_id(pos, NULL, minfo->mesh_id, minfo->mesh_id_len);
- pos = rtw_set_ie_mpm(pos, NULL
- , minfo->mesh_auth_id ? 1 : 0
- , plink->plid
- , &plink->llid
- , &reason
- , minfo->mesh_auth_id ? plink->chosen_pmk : NULL);
- #ifdef CONFIG_RTW_MESH_AEK
- if (minfo->mesh_auth_id) {
- u8 ampe_buf[70];
- int enc_ret;
- *pos = WLAN_EID_MIC;
- *(pos + 1) = AES_BLOCK_SIZE;
- ampe_buf[0] = WLAN_EID_AMPE;
- ampe_buf[1] = 68;
- _rtw_memcpy(ampe_buf + 2, plink->sel_pcs, 4);
- _rtw_memcpy(ampe_buf + 6, plink->p_nonce, 32);
- _rtw_memcpy(ampe_buf + 38, plink->l_nonce, 32);
- enc_ret = rtw_mpm_ampe_enc(adapter, plink
- , frame + sizeof(struct rtw_ieee80211_hdr_3addr)
- , pos, ampe_buf, 1);
- if (enc_ret != _SUCCESS) {
- rtw_mfree(frame, flen);
- frame = NULL;
- goto exit;
- }
- }
- #endif
- *len = flen;
- exit:
- return frame;
- }
- void _rtw_mesh_expire_peer_ent(_adapter *adapter, struct mesh_plink_ent *plink)
- {
- #if defined(CONFIG_RTW_MESH_STA_DEL_DISASOC)
- _rtw_mesh_plink_del_ent(adapter, plink);
- rtw_cfg80211_indicate_sta_disassoc(adapter, plink->addr, 0);
- #else
- u8 *frame = NULL;
- u32 flen;
- if (plink->plink_state == RTW_MESH_PLINK_ESTAB)
- frame = rtw_mesh_construct_peer_mesh_close(adapter, plink, WLAN_REASON_MESH_CLOSE, &flen);
- if (frame) {
- struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
- struct wireless_dev *wdev = adapter->rtw_wdev;
- s32 freq = rtw_ch2freq(mlmeext->cur_channel);
- #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)
- rtw_cfg80211_rx_mgmt(wdev, freq, 0, frame, flen, GFP_ATOMIC);
- #else
- cfg80211_rx_action(adapter->pnetdev, freq, frame, flen, GFP_ATOMIC);
- #endif
- rtw_mfree(frame, flen);
- } else {
- rtw_mesh_expire_peer_notify(adapter, plink->addr);
- RTW_INFO(FUNC_ADPT_FMT" set "MAC_FMT" plink unknown\n"
- , FUNC_ADPT_ARG(adapter), MAC_ARG(plink->addr));
- plink->plink_state = RTW_MESH_PLINK_UNKNOWN;
- }
- #endif
- }
- void rtw_mesh_expire_peer(_adapter *adapter, const u8 *peer_addr)
- {
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
- struct mesh_plink_ent *plink;
- _irqL irqL;
- _enter_critical_bh(&(plink_ctl->lock), &irqL);
- plink = _rtw_mesh_plink_get(adapter, peer_addr);
- if (!plink)
- goto exit;
- _rtw_mesh_expire_peer_ent(adapter, plink);
- exit:
- _exit_critical_bh(&(plink_ctl->lock), &irqL);
- }
- u8 rtw_mesh_ps_annc(_adapter *adapter, u8 ps)
- {
- _irqL irqL;
- _list *head, *list;
- struct sta_info *sta;
- struct sta_priv *stapriv = &adapter->stapriv;
- u8 sta_alive_num = 0, i;
- char sta_alive_list[NUM_STA];
- u8 annc_cnt = 0;
- if (rtw_linked_check(adapter) == _FALSE)
- goto exit;
- _enter_critical_bh(&stapriv->asoc_list_lock, &irqL);
- head = &stapriv->asoc_list;
- list = get_next(head);
- while ((rtw_end_of_queue_search(head, list)) == _FALSE) {
- int stainfo_offset;
- sta = LIST_CONTAINOR(list, struct sta_info, asoc_list);
- list = get_next(list);
- stainfo_offset = rtw_stainfo_offset(stapriv, sta);
- if (stainfo_offset_valid(stainfo_offset))
- sta_alive_list[sta_alive_num++] = stainfo_offset;
- }
- _exit_critical_bh(&stapriv->asoc_list_lock, &irqL);
- for (i = 0; i < sta_alive_num; i++) {
- sta = rtw_get_stainfo_by_offset(stapriv, sta_alive_list[i]);
- if (!sta)
- continue;
- issue_qos_nulldata(adapter, sta->cmn.mac_addr, 7, ps, 3, 500);
- annc_cnt++;
- }
- exit:
- return annc_cnt;
- }
- static void mpath_tx_tasklet_hdl(void *priv)
- {
- _adapter *adapter = (_adapter *)priv;
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- struct xmit_frame *xframe;
- _list *list, *head;
- _list tmp;
- u32 tmp_len;
- s32 res;
- _rtw_init_listhead(&tmp);
- while (1) {
- tmp_len = 0;
- enter_critical_bh(&minfo->mpath_tx_queue.lock);
- if (minfo->mpath_tx_queue_len) {
- rtw_list_splice_init(&minfo->mpath_tx_queue.queue, &tmp);
- tmp_len = minfo->mpath_tx_queue_len;
- minfo->mpath_tx_queue_len = 0;
- }
- exit_critical_bh(&minfo->mpath_tx_queue.lock);
- if (!tmp_len)
- break;
- head = &tmp;
- list = get_next(head);
- while (rtw_end_of_queue_search(head, list) == _FALSE) {
- xframe = LIST_CONTAINOR(list, struct xmit_frame, list);
- list = get_next(list);
- rtw_list_delete(&xframe->list);
- res = rtw_xmit_posthandle(adapter, xframe, xframe->pkt);
- if (res < 0) {
- #ifdef DBG_TX_DROP_FRAME
- RTW_INFO("DBG_TX_DROP_FRAME %s rtw_xmit fail\n", __FUNCTION__);
- #endif
- adapter->xmitpriv.tx_drop++;
- }
- }
- }
- }
- static void rtw_mpath_tx_queue_flush(_adapter *adapter)
- {
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- struct xmit_frame *xframe;
- _list *list, *head;
- _list tmp;
- _rtw_init_listhead(&tmp);
- enter_critical_bh(&minfo->mpath_tx_queue.lock);
- rtw_list_splice_init(&minfo->mpath_tx_queue.queue, &tmp);
- minfo->mpath_tx_queue_len = 0;
- exit_critical_bh(&minfo->mpath_tx_queue.lock);
- head = &tmp;
- list = get_next(head);
- while (rtw_end_of_queue_search(head, list) == _FALSE) {
- xframe = LIST_CONTAINOR(list, struct xmit_frame, list);
- list = get_next(list);
- rtw_list_delete(&xframe->list);
- rtw_free_xmitframe(&adapter->xmitpriv, xframe);
- }
- }
- #ifdef PLATFORM_LINUX /* 3.10 ~ 4.13 checked */
- #if defined(CONFIG_SLUB)
- #include <linux/slub_def.h>
- #elif defined(CONFIG_SLAB)
- #include <linux/slab_def.h>
- #endif
- typedef struct kmem_cache rtw_mcache;
- #endif
- rtw_mcache *rtw_mcache_create(const char *name, size_t size)
- {
- #ifdef PLATFORM_LINUX /* 3.10 ~ 4.13 checked */
- return kmem_cache_create(name, size, 0, 0, NULL);
- #else
- #error "TBD\n";
- #endif
- }
- void rtw_mcache_destroy(rtw_mcache *s)
- {
- #ifdef PLATFORM_LINUX /* 3.10 ~ 4.13 checked */
- kmem_cache_destroy(s);
- #else
- #error "TBD\n";
- #endif
- }
- void *_rtw_mcache_alloc(rtw_mcache *cachep)
- {
- #ifdef PLATFORM_LINUX /* 3.10 ~ 4.13 checked */
- return kmem_cache_alloc(cachep, GFP_ATOMIC);
- #else
- #error "TBD\n";
- #endif
- }
- void _rtw_mcache_free(rtw_mcache *cachep, void *objp)
- {
- #ifdef PLATFORM_LINUX /* 3.10 ~ 4.13 checked */
- kmem_cache_free(cachep, objp);
- #else
- #error "TBD\n";
- #endif
- }
- #ifdef DBG_MEM_ALLOC
- inline void *dbg_rtw_mcache_alloc(rtw_mcache *cachep, const enum mstat_f flags, const char *func, const int line)
- {
- void *p;
- u32 sz = cachep->size;
- if (match_mstat_sniff_rules(flags, sz))
- RTW_INFO("DBG_MEM_ALLOC %s:%d %s(%u)\n", func, line, __func__, sz);
- p = _rtw_mcache_alloc(cachep);
- rtw_mstat_update(
- flags
- , p ? MSTAT_ALLOC_SUCCESS : MSTAT_ALLOC_FAIL
- , sz
- );
- return p;
- }
- inline void dbg_rtw_mcache_free(rtw_mcache *cachep, void *pbuf, const enum mstat_f flags, const char *func, const int line)
- {
- u32 sz = cachep->size;
- if (match_mstat_sniff_rules(flags, sz))
- RTW_INFO("DBG_MEM_ALLOC %s:%d %s(%u)\n", func, line, __func__, sz);
- _rtw_mcache_free(cachep, pbuf);
- rtw_mstat_update(
- flags
- , MSTAT_FREE
- , sz
- );
- }
- #define rtw_mcache_alloc(cachep) dbg_rtw_mcache_alloc(cachep, MSTAT_TYPE_PHY, __FUNCTION__, __LINE__)
- #define rtw_mcache_free(cachep, objp) dbg_rtw_mcache_free(cachep, objp, MSTAT_TYPE_PHY, __FUNCTION__, __LINE__)
- #else
- #define rtw_mcache_alloc(cachep) _rtw_mcache_alloc(cachep)
- #define rtw_mcache_free(cachep, objp) _rtw_mcache_free(cachep, objp)
- #endif /* DBG_MEM_ALLOC */
- /* Mesh Received Cache */
- #define RTW_MRC_BUCKETS 256 /* must be a power of 2 */
- #define RTW_MRC_QUEUE_MAX_LEN 4
- #define RTW_MRC_TIMEOUT_MS (3 * 1000)
- /**
- * struct rtw_mrc_entry - entry in the Mesh Received Cache
- *
- * @seqnum: mesh sequence number of the frame
- * @exp_time: expiration time of the entry
- * @msa: mesh source address of the frame
- * @list: hashtable list pointer
- *
- * The Mesh Received Cache keeps track of the latest received frames that
- * have been received by a mesh interface and discards received frames
- * that are found in the cache.
- */
- struct rtw_mrc_entry {
- rtw_hlist_node list;
- systime exp_time;
- u32 seqnum;
- u8 msa[ETH_ALEN];
- };
- struct rtw_mrc {
- rtw_hlist_head bucket[RTW_MRC_BUCKETS];
- u32 idx_mask;
- rtw_mcache *cache;
- };
- static int rtw_mrc_init(_adapter *adapter)
- {
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- char cache_name[IFNAMSIZ + 8 + 1];
- int i;
- minfo->mrc = rtw_malloc(sizeof(struct rtw_mrc));
- if (!minfo->mrc)
- return -ENOMEM;
- minfo->mrc->idx_mask = RTW_MRC_BUCKETS - 1;
- for (i = 0; i < RTW_MRC_BUCKETS; i++)
- rtw_hlist_head_init(&minfo->mrc->bucket[i]);
- sprintf(cache_name, "rtw_mrc_%s", ADPT_ARG(adapter));
- minfo->mrc->cache = rtw_mcache_create(cache_name, sizeof(struct rtw_mrc_entry));
- return 0;
- }
- static void rtw_mrc_free(_adapter *adapter)
- {
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- struct rtw_mrc *mrc = minfo->mrc;
- struct rtw_mrc_entry *p;
- rtw_hlist_node *np, *n;
- int i;
- if (!mrc)
- return;
- for (i = 0; i < RTW_MRC_BUCKETS; i++) {
- rtw_hlist_for_each_entry_safe(p, np, n, &mrc->bucket[i], list) {
- rtw_hlist_del(&p->list);
- rtw_mcache_free(mrc->cache, p);
- }
- }
- rtw_mcache_destroy(mrc->cache);
- rtw_mfree(mrc, sizeof(struct rtw_mrc));
- minfo->mrc = NULL;
- }
- /**
- * rtw_mrc_check - Check frame in mesh received cache and add if absent.
- *
- * @adapter: interface
- * @msa: mesh source address
- * @seq: mesh seq number
- *
- * Returns: 0 if the frame is not in the cache, nonzero otherwise.
- *
- * Checks using the mesh source address and the mesh sequence number if we have
- * received this frame lately. If the frame is not in the cache, it is added to
- * it.
- */
- static int rtw_mrc_check(_adapter *adapter, const u8 *msa, u32 seq)
- {
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- struct rtw_mrc *mrc = minfo->mrc;
- int entries = 0;
- u8 idx;
- struct rtw_mrc_entry *p;
- rtw_hlist_node *np, *n;
- u8 timeout;
- if (!mrc)
- return -1;
- idx = seq & mrc->idx_mask;
- rtw_hlist_for_each_entry_safe(p, np, n, &mrc->bucket[idx], list) {
- ++entries;
- timeout = rtw_time_after(rtw_get_current_time(), p->exp_time);
- if (timeout || entries == RTW_MRC_QUEUE_MAX_LEN) {
- if (!timeout)
- minfo->mshstats.mrc_del_qlen++;
- rtw_hlist_del(&p->list);
- rtw_mcache_free(mrc->cache, p);
- --entries;
- } else if ((seq == p->seqnum) && _rtw_memcmp(msa, p->msa, ETH_ALEN) == _TRUE)
- return -1;
- }
- p = rtw_mcache_alloc(mrc->cache);
- if (!p)
- return 0;
- p->seqnum = seq;
- p->exp_time = rtw_get_current_time() + rtw_ms_to_systime(RTW_MRC_TIMEOUT_MS);
- _rtw_memcpy(p->msa, msa, ETH_ALEN);
- rtw_hlist_add_head(&p->list, &mrc->bucket[idx]);
- return 0;
- }
- static int rtw_mesh_decache(_adapter *adapter, const u8 *msa, u32 seq)
- {
- return rtw_mrc_check(adapter, msa, seq);
- }
- #ifndef RTW_MESH_SCAN_RESULT_EXP_MS
- #define RTW_MESH_SCAN_RESULT_EXP_MS (10 * 1000)
- #endif
- #ifndef RTW_MESH_ACNODE_PREVENT
- #define RTW_MESH_ACNODE_PREVENT 0
- #endif
- #ifndef RTW_MESH_ACNODE_CONF_TIMEOUT_MS
- #define RTW_MESH_ACNODE_CONF_TIMEOUT_MS (20 * 1000)
- #endif
- #ifndef RTW_MESH_ACNODE_NOTIFY_TIMEOUT_MS
- #define RTW_MESH_ACNODE_NOTIFY_TIMEOUT_MS (2 * 1000)
- #endif
- #ifndef RTW_MESH_OFFCH_CAND
- #define RTW_MESH_OFFCH_CAND 1
- #endif
- #ifndef RTW_MESH_OFFCH_CAND_FIND_INT_MS
- #define RTW_MESH_OFFCH_CAND_FIND_INT_MS (10 * 1000)
- #endif
- #ifndef RTW_MESH_PEER_CONF_TIMEOUT_MS
- #define RTW_MESH_PEER_CONF_TIMEOUT_MS (20 * 1000)
- #endif
- #ifndef RTW_MESH_PEER_BLACKLIST_TIMEOUT_MS
- #define RTW_MESH_PEER_BLACKLIST_TIMEOUT_MS (20 * 1000)
- #endif
- #ifndef RTW_MESH_CTO_MGATE_REQUIRE
- #define RTW_MESH_CTO_MGATE_REQUIRE 0
- #endif
- #ifndef RTW_MESH_CTO_MGATE_CONF_TIMEOUT_MS
- #define RTW_MESH_CTO_MGATE_CONF_TIMEOUT_MS (20 * 1000)
- #endif
- #ifndef RTW_MESH_CTO_MGATE_BLACKLIST_TIMEOUT_MS
- #define RTW_MESH_CTO_MGATE_BLACKLIST_TIMEOUT_MS (20 * 1000)
- #endif
- void rtw_mesh_cfg_init_peer_sel_policy(struct rtw_mesh_cfg *mcfg)
- {
- struct mesh_peer_sel_policy *sel_policy = &mcfg->peer_sel_policy;
- sel_policy->scanr_exp_ms = RTW_MESH_SCAN_RESULT_EXP_MS;
- #if CONFIG_RTW_MESH_ACNODE_PREVENT
- sel_policy->acnode_prevent = RTW_MESH_ACNODE_PREVENT;
- sel_policy->acnode_conf_timeout_ms = RTW_MESH_ACNODE_CONF_TIMEOUT_MS;
- sel_policy->acnode_notify_timeout_ms = RTW_MESH_ACNODE_NOTIFY_TIMEOUT_MS;
- #endif
- #if CONFIG_RTW_MESH_OFFCH_CAND
- sel_policy->offch_cand = RTW_MESH_OFFCH_CAND;
- sel_policy->offch_find_int_ms = RTW_MESH_OFFCH_CAND_FIND_INT_MS;
- #endif
- #if CONFIG_RTW_MESH_PEER_BLACKLIST
- sel_policy->peer_conf_timeout_ms = RTW_MESH_PEER_CONF_TIMEOUT_MS;
- sel_policy->peer_blacklist_timeout_ms = RTW_MESH_PEER_BLACKLIST_TIMEOUT_MS;
- #endif
- #if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
- sel_policy->cto_mgate_require = RTW_MESH_CTO_MGATE_REQUIRE;
- sel_policy->cto_mgate_conf_timeout_ms = RTW_MESH_CTO_MGATE_CONF_TIMEOUT_MS;
- sel_policy->cto_mgate_blacklist_timeout_ms = RTW_MESH_CTO_MGATE_BLACKLIST_TIMEOUT_MS;
- #endif
- }
- void rtw_mesh_cfg_init(_adapter *adapter)
- {
- struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
- mcfg->max_peer_links = RTW_MESH_MAX_PEER_LINKS;
- mcfg->plink_timeout = RTW_MESH_PEER_LINK_TIMEOUT;
- mcfg->dot11MeshTTL = RTW_MESH_TTL;
- mcfg->element_ttl = RTW_MESH_DEFAULT_ELEMENT_TTL;
- mcfg->dot11MeshHWMPmaxPREQretries = RTW_MESH_MAX_PREQ_RETRIES;
- mcfg->path_refresh_time = RTW_MESH_PATH_REFRESH_TIME;
- mcfg->min_discovery_timeout = RTW_MESH_MIN_DISCOVERY_TIMEOUT;
- mcfg->dot11MeshHWMPactivePathTimeout = RTW_MESH_PATH_TIMEOUT;
- mcfg->dot11MeshHWMPpreqMinInterval = RTW_MESH_PREQ_MIN_INT;
- mcfg->dot11MeshHWMPperrMinInterval = RTW_MESH_PERR_MIN_INT;
- mcfg->dot11MeshHWMPnetDiameterTraversalTime = RTW_MESH_DIAM_TRAVERSAL_TIME;
- mcfg->dot11MeshHWMPRootMode = RTW_IEEE80211_ROOTMODE_NO_ROOT;
- mcfg->dot11MeshHWMPRannInterval = RTW_MESH_RANN_INTERVAL;
- mcfg->dot11MeshGateAnnouncementProtocol = _FALSE;
- mcfg->dot11MeshForwarding = _TRUE;
- mcfg->rssi_threshold = 0;
- mcfg->dot11MeshHWMPactivePathToRootTimeout = RTW_MESH_PATH_TO_ROOT_TIMEOUT;
- mcfg->dot11MeshHWMProotInterval = RTW_MESH_ROOT_INTERVAL;
- mcfg->dot11MeshHWMPconfirmationInterval = RTW_MESH_ROOT_CONFIRMATION_INTERVAL;
- mcfg->path_gate_timeout_factor = 3;
- rtw_mesh_cfg_init_peer_sel_policy(mcfg);
- #ifdef CONFIG_RTW_MESH_ADD_ROOT_CHK
- mcfg->sane_metric_delta = RTW_MESH_SANE_METRIC_DELTA;
- mcfg->max_root_add_chk_cnt = RTW_MESH_MAX_ROOT_ADD_CHK_CNT;
- #endif
- #if CONFIG_RTW_MESH_DATA_BMC_TO_UC
- mcfg->b2u_flags_msrc = 0;
- mcfg->b2u_flags_mfwd = RTW_MESH_B2U_GA_UCAST;
- #endif
- }
- void rtw_mesh_cfg_init_max_peer_links(_adapter *adapter, u8 stack_conf)
- {
- struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
- mcfg->max_peer_links = RTW_MESH_MAX_PEER_LINKS;
- if (mcfg->max_peer_links > stack_conf)
- mcfg->max_peer_links = stack_conf;
- }
- void rtw_mesh_cfg_init_plink_timeout(_adapter *adapter, u32 stack_conf)
- {
- struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
- mcfg->plink_timeout = stack_conf;
- }
- void rtw_mesh_init_mesh_info(_adapter *adapter)
- {
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- _rtw_memset(minfo, 0, sizeof(struct rtw_mesh_info));
- rtw_mesh_plink_ctl_init(adapter);
-
- minfo->last_preq = rtw_get_current_time();
- /* minfo->last_sn_update = rtw_get_current_time(); */
- minfo->next_perr = rtw_get_current_time();
-
- ATOMIC_SET(&minfo->mpaths, 0);
- rtw_mesh_pathtbl_init(adapter);
- _rtw_init_queue(&minfo->mpath_tx_queue);
- tasklet_init(&minfo->mpath_tx_tasklet
- , (void(*)(unsigned long))mpath_tx_tasklet_hdl
- , (unsigned long)adapter);
- rtw_mrc_init(adapter);
- _rtw_init_listhead(&minfo->preq_queue.list);
- _rtw_spinlock_init(&minfo->mesh_preq_queue_lock);
-
- rtw_init_timer(&adapter->mesh_path_timer, adapter, rtw_ieee80211_mesh_path_timer, adapter);
- rtw_init_timer(&adapter->mesh_path_root_timer, adapter, rtw_ieee80211_mesh_path_root_timer, adapter);
- rtw_init_timer(&adapter->mesh_atlm_param_req_timer, adapter, rtw_mesh_atlm_param_req_timer, adapter);
- _init_workitem(&adapter->mesh_work, rtw_mesh_work_hdl, NULL);
- }
- void rtw_mesh_deinit_mesh_info(_adapter *adapter)
- {
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- tasklet_kill(&minfo->mpath_tx_tasklet);
- rtw_mpath_tx_queue_flush(adapter);
- _rtw_deinit_queue(&adapter->mesh_info.mpath_tx_queue);
- rtw_mrc_free(adapter);
- rtw_mesh_pathtbl_unregister(adapter);
- rtw_mesh_plink_ctl_deinit(adapter);
- _cancel_workitem_sync(&adapter->mesh_work);
- _cancel_timer_ex(&adapter->mesh_path_timer);
- _cancel_timer_ex(&adapter->mesh_path_root_timer);
- _cancel_timer_ex(&adapter->mesh_atlm_param_req_timer);
- }
- /**
- * rtw_mesh_nexthop_resolve - lookup next hop; conditionally start path discovery
- *
- * @skb: 802.11 frame to be sent
- * @sdata: network subif the frame will be sent through
- *
- * Lookup next hop for given skb and start path discovery if no
- * forwarding information is found.
- *
- * Returns: 0 if the next hop was found and -ENOENT if the frame was queued.
- * skb is freeed here if no mpath could be allocated.
- */
- int rtw_mesh_nexthop_resolve(_adapter *adapter,
- struct xmit_frame *xframe)
- {
- struct pkt_attrib *attrib = &xframe->attrib;
- struct rtw_mesh_path *mpath;
- struct xmit_frame *xframe_to_free = NULL;
- u8 *target_addr = attrib->mda;
- int err = 0;
- int ret = _SUCCESS;
- rtw_rcu_read_lock();
- err = rtw_mesh_nexthop_lookup(adapter, target_addr, attrib->msa, attrib->ra);
- if (!err)
- goto endlookup;
- /* no nexthop found, start resolving */
- mpath = rtw_mesh_path_lookup(adapter, target_addr);
- if (!mpath) {
- mpath = rtw_mesh_path_add(adapter, target_addr);
- if (IS_ERR(mpath)) {
- xframe->pkt = NULL; /* free pkt outside */
- rtw_mesh_path_discard_frame(adapter, xframe);
- err = PTR_ERR(mpath);
- ret = _FAIL;
- goto endlookup;
- }
- }
- if (!(mpath->flags & RTW_MESH_PATH_RESOLVING))
- rtw_mesh_queue_preq(mpath, RTW_PREQ_Q_F_START);
- enter_critical_bh(&mpath->frame_queue.lock);
- if (mpath->frame_queue_len >= RTW_MESH_FRAME_QUEUE_LEN) {
- xframe_to_free = LIST_CONTAINOR(get_next(get_list_head(&mpath->frame_queue)), struct xmit_frame, list);
- rtw_list_delete(&(xframe_to_free->list));
- mpath->frame_queue_len--;
- }
- rtw_list_insert_tail(&xframe->list, get_list_head(&mpath->frame_queue));
- mpath->frame_queue_len++;
- exit_critical_bh(&mpath->frame_queue.lock);
- ret = RTW_RA_RESOLVING;
- if (xframe_to_free)
- rtw_mesh_path_discard_frame(adapter, xframe_to_free);
- endlookup:
- rtw_rcu_read_unlock();
- return ret;
- }
- /**
- * rtw_mesh_nexthop_lookup - put the appropriate next hop on a mesh frame. Calling
- * this function is considered "using" the associated mpath, so preempt a path
- * refresh if this mpath expires soon.
- *
- * @skb: 802.11 frame to be sent
- * @sdata: network subif the frame will be sent through
- *
- * Returns: 0 if the next hop was found. Nonzero otherwise.
- */
- int rtw_mesh_nexthop_lookup(_adapter *adapter,
- const u8 *mda, const u8 *msa, u8 *ra)
- {
- struct rtw_mesh_path *mpath;
- struct sta_info *next_hop;
- const u8 *target_addr = mda;
- int err = -ENOENT;
- rtw_rcu_read_lock();
- mpath = rtw_mesh_path_lookup(adapter, target_addr);
- if (!mpath || !(mpath->flags & RTW_MESH_PATH_ACTIVE))
- goto endlookup;
- if (rtw_time_after(rtw_get_current_time(),
- mpath->exp_time -
- rtw_ms_to_systime(adapter->mesh_cfg.path_refresh_time)) &&
- _rtw_memcmp(adapter_mac_addr(adapter), msa, ETH_ALEN) == _TRUE &&
- !(mpath->flags & RTW_MESH_PATH_RESOLVING) &&
- !(mpath->flags & RTW_MESH_PATH_FIXED)) {
- rtw_mesh_queue_preq(mpath, RTW_PREQ_Q_F_START | RTW_PREQ_Q_F_REFRESH);
- }
- next_hop = rtw_rcu_dereference(mpath->next_hop);
- if (next_hop) {
- _rtw_memcpy(ra, next_hop->cmn.mac_addr, ETH_ALEN);
- err = 0;
- }
- endlookup:
- rtw_rcu_read_unlock();
- return err;
- }
- #if CONFIG_RTW_MESH_DATA_BMC_TO_UC
- static bool rtw_mesh_data_bmc_to_uc(_adapter *adapter
- , const u8 *da, const u8 *sa, const u8 *mda, const u8 *msa
- , u8 ae_need, const u8 *ori_ta, u8 mfwd_ttl
- , _list *b2u_list, u8 *b2u_num, u32 *b2u_mseq)
- {
- struct sta_priv *stapriv = &adapter->stapriv;
- struct xmit_priv *xmitpriv = &adapter->xmitpriv;
- _irqL irqL;
- _list *head, *list;
- struct sta_info *sta;
- char b2u_sta_id[NUM_STA];
- u8 b2u_sta_num = 0;
- bool bmc_need = _FALSE;
- int i;
- _enter_critical_bh(&stapriv->asoc_list_lock, &irqL);
- head = &stapriv->asoc_list;
- list = get_next(head);
- while ((rtw_end_of_queue_search(head, list)) == _FALSE) {
- int stainfo_offset;
- sta = LIST_CONTAINOR(list, struct sta_info, asoc_list);
- list = get_next(list);
-
- stainfo_offset = rtw_stainfo_offset(stapriv, sta);
- if (stainfo_offset_valid(stainfo_offset))
- b2u_sta_id[b2u_sta_num++] = stainfo_offset;
- }
- _exit_critical_bh(&stapriv->asoc_list_lock, &irqL);
- if (!b2u_sta_num)
- goto exit;
- for (i = 0; i < b2u_sta_num; i++) {
- struct xmit_frame *b2uframe;
- struct pkt_attrib *attrib;
- sta = rtw_get_stainfo_by_offset(stapriv, b2u_sta_id[i]);
- if (!(sta->state & _FW_LINKED)
- || _rtw_memcmp(sta->cmn.mac_addr, msa, ETH_ALEN) == _TRUE
- || (ori_ta && _rtw_memcmp(sta->cmn.mac_addr, ori_ta, ETH_ALEN) == _TRUE)
- || is_broadcast_mac_addr(sta->cmn.mac_addr)
- || is_zero_mac_addr(sta->cmn.mac_addr))
- continue;
- b2uframe = rtw_alloc_xmitframe(xmitpriv);
- if (!b2uframe) {
- bmc_need = _TRUE;
- break;
- }
- if ((*b2u_num)++ == 0 && !ori_ta) {
- *b2u_mseq = (cpu_to_le32(adapter->mesh_info.mesh_seqnum));
- adapter->mesh_info.mesh_seqnum++;
- }
- attrib = &b2uframe->attrib;
- attrib->mb2u = 1;
- attrib->mseq = *b2u_mseq;
- attrib->mfwd_ttl = ori_ta ? mfwd_ttl : 0;
- _rtw_memcpy(attrib->ra, sta->cmn.mac_addr, ETH_ALEN);
- _rtw_memcpy(attrib->ta, adapter_mac_addr(adapter), ETH_ALEN);
- _rtw_memcpy(attrib->mda, mda, ETH_ALEN);
- _rtw_memcpy(attrib->msa, msa, ETH_ALEN);
- _rtw_memcpy(attrib->dst, da, ETH_ALEN);
- _rtw_memcpy(attrib->src, sa, ETH_ALEN);
- attrib->mesh_frame_mode = ae_need ? MESH_UCAST_PX_DATA : MESH_UCAST_DATA;
- rtw_list_insert_tail(&b2uframe->list, b2u_list);
- }
- exit:
- return bmc_need;
- }
- void dump_mesh_b2u_flags(void *sel, _adapter *adapter)
- {
- struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
- RTW_PRINT_SEL(sel, "%4s %4s\n", "msrc", "mfwd");
- RTW_PRINT_SEL(sel, "0x%02x 0x%02x\n", mcfg->b2u_flags_msrc, mcfg->b2u_flags_mfwd);
- }
- #endif /* CONFIG_RTW_MESH_DATA_BMC_TO_UC */
- int rtw_mesh_addr_resolve(_adapter *adapter, struct xmit_frame *xframe, _pkt *pkt, _list *b2u_list)
- {
- struct pkt_file pktfile;
- struct ethhdr etherhdr;
- struct pkt_attrib *attrib;
- struct rtw_mesh_path *mpath = NULL, *mppath = NULL;
- u8 is_da_mcast;
- u8 ae_need;
- #if CONFIG_RTW_MESH_DATA_BMC_TO_UC
- bool bmc_need = _TRUE;
- u8 b2u_num = 0;
- u32 b2u_mseq = 0;
- #endif
- int res = _SUCCESS;
- _rtw_open_pktfile(pkt, &pktfile);
- if (_rtw_pktfile_read(&pktfile, (u8 *)ðerhdr, ETH_HLEN) != ETH_HLEN) {
- res = _FAIL;
- goto exit;
- }
-
- xframe->pkt = pkt;
- #if CONFIG_RTW_MESH_DATA_BMC_TO_UC
- _rtw_init_listhead(b2u_list);
- #endif
- is_da_mcast = IS_MCAST(etherhdr.h_dest);
- if (!is_da_mcast) {
- struct sta_info *next_hop;
- bool mpp_lookup = 1;
-
- mpath = rtw_mesh_path_lookup(adapter, etherhdr.h_dest);
- if (mpath) {
- mpp_lookup = 0;
- next_hop = rtw_rcu_dereference(mpath->next_hop);
- if (!next_hop
- || !(mpath->flags & (RTW_MESH_PATH_ACTIVE | RTW_MESH_PATH_RESOLVING))
- ) {
- /* mpath is not valid, search mppath */
- mpp_lookup = 1;
- }
- }
- if (mpp_lookup) {
- mppath = rtw_mpp_path_lookup(adapter, etherhdr.h_dest);
- if (mppath)
- mppath->exp_time = rtw_get_current_time();
- }
- if (mppath && mpath)
- rtw_mesh_path_del(adapter, mpath->dst);
- ae_need = _rtw_memcmp(adapter_mac_addr(adapter), etherhdr.h_source, ETH_ALEN) == _FALSE
- || (mppath && _rtw_memcmp(mppath->mpp, etherhdr.h_dest, ETH_ALEN) == _FALSE);
- } else {
- ae_need = _rtw_memcmp(adapter_mac_addr(adapter), etherhdr.h_source, ETH_ALEN) == _FALSE;
- #if CONFIG_RTW_MESH_DATA_BMC_TO_UC
- if (rtw_msrc_b2u_policy_chk(adapter->mesh_cfg.b2u_flags_msrc, etherhdr.h_dest)) {
- bmc_need = rtw_mesh_data_bmc_to_uc(adapter
- , etherhdr.h_dest, etherhdr.h_source
- , etherhdr.h_dest, adapter_mac_addr(adapter), ae_need, NULL, 0
- , b2u_list, &b2u_num, &b2u_mseq);
- if (bmc_need == _FALSE) {
- res = RTW_BMC_NO_NEED;
- goto exit;
- }
- }
- #endif
- }
- attrib = &xframe->attrib;
- #if CONFIG_RTW_MESH_DATA_BMC_TO_UC
- if (b2u_num) {
- attrib->mb2u = 1;
- attrib->mseq = b2u_mseq;
- } else
- attrib->mb2u = 0;
- #endif
- attrib->mfwd_ttl = 0;
- _rtw_memcpy(attrib->dst, etherhdr.h_dest, ETH_ALEN);
- _rtw_memcpy(attrib->src, etherhdr.h_source, ETH_ALEN);
- _rtw_memcpy(attrib->ta, adapter_mac_addr(adapter), ETH_ALEN);
- if (is_da_mcast) {
- attrib->mesh_frame_mode = ae_need ? MESH_BMCAST_PX_DATA : MESH_BMCAST_DATA;
- _rtw_memcpy(attrib->ra, attrib->dst, ETH_ALEN);
- _rtw_memcpy(attrib->msa, adapter_mac_addr(adapter), ETH_ALEN);
- } else {
- attrib->mesh_frame_mode = ae_need ? MESH_UCAST_PX_DATA : MESH_UCAST_DATA;
- _rtw_memcpy(attrib->mda, (mppath && ae_need) ? mppath->mpp : attrib->dst, ETH_ALEN);
- _rtw_memcpy(attrib->msa, adapter_mac_addr(adapter), ETH_ALEN);
- /* RA needs to be resolved */
- res = rtw_mesh_nexthop_resolve(adapter, xframe);
- }
- exit:
- return res;
- }
- s8 rtw_mesh_tx_set_whdr_mctrl_len(u8 mesh_frame_mode, struct pkt_attrib *attrib)
- {
- u8 ret = 0;
- switch (mesh_frame_mode) {
- case MESH_UCAST_DATA:
- attrib->hdrlen = WLAN_HDR_A4_QOS_LEN;
- /* mesh flag + mesh TTL + Mesh SN. no ext addr. */
- attrib->meshctrl_len = 6;
- break;
- case MESH_BMCAST_DATA:
- attrib->hdrlen = WLAN_HDR_A3_QOS_LEN;
- /* mesh flag + mesh TTL + Mesh SN. no ext addr. */
- attrib->meshctrl_len = 6;
- break;
- case MESH_UCAST_PX_DATA:
- attrib->hdrlen = WLAN_HDR_A4_QOS_LEN;
- /* mesh flag + mesh TTL + Mesh SN + extaddr1 + extaddr2. */
- attrib->meshctrl_len = 18;
- break;
- case MESH_BMCAST_PX_DATA:
- attrib->hdrlen = WLAN_HDR_A3_QOS_LEN;
- /* mesh flag + mesh TTL + Mesh SN + extaddr1 */
- attrib->meshctrl_len = 12;
- break;
- default:
- RTW_WARN("Invalid mesh frame mode:%u\n", mesh_frame_mode);
- ret = -1;
- break;
- }
- return ret;
- }
- void rtw_mesh_tx_build_mctrl(_adapter *adapter, struct pkt_attrib *attrib, u8 *buf)
- {
- struct rtw_ieee80211s_hdr *mctrl = (struct rtw_ieee80211s_hdr *)buf;
- _rtw_memset(mctrl, 0, XATTRIB_GET_MCTRL_LEN(attrib));
- if (attrib->mfwd_ttl
- #if CONFIG_RTW_MESH_DATA_BMC_TO_UC
- || attrib->mb2u
- #endif
- ) {
- #if CONFIG_RTW_MESH_DATA_BMC_TO_UC
- if (!attrib->mfwd_ttl)
- mctrl->ttl = adapter->mesh_cfg.dot11MeshTTL;
- else
- #endif
- mctrl->ttl = attrib->mfwd_ttl;
- mctrl->seqnum = (cpu_to_le32(attrib->mseq));
- } else {
- mctrl->ttl = adapter->mesh_cfg.dot11MeshTTL;
- mctrl->seqnum = (cpu_to_le32(adapter->mesh_info.mesh_seqnum));
- adapter->mesh_info.mesh_seqnum++;
- }
- switch (attrib->mesh_frame_mode){
- case MESH_UCAST_DATA:
- case MESH_BMCAST_DATA:
- break;
- case MESH_UCAST_PX_DATA:
- mctrl->flags |= MESH_FLAGS_AE_A5_A6;
- _rtw_memcpy(mctrl->eaddr1, attrib->dst, ETH_ALEN);
- _rtw_memcpy(mctrl->eaddr2, attrib->src, ETH_ALEN);
- break;
- case MESH_BMCAST_PX_DATA:
- mctrl->flags |= MESH_FLAGS_AE_A4;
- _rtw_memcpy(mctrl->eaddr1, attrib->src, ETH_ALEN);
- break;
- case MESH_MHOP_UCAST_ACT:
- /* TBD */
- break;
- case MESH_MHOP_BMCAST_ACT:
- /* TBD */
- break;
- default:
- break;
- }
- }
- u8 rtw_mesh_tx_build_whdr(_adapter *adapter, struct pkt_attrib *attrib
- , u16 *fctrl, struct rtw_ieee80211_hdr *whdr)
- {
- switch (attrib->mesh_frame_mode) {
- case MESH_UCAST_DATA: /* 1, 1, RA, TA, mDA(=DA), mSA(=SA) */
- case MESH_UCAST_PX_DATA: /* 1, 1, RA, TA, mDA, mSA, [DA, SA] */
- SetToDs(fctrl);
- SetFrDs(fctrl);
- _rtw_memcpy(whdr->addr1, attrib->ra, ETH_ALEN);
- _rtw_memcpy(whdr->addr2, attrib->ta, ETH_ALEN);
- _rtw_memcpy(whdr->addr3, attrib->mda, ETH_ALEN);
- _rtw_memcpy(whdr->addr4, attrib->msa, ETH_ALEN);
- break;
- case MESH_BMCAST_DATA: /* 0, 1, RA(DA), TA, mSA(SA) */
- case MESH_BMCAST_PX_DATA: /* 0, 1, RA(DA), TA, mSA, [SA] */
- SetFrDs(fctrl);
- _rtw_memcpy(whdr->addr1, attrib->ra, ETH_ALEN);
- _rtw_memcpy(whdr->addr2, attrib->ta, ETH_ALEN);
- _rtw_memcpy(whdr->addr3, attrib->msa, ETH_ALEN);
- break;
- case MESH_MHOP_UCAST_ACT:
- /* TBD */
- RTW_INFO("MESH_MHOP_UCAST_ACT\n");
- break;
- case MESH_MHOP_BMCAST_ACT:
- /* TBD */
- RTW_INFO("MESH_MHOP_BMCAST_ACT\n");
- break;
- default:
- RTW_WARN("Invalid mesh frame mode\n");
- break;
- }
-
- return 0;
- }
- int rtw_mesh_rx_data_validate_hdr(_adapter *adapter, union recv_frame *rframe, struct sta_info **sta)
- {
- struct sta_priv *stapriv = &adapter->stapriv;
- struct rx_pkt_attrib *rattrib = &rframe->u.hdr.attrib;
- u8 *whdr = get_recvframe_data(rframe);
- u8 is_ra_bmc = 0;
- u8 a4_shift = 0;
- u8 ps;
- u8 *qc;
- u8 mps_mode = RTW_MESH_PS_UNKNOWN;
- sint ret = _FAIL;
- if (!(MLME_STATE(adapter) & WIFI_ASOC_STATE))
- goto exit;
- if (!rattrib->qos)
- goto exit;
- switch (rattrib->to_fr_ds) {
- case 1:
- if (!IS_MCAST(GetAddr1Ptr(whdr)))
- goto exit;
- *sta = rtw_get_stainfo(stapriv, get_addr2_ptr(whdr));
- if (*sta == NULL) {
- ret = _SUCCESS; /* return _SUCCESS to drop at sta checking */
- goto exit;
- }
- _rtw_memcpy(rattrib->ra, GetAddr1Ptr(whdr), ETH_ALEN);
- _rtw_memcpy(rattrib->ta, get_addr2_ptr(whdr), ETH_ALEN);
- _rtw_memcpy(rattrib->mda, GetAddr1Ptr(whdr), ETH_ALEN);
- _rtw_memcpy(rattrib->msa, GetAddr3Ptr(whdr), ETH_ALEN); /* may change after checking AMSDU subframe header */
- _rtw_memcpy(rattrib->dst, GetAddr1Ptr(whdr), ETH_ALEN);
- _rtw_memcpy(rattrib->src, GetAddr3Ptr(whdr), ETH_ALEN); /* may change after checking mesh ctrl field */
- _rtw_memcpy(rattrib->bssid, get_addr2_ptr(whdr), ETH_ALEN);
- is_ra_bmc = 1;
- break;
- case 3:
- if (IS_MCAST(GetAddr1Ptr(whdr)))
- goto exit;
- *sta = rtw_get_stainfo(stapriv, get_addr2_ptr(whdr));
- if (*sta == NULL) {
- ret = _SUCCESS; /* return _SUCCESS to drop at sta checking */
- goto exit;
- }
- _rtw_memcpy(rattrib->ra, GetAddr1Ptr(whdr), ETH_ALEN);
- _rtw_memcpy(rattrib->ta, get_addr2_ptr(whdr), ETH_ALEN);
- _rtw_memcpy(rattrib->mda, GetAddr3Ptr(whdr), ETH_ALEN); /* may change after checking AMSDU subframe header */
- _rtw_memcpy(rattrib->msa, GetAddr4Ptr(whdr), ETH_ALEN); /* may change after checking AMSDU subframe header */
- _rtw_memcpy(rattrib->dst, GetAddr3Ptr(whdr), ETH_ALEN); /* may change after checking mesh ctrl field */
- _rtw_memcpy(rattrib->src, GetAddr4Ptr(whdr), ETH_ALEN); /* may change after checking mesh ctrl field */
- _rtw_memcpy(rattrib->bssid, get_addr2_ptr(whdr), ETH_ALEN);
- a4_shift = ETH_ALEN;
- break;
- default:
- goto exit;
- }
- qc = whdr + WLAN_HDR_A3_LEN + a4_shift;
- ps = GetPwrMgt(whdr);
- mps_mode = ps ? (is_ra_bmc || (get_mps_lv(qc)) ? RTW_MESH_PS_DSLEEP : RTW_MESH_PS_LSLEEP) : RTW_MESH_PS_ACTIVE;
- if (ps) {
- if (!((*sta)->state & WIFI_SLEEP_STATE))
- stop_sta_xmit(adapter, *sta);
- } else {
- if ((*sta)->state & WIFI_SLEEP_STATE)
- wakeup_sta_to_xmit(adapter, *sta);
- }
- if (is_ra_bmc)
- (*sta)->nonpeer_mps = mps_mode;
- else {
- (*sta)->peer_mps = mps_mode;
- if (mps_mode != RTW_MESH_PS_ACTIVE && (*sta)->nonpeer_mps == RTW_MESH_PS_ACTIVE)
- (*sta)->nonpeer_mps = RTW_MESH_PS_DSLEEP;
- }
- if (get_frame_sub_type(whdr) & BIT(6)) {
- /* No data, will not indicate to upper layer, temporily count it here */
- count_rx_stats(adapter, rframe, *sta);
- ret = RTW_RX_HANDLED;
- goto exit;
- }
- rattrib->mesh_ctrl_present = get_mctrl_present(qc) ? 1 : 0;
- if (!rattrib->mesh_ctrl_present)
- goto exit;
- ret = _SUCCESS;
- exit:
- return ret;
- }
- int rtw_mesh_rx_data_validate_mctrl(_adapter *adapter, union recv_frame *rframe
- , const struct rtw_ieee80211s_hdr *mctrl, const u8 *mda, const u8 *msa
- , u8 *mctrl_len
- , const u8 **da, const u8 **sa)
- {
- struct rx_pkt_attrib *rattrib = &rframe->u.hdr.attrib;
- u8 mlen;
- u8 ae;
- int ret = _SUCCESS;
- ae = mctrl->flags & MESH_FLAGS_AE;
- mlen = ae_to_mesh_ctrl_len[ae];
- switch (rattrib->to_fr_ds) {
- case 1:
- *da = mda;
- if (ae == MESH_FLAGS_AE_A4)
- *sa = mctrl->eaddr1;
- else if (ae == 0)
- *sa = msa;
- else
- ret = _FAIL;
- break;
- case 3:
- if (ae == MESH_FLAGS_AE_A5_A6) {
- *da = mctrl->eaddr1;
- *sa = mctrl->eaddr2;
- } else if (ae == 0) {
- *da = mda;
- *sa = msa;
- } else
- ret = _FAIL;
- break;
- default:
- ret = _FAIL;
- }
- if (ret == _FAIL) {
- #ifdef DBG_RX_DROP_FRAME
- RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" invalid tfDS:%u AE:%u combination ra="MAC_FMT" ta="MAC_FMT"\n"
- , FUNC_ADPT_ARG(adapter), rattrib->to_fr_ds, ae, MAC_ARG(rattrib->ra), MAC_ARG(rattrib->ta));
- #endif
- *mctrl_len = 0;
- } else
- *mctrl_len = mlen;
- return ret;
- }
- inline int rtw_mesh_rx_validate_mctrl_non_amsdu(_adapter *adapter, union recv_frame *rframe)
- {
- struct rx_pkt_attrib *rattrib = &rframe->u.hdr.attrib;
- const u8 *da, *sa;
- int ret;
- ret = rtw_mesh_rx_data_validate_mctrl(adapter, rframe
- , (struct rtw_ieee80211s_hdr *)(get_recvframe_data(rframe) + rattrib->hdrlen + rattrib->iv_len)
- , rattrib->mda, rattrib->msa
- , &rattrib->mesh_ctrl_len
- , &da, &sa);
- if (ret == _SUCCESS) {
- _rtw_memcpy(rattrib->dst, da, ETH_ALEN);
- _rtw_memcpy(rattrib->src, sa, ETH_ALEN);
- }
- return ret;
- }
- /**
- * rtw_mesh_rx_nexthop_resolve - lookup next hop; conditionally start path discovery
- *
- * @skb: 802.11 frame to be sent
- * @sdata: network subif the frame will be sent through
- *
- * Lookup next hop for given skb and start path discovery if no
- * forwarding information is found.
- *
- * Returns: 0 if the next hop was found and -ENOENT if the frame was queued.
- * skb is freeed here if no mpath could be allocated.
- */
- static int rtw_mesh_rx_nexthop_resolve(_adapter *adapter,
- const u8 *mda, const u8 *msa, u8 *ra)
- {
- struct rtw_mesh_path *mpath;
- struct xmit_frame *xframe_to_free = NULL;
- int err = 0;
- int ret = _SUCCESS;
- rtw_rcu_read_lock();
- err = rtw_mesh_nexthop_lookup(adapter, mda, msa, ra);
- if (!err)
- goto endlookup;
- /* no nexthop found, start resolving */
- mpath = rtw_mesh_path_lookup(adapter, mda);
- if (!mpath) {
- mpath = rtw_mesh_path_add(adapter, mda);
- if (IS_ERR(mpath)) {
- err = PTR_ERR(mpath);
- ret = _FAIL;
- goto endlookup;
- }
- }
- if (!(mpath->flags & RTW_MESH_PATH_RESOLVING))
- rtw_mesh_queue_preq(mpath, RTW_PREQ_Q_F_START);
- ret = _FAIL;
- endlookup:
- rtw_rcu_read_unlock();
- return ret;
- }
- #define RTW_MESH_DECACHE_BMC 1
- #define RTW_MESH_DECACHE_UC 0
- #define RTW_MESH_FORWARD_MDA_SELF_COND 0
- #define DBG_RTW_MESH_FORWARD_MDA_SELF_COND 0
- int rtw_mesh_rx_msdu_act_check(union recv_frame *rframe
- , const u8 *mda, const u8 *msa
- , const u8 *da, const u8 *sa
- , struct rtw_ieee80211s_hdr *mctrl
- , struct xmit_frame **fwd_frame, _list *b2u_list)
- {
- _adapter *adapter = rframe->u.hdr.adapter;
- struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- struct rx_pkt_attrib *rattrib = &rframe->u.hdr.attrib;
- struct rtw_mesh_path *mppath;
- u8 is_mda_bmc = IS_MCAST(mda);
- u8 is_mda_self = !is_mda_bmc && _rtw_memcmp(mda, adapter_mac_addr(adapter), ETH_ALEN);
- struct xmit_frame *xframe;
- struct pkt_attrib *xattrib;
- u8 fwd_ra[ETH_ALEN] = {0};
- u8 fwd_mpp[ETH_ALEN] = {0}; /* forward to other gate */
- u32 fwd_mseq;
- int act = 0;
- u8 ae_need;
- #if CONFIG_RTW_MESH_DATA_BMC_TO_UC
- bool bmc_need = _TRUE;
- u8 b2u_num = 0;
- #endif
- /* fwd info lifetime update */
- #if 0
- if (!is_mda_self)
- mDA(A3) fwinfo.lifetime
- mSA(A4) fwinfo.lifetime
- Precursor-to-mDA(A2) fwinfo.lifetime
- #endif
- /* update/create pxoxy info for SA, mSA */
- if ((mctrl->flags & MESH_FLAGS_AE)
- && sa != msa && _rtw_memcmp(sa, msa, ETH_ALEN) == _FALSE
- ) {
- const u8 *proxied_addr = sa;
- const u8 *mpp_addr = msa;
- rtw_rcu_read_lock();
- mppath = rtw_mpp_path_lookup(adapter, proxied_addr);
- if (!mppath)
- rtw_mpp_path_add(adapter, proxied_addr, mpp_addr);
- else {
- enter_critical_bh(&mppath->state_lock);
- if (_rtw_memcmp(mppath->mpp, mpp_addr, ETH_ALEN) == _FALSE)
- _rtw_memcpy(mppath->mpp, mpp_addr, ETH_ALEN);
- mppath->exp_time = rtw_get_current_time();
- exit_critical_bh(&mppath->state_lock);
- }
- rtw_rcu_read_unlock();
- }
- /* mSA is self, need no further process */
- if (_rtw_memcmp(msa, adapter_mac_addr(adapter), ETH_ALEN) == _TRUE)
- goto exit;
- fwd_mseq = le32_to_cpu(mctrl->seqnum);
- /* check duplicate MSDU from mSA */
- if (((RTW_MESH_DECACHE_BMC && is_mda_bmc)
- || (RTW_MESH_DECACHE_UC && !is_mda_bmc))
- && rtw_mesh_decache(adapter, msa, fwd_mseq)
- ) {
- minfo->mshstats.dropped_frames_duplicate++;
- goto exit;
- }
- if (is_mda_bmc) {
- /* mDA is bmc addr */
- act |= RTW_RX_MSDU_ACT_INDICATE;
- if (!mcfg->dot11MeshForwarding)
- goto exit;
- goto fwd_chk;
- } else if (!is_mda_self) {
- /* mDA is unicast but not self */
- if (!mcfg->dot11MeshForwarding) {
- rtw_mesh_path_error_tx(adapter
- , adapter->mesh_cfg.element_ttl
- , mda, 0
- , WLAN_REASON_MESH_PATH_NOFORWARD
- , rattrib->ta
- );
- #ifdef DBG_RX_DROP_FRAME
- RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" mDA("MAC_FMT") not self, !dot11MeshForwarding\n"
- , FUNC_ADPT_ARG(adapter), MAC_ARG(mda));
- #endif
- goto exit;
- }
- if (rtw_mesh_rx_nexthop_resolve(adapter, mda, msa, fwd_ra) != _SUCCESS) {
- /* mDA is unknown */
- rtw_mesh_path_error_tx(adapter
- , adapter->mesh_cfg.element_ttl
- , mda, 0
- , WLAN_REASON_MESH_PATH_NOFORWARD
- , rattrib->ta
- );
- #ifdef DBG_RX_DROP_FRAME
- RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" mDA("MAC_FMT") unknown\n"
- , FUNC_ADPT_ARG(adapter), MAC_ARG(mda));
- #endif
- minfo->mshstats.dropped_frames_no_route++;
- goto exit;
- } else {
- /* mDA is known in fwd info */
- #if 0
- if (TA is not in precursors)
- goto exit;
- #endif
- goto fwd_chk;
- }
- } else {
- /* mDA is self */
- #if RTW_MESH_FORWARD_MDA_SELF_COND
- if (da == mda
- || _rtw_memcmp(da, adapter_mac_addr(adapter), ETH_ALEN)
- ) {
- /* DA is self, indicate */
- act |= RTW_RX_MSDU_ACT_INDICATE;
- goto exit;
- }
- if (rtw_get_iface_by_macddr(adapter, da)) {
- /* DA is buddy, indicate */
- act |= RTW_RX_MSDU_ACT_INDICATE;
- #if DBG_RTW_MESH_FORWARD_MDA_SELF_COND
- RTW_INFO(FUNC_ADPT_FMT" DA("MAC_FMT") is buddy("ADPT_FMT")\n"
- , FUNC_ADPT_ARG(adapter), MAC_ARG(da), ADPT_ARG(rtw_get_iface_by_macddr(adapter, da)));
- #endif
- goto exit;
- }
- /* DA is not self or buddy */
- if (rtw_mesh_nexthop_lookup(adapter, da, msa, fwd_ra) == 0) {
- /* DA is known in fwd info */
- if (!mcfg->dot11MeshForwarding) {
- /* path error to? */
- #if defined(DBG_RX_DROP_FRAME) || DBG_RTW_MESH_FORWARD_MDA_SELF_COND
- RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" DA("MAC_FMT") not self, !dot11MeshForwarding\n"
- , FUNC_ADPT_ARG(adapter), MAC_ARG(da));
- #endif
- goto exit;
- }
- mda = da;
- #if DBG_RTW_MESH_FORWARD_MDA_SELF_COND
- RTW_INFO(FUNC_ADPT_FMT" fwd to DA("MAC_FMT"), fwd_RA("MAC_FMT")\n"
- , FUNC_ADPT_ARG(adapter), MAC_ARG(da), MAC_ARG(fwd_ra));
- #endif
- goto fwd_chk;
- }
- rtw_rcu_read_lock();
- mppath = rtw_mpp_path_lookup(adapter, da);
- if (mppath) {
- if (_rtw_memcmp(mppath->mpp, adapter_mac_addr(adapter), ETH_ALEN) == _FALSE) {
- /* DA is proxied by others */
- if (!mcfg->dot11MeshForwarding) {
- /* path error to? */
- #if defined(DBG_RX_DROP_FRAME) || DBG_RTW_MESH_FORWARD_MDA_SELF_COND
- RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" DA("MAC_FMT") is proxied by ("MAC_FMT"), !dot11MeshForwarding\n"
- , FUNC_ADPT_ARG(adapter), MAC_ARG(da), MAC_ARG(mppath->mpp));
- #endif
- rtw_rcu_read_unlock();
- goto exit;
- }
- _rtw_memcpy(fwd_mpp, mppath->mpp, ETH_ALEN);
- mda = fwd_mpp;
- msa = adapter_mac_addr(adapter);
- rtw_rcu_read_unlock();
- /* resolve RA */
- if (rtw_mesh_nexthop_lookup(adapter, mda, msa, fwd_ra) != 0) {
- minfo->mshstats.dropped_frames_no_route++;
- #if defined(DBG_RX_DROP_FRAME) || DBG_RTW_MESH_FORWARD_MDA_SELF_COND
- RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" DA("MAC_FMT") is proxied by ("MAC_FMT"), RA resolve fail\n"
- , FUNC_ADPT_ARG(adapter), MAC_ARG(da), MAC_ARG(mppath->mpp));
- #endif
- goto exit;
- }
- #if DBG_RTW_MESH_FORWARD_MDA_SELF_COND
- RTW_INFO(FUNC_ADPT_FMT" DA("MAC_FMT") is proxied by ("MAC_FMT"), fwd_RA("MAC_FMT")\n"
- , FUNC_ADPT_ARG(adapter), MAC_ARG(da), MAC_ARG(mppath->mpp), MAC_ARG(fwd_ra));
- #endif
- goto fwd_chk; /* forward to other gate */
- } else {
- #if DBG_RTW_MESH_FORWARD_MDA_SELF_COND
- RTW_INFO(FUNC_ADPT_FMT" DA("MAC_FMT") is proxied by self\n"
- , FUNC_ADPT_ARG(adapter), MAC_ARG(da));
- #endif
- }
- }
- rtw_rcu_read_unlock();
- if (!mppath) {
- #if DBG_RTW_MESH_FORWARD_MDA_SELF_COND
- RTW_INFO(FUNC_ADPT_FMT" DA("MAC_FMT") unknown\n"
- , FUNC_ADPT_ARG(adapter), MAC_ARG(da));
- #endif
- /* DA is unknown */
- #if 0 /* TODO: flags with AE bit */
- rtw_mesh_path_error_tx(adapter
- , adapter->mesh_cfg.element_ttl
- , mda, adapter->mesh_info.last_sn_update
- , WLAN_REASON_MESH_PATH_NOPROXY
- , msa
- );
- #endif
- }
- /*
- * indicate to DS for both cases:
- * 1.) DA is proxied by self
- * 2.) DA is unknown
- */
- #endif /* RTW_MESH_FORWARD_MDA_SELF_COND */
- act |= RTW_RX_MSDU_ACT_INDICATE;
- goto exit;
- }
- fwd_chk:
- if (adapter->stapriv.asoc_list_cnt <= 1)
- goto exit;
- if (mctrl->ttl == 1) {
- minfo->mshstats.dropped_frames_ttl++;
- if (!act) {
- #ifdef DBG_RX_DROP_FRAME
- RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" ttl reaches 0, not forwarding\n"
- , FUNC_ADPT_ARG(adapter));
- #endif
- }
- goto exit;
- }
- #if CONFIG_RTW_MESH_DATA_BMC_TO_UC
- _rtw_init_listhead(b2u_list);
- #endif
- ae_need = _rtw_memcmp(da , mda, ETH_ALEN) == _FALSE
- || _rtw_memcmp(sa , msa, ETH_ALEN) == _FALSE;
- #if CONFIG_RTW_MESH_DATA_BMC_TO_UC
- if (is_mda_bmc
- && rtw_mfwd_b2u_policy_chk(mcfg->b2u_flags_mfwd, mda, rattrib->to_fr_ds == 3)
- ) {
- bmc_need = rtw_mesh_data_bmc_to_uc(adapter
- , da, sa, mda, msa, ae_need, rframe->u.hdr.psta->cmn.mac_addr, mctrl->ttl - 1
- , b2u_list, &b2u_num, &fwd_mseq);
- }
- if (bmc_need == _TRUE)
- #endif
- {
- xframe = rtw_alloc_xmitframe(&adapter->xmitpriv);
- if (!xframe) {
- #ifdef DBG_TX_DROP_FRAME
- RTW_INFO("DBG_TX_DROP_FRAME "FUNC_ADPT_FMT" rtw_alloc_xmitframe fail\n"
- , FUNC_ADPT_ARG(adapter));
- #endif
- goto exit;
- }
- xattrib = &xframe->attrib;
- #if CONFIG_RTW_MESH_DATA_BMC_TO_UC
- if (b2u_num)
- xattrib->mb2u = 1;
- else
- xattrib->mb2u = 0;
- #endif
- xattrib->mfwd_ttl = mctrl->ttl - 1;
- xattrib->mseq = fwd_mseq;
- _rtw_memcpy(xattrib->dst, da, ETH_ALEN);
- _rtw_memcpy(xattrib->src, sa, ETH_ALEN);
- _rtw_memcpy(xattrib->mda, mda, ETH_ALEN);
- _rtw_memcpy(xattrib->msa, msa, ETH_ALEN);
- _rtw_memcpy(xattrib->ta, adapter_mac_addr(adapter), ETH_ALEN);
- if (is_mda_bmc) {
- xattrib->mesh_frame_mode = ae_need ? MESH_BMCAST_PX_DATA : MESH_BMCAST_DATA;
- _rtw_memcpy(xattrib->ra, mda, ETH_ALEN);
- } else {
- xattrib->mesh_frame_mode = ae_need ? MESH_UCAST_PX_DATA : MESH_UCAST_DATA;
- _rtw_memcpy(xattrib->ra, fwd_ra, ETH_ALEN);
- }
- *fwd_frame = xframe;
- }
- act |= RTW_RX_MSDU_ACT_FORWARD;
- if (is_mda_bmc)
- minfo->mshstats.fwded_mcast++;
- else
- minfo->mshstats.fwded_unicast++;
- minfo->mshstats.fwded_frames++;
- exit:
- return act;
- }
- void dump_mesh_stats(void *sel, _adapter *adapter)
- {
- struct rtw_mesh_info *minfo = &adapter->mesh_info;
- struct rtw_mesh_stats *stats = &minfo->mshstats;
- RTW_PRINT_SEL(sel, "fwd_bmc:%u\n", stats->fwded_mcast);
- RTW_PRINT_SEL(sel, "fwd_uc:%u\n", stats->fwded_unicast);
- RTW_PRINT_SEL(sel, "drop_ttl:%u\n", stats->dropped_frames_ttl);
- RTW_PRINT_SEL(sel, "drop_no_route:%u\n", stats->dropped_frames_no_route);
- RTW_PRINT_SEL(sel, "drop_congestion:%u\n", stats->dropped_frames_congestion);
- RTW_PRINT_SEL(sel, "drop_dup:%u\n", stats->dropped_frames_duplicate);
- RTW_PRINT_SEL(sel, "mrc_del_qlen:%u\n", stats->mrc_del_qlen);
- }
- #endif /* CONFIG_RTW_MESH */
|