spectrum_router.c 95 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612
  1. /*
  2. * drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
  3. * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
  4. * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com>
  5. * Copyright (c) 2016 Ido Schimmel <idosch@mellanox.com>
  6. * Copyright (c) 2016 Yotam Gigi <yotamg@mellanox.com>
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in the
  15. * documentation and/or other materials provided with the distribution.
  16. * 3. Neither the names of the copyright holders nor the names of its
  17. * contributors may be used to endorse or promote products derived from
  18. * this software without specific prior written permission.
  19. *
  20. * Alternatively, this software may be distributed under the terms of the
  21. * GNU General Public License ("GPL") version 2 as published by the Free
  22. * Software Foundation.
  23. *
  24. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  25. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  28. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  29. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  30. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  31. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  32. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  33. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  34. * POSSIBILITY OF SUCH DAMAGE.
  35. */
  36. #include <linux/kernel.h>
  37. #include <linux/types.h>
  38. #include <linux/rhashtable.h>
  39. #include <linux/bitops.h>
  40. #include <linux/in6.h>
  41. #include <linux/notifier.h>
  42. #include <linux/inetdevice.h>
  43. #include <linux/netdevice.h>
  44. #include <net/netevent.h>
  45. #include <net/neighbour.h>
  46. #include <net/arp.h>
  47. #include <net/ip_fib.h>
  48. #include <net/fib_rules.h>
  49. #include <net/l3mdev.h>
  50. #include "spectrum.h"
  51. #include "core.h"
  52. #include "reg.h"
  53. #include "spectrum_cnt.h"
  54. #include "spectrum_dpipe.h"
  55. #include "spectrum_router.h"
  56. struct mlxsw_sp_rif {
  57. struct list_head nexthop_list;
  58. struct list_head neigh_list;
  59. struct net_device *dev;
  60. struct mlxsw_sp_fid *f;
  61. unsigned char addr[ETH_ALEN];
  62. int mtu;
  63. u16 rif_index;
  64. u16 vr_id;
  65. unsigned int counter_ingress;
  66. bool counter_ingress_valid;
  67. unsigned int counter_egress;
  68. bool counter_egress_valid;
  69. };
  70. static unsigned int *
  71. mlxsw_sp_rif_p_counter_get(struct mlxsw_sp_rif *rif,
  72. enum mlxsw_sp_rif_counter_dir dir)
  73. {
  74. switch (dir) {
  75. case MLXSW_SP_RIF_COUNTER_EGRESS:
  76. return &rif->counter_egress;
  77. case MLXSW_SP_RIF_COUNTER_INGRESS:
  78. return &rif->counter_ingress;
  79. }
  80. return NULL;
  81. }
  82. static bool
  83. mlxsw_sp_rif_counter_valid_get(struct mlxsw_sp_rif *rif,
  84. enum mlxsw_sp_rif_counter_dir dir)
  85. {
  86. switch (dir) {
  87. case MLXSW_SP_RIF_COUNTER_EGRESS:
  88. return rif->counter_egress_valid;
  89. case MLXSW_SP_RIF_COUNTER_INGRESS:
  90. return rif->counter_ingress_valid;
  91. }
  92. return false;
  93. }
  94. static void
  95. mlxsw_sp_rif_counter_valid_set(struct mlxsw_sp_rif *rif,
  96. enum mlxsw_sp_rif_counter_dir dir,
  97. bool valid)
  98. {
  99. switch (dir) {
  100. case MLXSW_SP_RIF_COUNTER_EGRESS:
  101. rif->counter_egress_valid = valid;
  102. break;
  103. case MLXSW_SP_RIF_COUNTER_INGRESS:
  104. rif->counter_ingress_valid = valid;
  105. break;
  106. }
  107. }
  108. static int mlxsw_sp_rif_counter_edit(struct mlxsw_sp *mlxsw_sp, u16 rif_index,
  109. unsigned int counter_index, bool enable,
  110. enum mlxsw_sp_rif_counter_dir dir)
  111. {
  112. char ritr_pl[MLXSW_REG_RITR_LEN];
  113. bool is_egress = false;
  114. int err;
  115. if (dir == MLXSW_SP_RIF_COUNTER_EGRESS)
  116. is_egress = true;
  117. mlxsw_reg_ritr_rif_pack(ritr_pl, rif_index);
  118. err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
  119. if (err)
  120. return err;
  121. mlxsw_reg_ritr_counter_pack(ritr_pl, counter_index, enable,
  122. is_egress);
  123. return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
  124. }
  125. int mlxsw_sp_rif_counter_value_get(struct mlxsw_sp *mlxsw_sp,
  126. struct mlxsw_sp_rif *rif,
  127. enum mlxsw_sp_rif_counter_dir dir, u64 *cnt)
  128. {
  129. char ricnt_pl[MLXSW_REG_RICNT_LEN];
  130. unsigned int *p_counter_index;
  131. bool valid;
  132. int err;
  133. valid = mlxsw_sp_rif_counter_valid_get(rif, dir);
  134. if (!valid)
  135. return -EINVAL;
  136. p_counter_index = mlxsw_sp_rif_p_counter_get(rif, dir);
  137. if (!p_counter_index)
  138. return -EINVAL;
  139. mlxsw_reg_ricnt_pack(ricnt_pl, *p_counter_index,
  140. MLXSW_REG_RICNT_OPCODE_NOP);
  141. err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ricnt), ricnt_pl);
  142. if (err)
  143. return err;
  144. *cnt = mlxsw_reg_ricnt_good_unicast_packets_get(ricnt_pl);
  145. return 0;
  146. }
  147. static int mlxsw_sp_rif_counter_clear(struct mlxsw_sp *mlxsw_sp,
  148. unsigned int counter_index)
  149. {
  150. char ricnt_pl[MLXSW_REG_RICNT_LEN];
  151. mlxsw_reg_ricnt_pack(ricnt_pl, counter_index,
  152. MLXSW_REG_RICNT_OPCODE_CLEAR);
  153. return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ricnt), ricnt_pl);
  154. }
  155. int mlxsw_sp_rif_counter_alloc(struct mlxsw_sp *mlxsw_sp,
  156. struct mlxsw_sp_rif *rif,
  157. enum mlxsw_sp_rif_counter_dir dir)
  158. {
  159. unsigned int *p_counter_index;
  160. int err;
  161. p_counter_index = mlxsw_sp_rif_p_counter_get(rif, dir);
  162. if (!p_counter_index)
  163. return -EINVAL;
  164. err = mlxsw_sp_counter_alloc(mlxsw_sp, MLXSW_SP_COUNTER_SUB_POOL_RIF,
  165. p_counter_index);
  166. if (err)
  167. return err;
  168. err = mlxsw_sp_rif_counter_clear(mlxsw_sp, *p_counter_index);
  169. if (err)
  170. goto err_counter_clear;
  171. err = mlxsw_sp_rif_counter_edit(mlxsw_sp, rif->rif_index,
  172. *p_counter_index, true, dir);
  173. if (err)
  174. goto err_counter_edit;
  175. mlxsw_sp_rif_counter_valid_set(rif, dir, true);
  176. return 0;
  177. err_counter_edit:
  178. err_counter_clear:
  179. mlxsw_sp_counter_free(mlxsw_sp, MLXSW_SP_COUNTER_SUB_POOL_RIF,
  180. *p_counter_index);
  181. return err;
  182. }
  183. void mlxsw_sp_rif_counter_free(struct mlxsw_sp *mlxsw_sp,
  184. struct mlxsw_sp_rif *rif,
  185. enum mlxsw_sp_rif_counter_dir dir)
  186. {
  187. unsigned int *p_counter_index;
  188. if (!mlxsw_sp_rif_counter_valid_get(rif, dir))
  189. return;
  190. p_counter_index = mlxsw_sp_rif_p_counter_get(rif, dir);
  191. if (WARN_ON(!p_counter_index))
  192. return;
  193. mlxsw_sp_rif_counter_edit(mlxsw_sp, rif->rif_index,
  194. *p_counter_index, false, dir);
  195. mlxsw_sp_counter_free(mlxsw_sp, MLXSW_SP_COUNTER_SUB_POOL_RIF,
  196. *p_counter_index);
  197. mlxsw_sp_rif_counter_valid_set(rif, dir, false);
  198. }
  199. static struct mlxsw_sp_rif *
  200. mlxsw_sp_rif_find_by_dev(const struct mlxsw_sp *mlxsw_sp,
  201. const struct net_device *dev);
  202. #define mlxsw_sp_prefix_usage_for_each(prefix, prefix_usage) \
  203. for_each_set_bit(prefix, (prefix_usage)->b, MLXSW_SP_PREFIX_COUNT)
  204. static bool
  205. mlxsw_sp_prefix_usage_subset(struct mlxsw_sp_prefix_usage *prefix_usage1,
  206. struct mlxsw_sp_prefix_usage *prefix_usage2)
  207. {
  208. unsigned char prefix;
  209. mlxsw_sp_prefix_usage_for_each(prefix, prefix_usage1) {
  210. if (!test_bit(prefix, prefix_usage2->b))
  211. return false;
  212. }
  213. return true;
  214. }
  215. static bool
  216. mlxsw_sp_prefix_usage_eq(struct mlxsw_sp_prefix_usage *prefix_usage1,
  217. struct mlxsw_sp_prefix_usage *prefix_usage2)
  218. {
  219. return !memcmp(prefix_usage1, prefix_usage2, sizeof(*prefix_usage1));
  220. }
  221. static bool
  222. mlxsw_sp_prefix_usage_none(struct mlxsw_sp_prefix_usage *prefix_usage)
  223. {
  224. struct mlxsw_sp_prefix_usage prefix_usage_none = {{ 0 } };
  225. return mlxsw_sp_prefix_usage_eq(prefix_usage, &prefix_usage_none);
  226. }
  227. static void
  228. mlxsw_sp_prefix_usage_cpy(struct mlxsw_sp_prefix_usage *prefix_usage1,
  229. struct mlxsw_sp_prefix_usage *prefix_usage2)
  230. {
  231. memcpy(prefix_usage1, prefix_usage2, sizeof(*prefix_usage1));
  232. }
  233. static void
  234. mlxsw_sp_prefix_usage_set(struct mlxsw_sp_prefix_usage *prefix_usage,
  235. unsigned char prefix_len)
  236. {
  237. set_bit(prefix_len, prefix_usage->b);
  238. }
  239. static void
  240. mlxsw_sp_prefix_usage_clear(struct mlxsw_sp_prefix_usage *prefix_usage,
  241. unsigned char prefix_len)
  242. {
  243. clear_bit(prefix_len, prefix_usage->b);
  244. }
  245. struct mlxsw_sp_fib_key {
  246. unsigned char addr[sizeof(struct in6_addr)];
  247. unsigned char prefix_len;
  248. };
  249. enum mlxsw_sp_fib_entry_type {
  250. MLXSW_SP_FIB_ENTRY_TYPE_REMOTE,
  251. MLXSW_SP_FIB_ENTRY_TYPE_LOCAL,
  252. MLXSW_SP_FIB_ENTRY_TYPE_TRAP,
  253. };
  254. struct mlxsw_sp_nexthop_group;
  255. struct mlxsw_sp_fib_node {
  256. struct list_head entry_list;
  257. struct list_head list;
  258. struct rhash_head ht_node;
  259. struct mlxsw_sp_fib *fib;
  260. struct mlxsw_sp_fib_key key;
  261. };
  262. struct mlxsw_sp_fib_entry_params {
  263. u32 tb_id;
  264. u32 prio;
  265. u8 tos;
  266. u8 type;
  267. };
  268. struct mlxsw_sp_fib_entry {
  269. struct list_head list;
  270. struct mlxsw_sp_fib_node *fib_node;
  271. enum mlxsw_sp_fib_entry_type type;
  272. struct list_head nexthop_group_node;
  273. struct mlxsw_sp_nexthop_group *nh_group;
  274. struct mlxsw_sp_fib_entry_params params;
  275. bool offloaded;
  276. };
  277. struct mlxsw_sp_fib {
  278. struct rhashtable ht;
  279. struct list_head node_list;
  280. struct mlxsw_sp_vr *vr;
  281. struct mlxsw_sp_lpm_tree *lpm_tree;
  282. unsigned long prefix_ref_count[MLXSW_SP_PREFIX_COUNT];
  283. struct mlxsw_sp_prefix_usage prefix_usage;
  284. enum mlxsw_sp_l3proto proto;
  285. };
  286. static const struct rhashtable_params mlxsw_sp_fib_ht_params;
  287. static struct mlxsw_sp_fib *mlxsw_sp_fib_create(struct mlxsw_sp_vr *vr,
  288. enum mlxsw_sp_l3proto proto)
  289. {
  290. struct mlxsw_sp_fib *fib;
  291. int err;
  292. fib = kzalloc(sizeof(*fib), GFP_KERNEL);
  293. if (!fib)
  294. return ERR_PTR(-ENOMEM);
  295. err = rhashtable_init(&fib->ht, &mlxsw_sp_fib_ht_params);
  296. if (err)
  297. goto err_rhashtable_init;
  298. INIT_LIST_HEAD(&fib->node_list);
  299. fib->proto = proto;
  300. fib->vr = vr;
  301. return fib;
  302. err_rhashtable_init:
  303. kfree(fib);
  304. return ERR_PTR(err);
  305. }
  306. static void mlxsw_sp_fib_destroy(struct mlxsw_sp_fib *fib)
  307. {
  308. WARN_ON(!list_empty(&fib->node_list));
  309. WARN_ON(fib->lpm_tree);
  310. rhashtable_destroy(&fib->ht);
  311. kfree(fib);
  312. }
  313. static struct mlxsw_sp_lpm_tree *
  314. mlxsw_sp_lpm_tree_find_unused(struct mlxsw_sp *mlxsw_sp)
  315. {
  316. static struct mlxsw_sp_lpm_tree *lpm_tree;
  317. int i;
  318. for (i = 0; i < mlxsw_sp->router.lpm.tree_count; i++) {
  319. lpm_tree = &mlxsw_sp->router.lpm.trees[i];
  320. if (lpm_tree->ref_count == 0)
  321. return lpm_tree;
  322. }
  323. return NULL;
  324. }
  325. static int mlxsw_sp_lpm_tree_alloc(struct mlxsw_sp *mlxsw_sp,
  326. struct mlxsw_sp_lpm_tree *lpm_tree)
  327. {
  328. char ralta_pl[MLXSW_REG_RALTA_LEN];
  329. mlxsw_reg_ralta_pack(ralta_pl, true,
  330. (enum mlxsw_reg_ralxx_protocol) lpm_tree->proto,
  331. lpm_tree->id);
  332. return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralta), ralta_pl);
  333. }
  334. static int mlxsw_sp_lpm_tree_free(struct mlxsw_sp *mlxsw_sp,
  335. struct mlxsw_sp_lpm_tree *lpm_tree)
  336. {
  337. char ralta_pl[MLXSW_REG_RALTA_LEN];
  338. mlxsw_reg_ralta_pack(ralta_pl, false,
  339. (enum mlxsw_reg_ralxx_protocol) lpm_tree->proto,
  340. lpm_tree->id);
  341. return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralta), ralta_pl);
  342. }
  343. static int
  344. mlxsw_sp_lpm_tree_left_struct_set(struct mlxsw_sp *mlxsw_sp,
  345. struct mlxsw_sp_prefix_usage *prefix_usage,
  346. struct mlxsw_sp_lpm_tree *lpm_tree)
  347. {
  348. char ralst_pl[MLXSW_REG_RALST_LEN];
  349. u8 root_bin = 0;
  350. u8 prefix;
  351. u8 last_prefix = MLXSW_REG_RALST_BIN_NO_CHILD;
  352. mlxsw_sp_prefix_usage_for_each(prefix, prefix_usage)
  353. root_bin = prefix;
  354. mlxsw_reg_ralst_pack(ralst_pl, root_bin, lpm_tree->id);
  355. mlxsw_sp_prefix_usage_for_each(prefix, prefix_usage) {
  356. if (prefix == 0)
  357. continue;
  358. mlxsw_reg_ralst_bin_pack(ralst_pl, prefix, last_prefix,
  359. MLXSW_REG_RALST_BIN_NO_CHILD);
  360. last_prefix = prefix;
  361. }
  362. return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralst), ralst_pl);
  363. }
  364. static struct mlxsw_sp_lpm_tree *
  365. mlxsw_sp_lpm_tree_create(struct mlxsw_sp *mlxsw_sp,
  366. struct mlxsw_sp_prefix_usage *prefix_usage,
  367. enum mlxsw_sp_l3proto proto)
  368. {
  369. struct mlxsw_sp_lpm_tree *lpm_tree;
  370. int err;
  371. lpm_tree = mlxsw_sp_lpm_tree_find_unused(mlxsw_sp);
  372. if (!lpm_tree)
  373. return ERR_PTR(-EBUSY);
  374. lpm_tree->proto = proto;
  375. err = mlxsw_sp_lpm_tree_alloc(mlxsw_sp, lpm_tree);
  376. if (err)
  377. return ERR_PTR(err);
  378. err = mlxsw_sp_lpm_tree_left_struct_set(mlxsw_sp, prefix_usage,
  379. lpm_tree);
  380. if (err)
  381. goto err_left_struct_set;
  382. memcpy(&lpm_tree->prefix_usage, prefix_usage,
  383. sizeof(lpm_tree->prefix_usage));
  384. return lpm_tree;
  385. err_left_struct_set:
  386. mlxsw_sp_lpm_tree_free(mlxsw_sp, lpm_tree);
  387. return ERR_PTR(err);
  388. }
  389. static int mlxsw_sp_lpm_tree_destroy(struct mlxsw_sp *mlxsw_sp,
  390. struct mlxsw_sp_lpm_tree *lpm_tree)
  391. {
  392. return mlxsw_sp_lpm_tree_free(mlxsw_sp, lpm_tree);
  393. }
  394. static struct mlxsw_sp_lpm_tree *
  395. mlxsw_sp_lpm_tree_get(struct mlxsw_sp *mlxsw_sp,
  396. struct mlxsw_sp_prefix_usage *prefix_usage,
  397. enum mlxsw_sp_l3proto proto)
  398. {
  399. struct mlxsw_sp_lpm_tree *lpm_tree;
  400. int i;
  401. for (i = 0; i < mlxsw_sp->router.lpm.tree_count; i++) {
  402. lpm_tree = &mlxsw_sp->router.lpm.trees[i];
  403. if (lpm_tree->ref_count != 0 &&
  404. lpm_tree->proto == proto &&
  405. mlxsw_sp_prefix_usage_eq(&lpm_tree->prefix_usage,
  406. prefix_usage))
  407. goto inc_ref_count;
  408. }
  409. lpm_tree = mlxsw_sp_lpm_tree_create(mlxsw_sp, prefix_usage,
  410. proto);
  411. if (IS_ERR(lpm_tree))
  412. return lpm_tree;
  413. inc_ref_count:
  414. lpm_tree->ref_count++;
  415. return lpm_tree;
  416. }
  417. static int mlxsw_sp_lpm_tree_put(struct mlxsw_sp *mlxsw_sp,
  418. struct mlxsw_sp_lpm_tree *lpm_tree)
  419. {
  420. if (--lpm_tree->ref_count == 0)
  421. return mlxsw_sp_lpm_tree_destroy(mlxsw_sp, lpm_tree);
  422. return 0;
  423. }
  424. #define MLXSW_SP_LPM_TREE_MIN 2 /* trees 0 and 1 are reserved */
  425. static int mlxsw_sp_lpm_init(struct mlxsw_sp *mlxsw_sp)
  426. {
  427. struct mlxsw_sp_lpm_tree *lpm_tree;
  428. u64 max_trees;
  429. int i;
  430. if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_LPM_TREES))
  431. return -EIO;
  432. max_trees = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_LPM_TREES);
  433. mlxsw_sp->router.lpm.tree_count = max_trees - MLXSW_SP_LPM_TREE_MIN;
  434. mlxsw_sp->router.lpm.trees = kcalloc(mlxsw_sp->router.lpm.tree_count,
  435. sizeof(struct mlxsw_sp_lpm_tree),
  436. GFP_KERNEL);
  437. if (!mlxsw_sp->router.lpm.trees)
  438. return -ENOMEM;
  439. for (i = 0; i < mlxsw_sp->router.lpm.tree_count; i++) {
  440. lpm_tree = &mlxsw_sp->router.lpm.trees[i];
  441. lpm_tree->id = i + MLXSW_SP_LPM_TREE_MIN;
  442. }
  443. return 0;
  444. }
  445. static void mlxsw_sp_lpm_fini(struct mlxsw_sp *mlxsw_sp)
  446. {
  447. kfree(mlxsw_sp->router.lpm.trees);
  448. }
  449. static bool mlxsw_sp_vr_is_used(const struct mlxsw_sp_vr *vr)
  450. {
  451. return !!vr->fib4;
  452. }
  453. static struct mlxsw_sp_vr *mlxsw_sp_vr_find_unused(struct mlxsw_sp *mlxsw_sp)
  454. {
  455. struct mlxsw_sp_vr *vr;
  456. int i;
  457. for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) {
  458. vr = &mlxsw_sp->router.vrs[i];
  459. if (!mlxsw_sp_vr_is_used(vr))
  460. return vr;
  461. }
  462. return NULL;
  463. }
  464. static int mlxsw_sp_vr_lpm_tree_bind(struct mlxsw_sp *mlxsw_sp,
  465. const struct mlxsw_sp_fib *fib)
  466. {
  467. char raltb_pl[MLXSW_REG_RALTB_LEN];
  468. mlxsw_reg_raltb_pack(raltb_pl, fib->vr->id,
  469. (enum mlxsw_reg_ralxx_protocol) fib->proto,
  470. fib->lpm_tree->id);
  471. return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(raltb), raltb_pl);
  472. }
  473. static int mlxsw_sp_vr_lpm_tree_unbind(struct mlxsw_sp *mlxsw_sp,
  474. const struct mlxsw_sp_fib *fib)
  475. {
  476. char raltb_pl[MLXSW_REG_RALTB_LEN];
  477. /* Bind to tree 0 which is default */
  478. mlxsw_reg_raltb_pack(raltb_pl, fib->vr->id,
  479. (enum mlxsw_reg_ralxx_protocol) fib->proto, 0);
  480. return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(raltb), raltb_pl);
  481. }
  482. static u32 mlxsw_sp_fix_tb_id(u32 tb_id)
  483. {
  484. /* For our purpose, squash main and local table into one */
  485. if (tb_id == RT_TABLE_LOCAL)
  486. tb_id = RT_TABLE_MAIN;
  487. return tb_id;
  488. }
  489. static struct mlxsw_sp_vr *mlxsw_sp_vr_find(struct mlxsw_sp *mlxsw_sp,
  490. u32 tb_id)
  491. {
  492. struct mlxsw_sp_vr *vr;
  493. int i;
  494. tb_id = mlxsw_sp_fix_tb_id(tb_id);
  495. for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) {
  496. vr = &mlxsw_sp->router.vrs[i];
  497. if (mlxsw_sp_vr_is_used(vr) && vr->tb_id == tb_id)
  498. return vr;
  499. }
  500. return NULL;
  501. }
  502. static struct mlxsw_sp_fib *mlxsw_sp_vr_fib(const struct mlxsw_sp_vr *vr,
  503. enum mlxsw_sp_l3proto proto)
  504. {
  505. switch (proto) {
  506. case MLXSW_SP_L3_PROTO_IPV4:
  507. return vr->fib4;
  508. case MLXSW_SP_L3_PROTO_IPV6:
  509. BUG_ON(1);
  510. }
  511. return NULL;
  512. }
  513. static struct mlxsw_sp_vr *mlxsw_sp_vr_create(struct mlxsw_sp *mlxsw_sp,
  514. u32 tb_id)
  515. {
  516. struct mlxsw_sp_vr *vr;
  517. vr = mlxsw_sp_vr_find_unused(mlxsw_sp);
  518. if (!vr)
  519. return ERR_PTR(-EBUSY);
  520. vr->fib4 = mlxsw_sp_fib_create(vr, MLXSW_SP_L3_PROTO_IPV4);
  521. if (IS_ERR(vr->fib4))
  522. return ERR_CAST(vr->fib4);
  523. vr->tb_id = tb_id;
  524. return vr;
  525. }
  526. static void mlxsw_sp_vr_destroy(struct mlxsw_sp_vr *vr)
  527. {
  528. mlxsw_sp_fib_destroy(vr->fib4);
  529. vr->fib4 = NULL;
  530. }
  531. static int
  532. mlxsw_sp_vr_lpm_tree_check(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_fib *fib,
  533. struct mlxsw_sp_prefix_usage *req_prefix_usage)
  534. {
  535. struct mlxsw_sp_lpm_tree *lpm_tree = fib->lpm_tree;
  536. struct mlxsw_sp_lpm_tree *new_tree;
  537. int err;
  538. if (mlxsw_sp_prefix_usage_eq(req_prefix_usage, &lpm_tree->prefix_usage))
  539. return 0;
  540. new_tree = mlxsw_sp_lpm_tree_get(mlxsw_sp, req_prefix_usage,
  541. fib->proto);
  542. if (IS_ERR(new_tree)) {
  543. /* We failed to get a tree according to the required
  544. * prefix usage. However, the current tree might be still good
  545. * for us if our requirement is subset of the prefixes used
  546. * in the tree.
  547. */
  548. if (mlxsw_sp_prefix_usage_subset(req_prefix_usage,
  549. &lpm_tree->prefix_usage))
  550. return 0;
  551. return PTR_ERR(new_tree);
  552. }
  553. /* Prevent packet loss by overwriting existing binding */
  554. fib->lpm_tree = new_tree;
  555. err = mlxsw_sp_vr_lpm_tree_bind(mlxsw_sp, fib);
  556. if (err)
  557. goto err_tree_bind;
  558. mlxsw_sp_lpm_tree_put(mlxsw_sp, lpm_tree);
  559. return 0;
  560. err_tree_bind:
  561. fib->lpm_tree = lpm_tree;
  562. mlxsw_sp_lpm_tree_put(mlxsw_sp, new_tree);
  563. return err;
  564. }
  565. static struct mlxsw_sp_vr *mlxsw_sp_vr_get(struct mlxsw_sp *mlxsw_sp, u32 tb_id)
  566. {
  567. struct mlxsw_sp_vr *vr;
  568. tb_id = mlxsw_sp_fix_tb_id(tb_id);
  569. vr = mlxsw_sp_vr_find(mlxsw_sp, tb_id);
  570. if (!vr)
  571. vr = mlxsw_sp_vr_create(mlxsw_sp, tb_id);
  572. return vr;
  573. }
  574. static void mlxsw_sp_vr_put(struct mlxsw_sp_vr *vr)
  575. {
  576. if (!vr->rif_count && list_empty(&vr->fib4->node_list))
  577. mlxsw_sp_vr_destroy(vr);
  578. }
  579. static int mlxsw_sp_vrs_init(struct mlxsw_sp *mlxsw_sp)
  580. {
  581. struct mlxsw_sp_vr *vr;
  582. u64 max_vrs;
  583. int i;
  584. if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_VRS))
  585. return -EIO;
  586. max_vrs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS);
  587. mlxsw_sp->router.vrs = kcalloc(max_vrs, sizeof(struct mlxsw_sp_vr),
  588. GFP_KERNEL);
  589. if (!mlxsw_sp->router.vrs)
  590. return -ENOMEM;
  591. for (i = 0; i < max_vrs; i++) {
  592. vr = &mlxsw_sp->router.vrs[i];
  593. vr->id = i;
  594. }
  595. return 0;
  596. }
  597. static void mlxsw_sp_router_fib_flush(struct mlxsw_sp *mlxsw_sp);
  598. static void mlxsw_sp_vrs_fini(struct mlxsw_sp *mlxsw_sp)
  599. {
  600. /* At this stage we're guaranteed not to have new incoming
  601. * FIB notifications and the work queue is free from FIBs
  602. * sitting on top of mlxsw netdevs. However, we can still
  603. * have other FIBs queued. Flush the queue before flushing
  604. * the device's tables. No need for locks, as we're the only
  605. * writer.
  606. */
  607. mlxsw_core_flush_owq();
  608. mlxsw_sp_router_fib_flush(mlxsw_sp);
  609. kfree(mlxsw_sp->router.vrs);
  610. }
  611. struct mlxsw_sp_neigh_key {
  612. struct neighbour *n;
  613. };
  614. struct mlxsw_sp_neigh_entry {
  615. struct list_head rif_list_node;
  616. struct rhash_head ht_node;
  617. struct mlxsw_sp_neigh_key key;
  618. u16 rif;
  619. bool connected;
  620. unsigned char ha[ETH_ALEN];
  621. struct list_head nexthop_list; /* list of nexthops using
  622. * this neigh entry
  623. */
  624. struct list_head nexthop_neighs_list_node;
  625. };
  626. static const struct rhashtable_params mlxsw_sp_neigh_ht_params = {
  627. .key_offset = offsetof(struct mlxsw_sp_neigh_entry, key),
  628. .head_offset = offsetof(struct mlxsw_sp_neigh_entry, ht_node),
  629. .key_len = sizeof(struct mlxsw_sp_neigh_key),
  630. };
  631. static struct mlxsw_sp_neigh_entry *
  632. mlxsw_sp_neigh_entry_alloc(struct mlxsw_sp *mlxsw_sp, struct neighbour *n,
  633. u16 rif)
  634. {
  635. struct mlxsw_sp_neigh_entry *neigh_entry;
  636. neigh_entry = kzalloc(sizeof(*neigh_entry), GFP_KERNEL);
  637. if (!neigh_entry)
  638. return NULL;
  639. neigh_entry->key.n = n;
  640. neigh_entry->rif = rif;
  641. INIT_LIST_HEAD(&neigh_entry->nexthop_list);
  642. return neigh_entry;
  643. }
  644. static void mlxsw_sp_neigh_entry_free(struct mlxsw_sp_neigh_entry *neigh_entry)
  645. {
  646. kfree(neigh_entry);
  647. }
  648. static int
  649. mlxsw_sp_neigh_entry_insert(struct mlxsw_sp *mlxsw_sp,
  650. struct mlxsw_sp_neigh_entry *neigh_entry)
  651. {
  652. return rhashtable_insert_fast(&mlxsw_sp->router.neigh_ht,
  653. &neigh_entry->ht_node,
  654. mlxsw_sp_neigh_ht_params);
  655. }
  656. static void
  657. mlxsw_sp_neigh_entry_remove(struct mlxsw_sp *mlxsw_sp,
  658. struct mlxsw_sp_neigh_entry *neigh_entry)
  659. {
  660. rhashtable_remove_fast(&mlxsw_sp->router.neigh_ht,
  661. &neigh_entry->ht_node,
  662. mlxsw_sp_neigh_ht_params);
  663. }
  664. static struct mlxsw_sp_neigh_entry *
  665. mlxsw_sp_neigh_entry_create(struct mlxsw_sp *mlxsw_sp, struct neighbour *n)
  666. {
  667. struct mlxsw_sp_neigh_entry *neigh_entry;
  668. struct mlxsw_sp_rif *rif;
  669. int err;
  670. rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, n->dev);
  671. if (!rif)
  672. return ERR_PTR(-EINVAL);
  673. neigh_entry = mlxsw_sp_neigh_entry_alloc(mlxsw_sp, n, rif->rif_index);
  674. if (!neigh_entry)
  675. return ERR_PTR(-ENOMEM);
  676. err = mlxsw_sp_neigh_entry_insert(mlxsw_sp, neigh_entry);
  677. if (err)
  678. goto err_neigh_entry_insert;
  679. list_add(&neigh_entry->rif_list_node, &rif->neigh_list);
  680. return neigh_entry;
  681. err_neigh_entry_insert:
  682. mlxsw_sp_neigh_entry_free(neigh_entry);
  683. return ERR_PTR(err);
  684. }
  685. static void
  686. mlxsw_sp_neigh_entry_destroy(struct mlxsw_sp *mlxsw_sp,
  687. struct mlxsw_sp_neigh_entry *neigh_entry)
  688. {
  689. list_del(&neigh_entry->rif_list_node);
  690. mlxsw_sp_neigh_entry_remove(mlxsw_sp, neigh_entry);
  691. mlxsw_sp_neigh_entry_free(neigh_entry);
  692. }
  693. static struct mlxsw_sp_neigh_entry *
  694. mlxsw_sp_neigh_entry_lookup(struct mlxsw_sp *mlxsw_sp, struct neighbour *n)
  695. {
  696. struct mlxsw_sp_neigh_key key;
  697. key.n = n;
  698. return rhashtable_lookup_fast(&mlxsw_sp->router.neigh_ht,
  699. &key, mlxsw_sp_neigh_ht_params);
  700. }
  701. static void
  702. mlxsw_sp_router_neighs_update_interval_init(struct mlxsw_sp *mlxsw_sp)
  703. {
  704. unsigned long interval = NEIGH_VAR(&arp_tbl.parms, DELAY_PROBE_TIME);
  705. mlxsw_sp->router.neighs_update.interval = jiffies_to_msecs(interval);
  706. }
  707. static void mlxsw_sp_router_neigh_ent_ipv4_process(struct mlxsw_sp *mlxsw_sp,
  708. char *rauhtd_pl,
  709. int ent_index)
  710. {
  711. struct net_device *dev;
  712. struct neighbour *n;
  713. __be32 dipn;
  714. u32 dip;
  715. u16 rif;
  716. mlxsw_reg_rauhtd_ent_ipv4_unpack(rauhtd_pl, ent_index, &rif, &dip);
  717. if (!mlxsw_sp->rifs[rif]) {
  718. dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Incorrect RIF in neighbour entry\n");
  719. return;
  720. }
  721. dipn = htonl(dip);
  722. dev = mlxsw_sp->rifs[rif]->dev;
  723. n = neigh_lookup(&arp_tbl, &dipn, dev);
  724. if (!n) {
  725. netdev_err(dev, "Failed to find matching neighbour for IP=%pI4h\n",
  726. &dip);
  727. return;
  728. }
  729. netdev_dbg(dev, "Updating neighbour with IP=%pI4h\n", &dip);
  730. neigh_event_send(n, NULL);
  731. neigh_release(n);
  732. }
  733. static void mlxsw_sp_router_neigh_rec_ipv4_process(struct mlxsw_sp *mlxsw_sp,
  734. char *rauhtd_pl,
  735. int rec_index)
  736. {
  737. u8 num_entries;
  738. int i;
  739. num_entries = mlxsw_reg_rauhtd_ipv4_rec_num_entries_get(rauhtd_pl,
  740. rec_index);
  741. /* Hardware starts counting at 0, so add 1. */
  742. num_entries++;
  743. /* Each record consists of several neighbour entries. */
  744. for (i = 0; i < num_entries; i++) {
  745. int ent_index;
  746. ent_index = rec_index * MLXSW_REG_RAUHTD_IPV4_ENT_PER_REC + i;
  747. mlxsw_sp_router_neigh_ent_ipv4_process(mlxsw_sp, rauhtd_pl,
  748. ent_index);
  749. }
  750. }
  751. static void mlxsw_sp_router_neigh_rec_process(struct mlxsw_sp *mlxsw_sp,
  752. char *rauhtd_pl, int rec_index)
  753. {
  754. switch (mlxsw_reg_rauhtd_rec_type_get(rauhtd_pl, rec_index)) {
  755. case MLXSW_REG_RAUHTD_TYPE_IPV4:
  756. mlxsw_sp_router_neigh_rec_ipv4_process(mlxsw_sp, rauhtd_pl,
  757. rec_index);
  758. break;
  759. case MLXSW_REG_RAUHTD_TYPE_IPV6:
  760. WARN_ON_ONCE(1);
  761. break;
  762. }
  763. }
  764. static bool mlxsw_sp_router_rauhtd_is_full(char *rauhtd_pl)
  765. {
  766. u8 num_rec, last_rec_index, num_entries;
  767. num_rec = mlxsw_reg_rauhtd_num_rec_get(rauhtd_pl);
  768. last_rec_index = num_rec - 1;
  769. if (num_rec < MLXSW_REG_RAUHTD_REC_MAX_NUM)
  770. return false;
  771. if (mlxsw_reg_rauhtd_rec_type_get(rauhtd_pl, last_rec_index) ==
  772. MLXSW_REG_RAUHTD_TYPE_IPV6)
  773. return true;
  774. num_entries = mlxsw_reg_rauhtd_ipv4_rec_num_entries_get(rauhtd_pl,
  775. last_rec_index);
  776. if (++num_entries == MLXSW_REG_RAUHTD_IPV4_ENT_PER_REC)
  777. return true;
  778. return false;
  779. }
  780. static int mlxsw_sp_router_neighs_update_rauhtd(struct mlxsw_sp *mlxsw_sp)
  781. {
  782. char *rauhtd_pl;
  783. u8 num_rec;
  784. int i, err;
  785. rauhtd_pl = kmalloc(MLXSW_REG_RAUHTD_LEN, GFP_KERNEL);
  786. if (!rauhtd_pl)
  787. return -ENOMEM;
  788. /* Make sure the neighbour's netdev isn't removed in the
  789. * process.
  790. */
  791. rtnl_lock();
  792. do {
  793. mlxsw_reg_rauhtd_pack(rauhtd_pl, MLXSW_REG_RAUHTD_TYPE_IPV4);
  794. err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(rauhtd),
  795. rauhtd_pl);
  796. if (err) {
  797. dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to dump neighbour talbe\n");
  798. break;
  799. }
  800. num_rec = mlxsw_reg_rauhtd_num_rec_get(rauhtd_pl);
  801. for (i = 0; i < num_rec; i++)
  802. mlxsw_sp_router_neigh_rec_process(mlxsw_sp, rauhtd_pl,
  803. i);
  804. } while (mlxsw_sp_router_rauhtd_is_full(rauhtd_pl));
  805. rtnl_unlock();
  806. kfree(rauhtd_pl);
  807. return err;
  808. }
  809. static void mlxsw_sp_router_neighs_update_nh(struct mlxsw_sp *mlxsw_sp)
  810. {
  811. struct mlxsw_sp_neigh_entry *neigh_entry;
  812. /* Take RTNL mutex here to prevent lists from changes */
  813. rtnl_lock();
  814. list_for_each_entry(neigh_entry, &mlxsw_sp->router.nexthop_neighs_list,
  815. nexthop_neighs_list_node)
  816. /* If this neigh have nexthops, make the kernel think this neigh
  817. * is active regardless of the traffic.
  818. */
  819. neigh_event_send(neigh_entry->key.n, NULL);
  820. rtnl_unlock();
  821. }
  822. static void
  823. mlxsw_sp_router_neighs_update_work_schedule(struct mlxsw_sp *mlxsw_sp)
  824. {
  825. unsigned long interval = mlxsw_sp->router.neighs_update.interval;
  826. mlxsw_core_schedule_dw(&mlxsw_sp->router.neighs_update.dw,
  827. msecs_to_jiffies(interval));
  828. }
  829. static void mlxsw_sp_router_neighs_update_work(struct work_struct *work)
  830. {
  831. struct mlxsw_sp *mlxsw_sp = container_of(work, struct mlxsw_sp,
  832. router.neighs_update.dw.work);
  833. int err;
  834. err = mlxsw_sp_router_neighs_update_rauhtd(mlxsw_sp);
  835. if (err)
  836. dev_err(mlxsw_sp->bus_info->dev, "Could not update kernel for neigh activity");
  837. mlxsw_sp_router_neighs_update_nh(mlxsw_sp);
  838. mlxsw_sp_router_neighs_update_work_schedule(mlxsw_sp);
  839. }
  840. static void mlxsw_sp_router_probe_unresolved_nexthops(struct work_struct *work)
  841. {
  842. struct mlxsw_sp_neigh_entry *neigh_entry;
  843. struct mlxsw_sp *mlxsw_sp = container_of(work, struct mlxsw_sp,
  844. router.nexthop_probe_dw.work);
  845. /* Iterate over nexthop neighbours, find those who are unresolved and
  846. * send arp on them. This solves the chicken-egg problem when
  847. * the nexthop wouldn't get offloaded until the neighbor is resolved
  848. * but it wouldn't get resolved ever in case traffic is flowing in HW
  849. * using different nexthop.
  850. *
  851. * Take RTNL mutex here to prevent lists from changes.
  852. */
  853. rtnl_lock();
  854. list_for_each_entry(neigh_entry, &mlxsw_sp->router.nexthop_neighs_list,
  855. nexthop_neighs_list_node)
  856. if (!neigh_entry->connected)
  857. neigh_event_send(neigh_entry->key.n, NULL);
  858. rtnl_unlock();
  859. mlxsw_core_schedule_dw(&mlxsw_sp->router.nexthop_probe_dw,
  860. MLXSW_SP_UNRESOLVED_NH_PROBE_INTERVAL);
  861. }
  862. static void
  863. mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp *mlxsw_sp,
  864. struct mlxsw_sp_neigh_entry *neigh_entry,
  865. bool removing);
  866. static enum mlxsw_reg_rauht_op mlxsw_sp_rauht_op(bool adding)
  867. {
  868. return adding ? MLXSW_REG_RAUHT_OP_WRITE_ADD :
  869. MLXSW_REG_RAUHT_OP_WRITE_DELETE;
  870. }
  871. static void
  872. mlxsw_sp_router_neigh_entry_op4(struct mlxsw_sp *mlxsw_sp,
  873. struct mlxsw_sp_neigh_entry *neigh_entry,
  874. enum mlxsw_reg_rauht_op op)
  875. {
  876. struct neighbour *n = neigh_entry->key.n;
  877. u32 dip = ntohl(*((__be32 *) n->primary_key));
  878. char rauht_pl[MLXSW_REG_RAUHT_LEN];
  879. mlxsw_reg_rauht_pack4(rauht_pl, op, neigh_entry->rif, neigh_entry->ha,
  880. dip);
  881. mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rauht), rauht_pl);
  882. }
  883. static void
  884. mlxsw_sp_neigh_entry_update(struct mlxsw_sp *mlxsw_sp,
  885. struct mlxsw_sp_neigh_entry *neigh_entry,
  886. bool adding)
  887. {
  888. if (!adding && !neigh_entry->connected)
  889. return;
  890. neigh_entry->connected = adding;
  891. if (neigh_entry->key.n->tbl == &arp_tbl)
  892. mlxsw_sp_router_neigh_entry_op4(mlxsw_sp, neigh_entry,
  893. mlxsw_sp_rauht_op(adding));
  894. else
  895. WARN_ON_ONCE(1);
  896. }
  897. struct mlxsw_sp_neigh_event_work {
  898. struct work_struct work;
  899. struct mlxsw_sp *mlxsw_sp;
  900. struct neighbour *n;
  901. };
  902. static void mlxsw_sp_router_neigh_event_work(struct work_struct *work)
  903. {
  904. struct mlxsw_sp_neigh_event_work *neigh_work =
  905. container_of(work, struct mlxsw_sp_neigh_event_work, work);
  906. struct mlxsw_sp *mlxsw_sp = neigh_work->mlxsw_sp;
  907. struct mlxsw_sp_neigh_entry *neigh_entry;
  908. struct neighbour *n = neigh_work->n;
  909. unsigned char ha[ETH_ALEN];
  910. bool entry_connected;
  911. u8 nud_state, dead;
  912. /* If these parameters are changed after we release the lock,
  913. * then we are guaranteed to receive another event letting us
  914. * know about it.
  915. */
  916. read_lock_bh(&n->lock);
  917. memcpy(ha, n->ha, ETH_ALEN);
  918. nud_state = n->nud_state;
  919. dead = n->dead;
  920. read_unlock_bh(&n->lock);
  921. rtnl_lock();
  922. entry_connected = nud_state & NUD_VALID && !dead;
  923. neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, n);
  924. if (!entry_connected && !neigh_entry)
  925. goto out;
  926. if (!neigh_entry) {
  927. neigh_entry = mlxsw_sp_neigh_entry_create(mlxsw_sp, n);
  928. if (IS_ERR(neigh_entry))
  929. goto out;
  930. }
  931. memcpy(neigh_entry->ha, ha, ETH_ALEN);
  932. mlxsw_sp_neigh_entry_update(mlxsw_sp, neigh_entry, entry_connected);
  933. mlxsw_sp_nexthop_neigh_update(mlxsw_sp, neigh_entry, !entry_connected);
  934. if (!neigh_entry->connected && list_empty(&neigh_entry->nexthop_list))
  935. mlxsw_sp_neigh_entry_destroy(mlxsw_sp, neigh_entry);
  936. out:
  937. rtnl_unlock();
  938. neigh_release(n);
  939. kfree(neigh_work);
  940. }
  941. int mlxsw_sp_router_netevent_event(struct notifier_block *unused,
  942. unsigned long event, void *ptr)
  943. {
  944. struct mlxsw_sp_neigh_event_work *neigh_work;
  945. struct mlxsw_sp_port *mlxsw_sp_port;
  946. struct mlxsw_sp *mlxsw_sp;
  947. unsigned long interval;
  948. struct neigh_parms *p;
  949. struct neighbour *n;
  950. switch (event) {
  951. case NETEVENT_DELAY_PROBE_TIME_UPDATE:
  952. p = ptr;
  953. /* We don't care about changes in the default table. */
  954. if (!p->dev || p->tbl != &arp_tbl)
  955. return NOTIFY_DONE;
  956. /* We are in atomic context and can't take RTNL mutex,
  957. * so use RCU variant to walk the device chain.
  958. */
  959. mlxsw_sp_port = mlxsw_sp_port_lower_dev_hold(p->dev);
  960. if (!mlxsw_sp_port)
  961. return NOTIFY_DONE;
  962. mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
  963. interval = jiffies_to_msecs(NEIGH_VAR(p, DELAY_PROBE_TIME));
  964. mlxsw_sp->router.neighs_update.interval = interval;
  965. mlxsw_sp_port_dev_put(mlxsw_sp_port);
  966. break;
  967. case NETEVENT_NEIGH_UPDATE:
  968. n = ptr;
  969. if (n->tbl != &arp_tbl)
  970. return NOTIFY_DONE;
  971. mlxsw_sp_port = mlxsw_sp_port_lower_dev_hold(n->dev);
  972. if (!mlxsw_sp_port)
  973. return NOTIFY_DONE;
  974. neigh_work = kzalloc(sizeof(*neigh_work), GFP_ATOMIC);
  975. if (!neigh_work) {
  976. mlxsw_sp_port_dev_put(mlxsw_sp_port);
  977. return NOTIFY_BAD;
  978. }
  979. INIT_WORK(&neigh_work->work, mlxsw_sp_router_neigh_event_work);
  980. neigh_work->mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
  981. neigh_work->n = n;
  982. /* Take a reference to ensure the neighbour won't be
  983. * destructed until we drop the reference in delayed
  984. * work.
  985. */
  986. neigh_clone(n);
  987. mlxsw_core_schedule_work(&neigh_work->work);
  988. mlxsw_sp_port_dev_put(mlxsw_sp_port);
  989. break;
  990. }
  991. return NOTIFY_DONE;
  992. }
  993. static int mlxsw_sp_neigh_init(struct mlxsw_sp *mlxsw_sp)
  994. {
  995. int err;
  996. err = rhashtable_init(&mlxsw_sp->router.neigh_ht,
  997. &mlxsw_sp_neigh_ht_params);
  998. if (err)
  999. return err;
  1000. /* Initialize the polling interval according to the default
  1001. * table.
  1002. */
  1003. mlxsw_sp_router_neighs_update_interval_init(mlxsw_sp);
  1004. /* Create the delayed works for the activity_update */
  1005. INIT_DELAYED_WORK(&mlxsw_sp->router.neighs_update.dw,
  1006. mlxsw_sp_router_neighs_update_work);
  1007. INIT_DELAYED_WORK(&mlxsw_sp->router.nexthop_probe_dw,
  1008. mlxsw_sp_router_probe_unresolved_nexthops);
  1009. mlxsw_core_schedule_dw(&mlxsw_sp->router.neighs_update.dw, 0);
  1010. mlxsw_core_schedule_dw(&mlxsw_sp->router.nexthop_probe_dw, 0);
  1011. return 0;
  1012. }
  1013. static void mlxsw_sp_neigh_fini(struct mlxsw_sp *mlxsw_sp)
  1014. {
  1015. cancel_delayed_work_sync(&mlxsw_sp->router.neighs_update.dw);
  1016. cancel_delayed_work_sync(&mlxsw_sp->router.nexthop_probe_dw);
  1017. rhashtable_destroy(&mlxsw_sp->router.neigh_ht);
  1018. }
  1019. static int mlxsw_sp_neigh_rif_flush(struct mlxsw_sp *mlxsw_sp,
  1020. const struct mlxsw_sp_rif *rif)
  1021. {
  1022. char rauht_pl[MLXSW_REG_RAUHT_LEN];
  1023. mlxsw_reg_rauht_pack(rauht_pl, MLXSW_REG_RAUHT_OP_WRITE_DELETE_ALL,
  1024. rif->rif_index, rif->addr);
  1025. return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rauht), rauht_pl);
  1026. }
  1027. static void mlxsw_sp_neigh_rif_gone_sync(struct mlxsw_sp *mlxsw_sp,
  1028. struct mlxsw_sp_rif *rif)
  1029. {
  1030. struct mlxsw_sp_neigh_entry *neigh_entry, *tmp;
  1031. mlxsw_sp_neigh_rif_flush(mlxsw_sp, rif);
  1032. list_for_each_entry_safe(neigh_entry, tmp, &rif->neigh_list,
  1033. rif_list_node)
  1034. mlxsw_sp_neigh_entry_destroy(mlxsw_sp, neigh_entry);
  1035. }
  1036. struct mlxsw_sp_nexthop_key {
  1037. struct fib_nh *fib_nh;
  1038. };
  1039. struct mlxsw_sp_nexthop {
  1040. struct list_head neigh_list_node; /* member of neigh entry list */
  1041. struct list_head rif_list_node;
  1042. struct mlxsw_sp_nexthop_group *nh_grp; /* pointer back to the group
  1043. * this belongs to
  1044. */
  1045. struct rhash_head ht_node;
  1046. struct mlxsw_sp_nexthop_key key;
  1047. struct mlxsw_sp_rif *rif;
  1048. u8 should_offload:1, /* set indicates this neigh is connected and
  1049. * should be put to KVD linear area of this group.
  1050. */
  1051. offloaded:1, /* set in case the neigh is actually put into
  1052. * KVD linear area of this group.
  1053. */
  1054. update:1; /* set indicates that MAC of this neigh should be
  1055. * updated in HW
  1056. */
  1057. struct mlxsw_sp_neigh_entry *neigh_entry;
  1058. };
  1059. struct mlxsw_sp_nexthop_group_key {
  1060. struct fib_info *fi;
  1061. };
  1062. struct mlxsw_sp_nexthop_group {
  1063. struct rhash_head ht_node;
  1064. struct list_head fib_list; /* list of fib entries that use this group */
  1065. struct mlxsw_sp_nexthop_group_key key;
  1066. u8 adj_index_valid:1,
  1067. gateway:1; /* routes using the group use a gateway */
  1068. u32 adj_index;
  1069. u16 ecmp_size;
  1070. u16 count;
  1071. struct mlxsw_sp_nexthop nexthops[0];
  1072. #define nh_rif nexthops[0].rif
  1073. };
  1074. static const struct rhashtable_params mlxsw_sp_nexthop_group_ht_params = {
  1075. .key_offset = offsetof(struct mlxsw_sp_nexthop_group, key),
  1076. .head_offset = offsetof(struct mlxsw_sp_nexthop_group, ht_node),
  1077. .key_len = sizeof(struct mlxsw_sp_nexthop_group_key),
  1078. };
  1079. static int mlxsw_sp_nexthop_group_insert(struct mlxsw_sp *mlxsw_sp,
  1080. struct mlxsw_sp_nexthop_group *nh_grp)
  1081. {
  1082. return rhashtable_insert_fast(&mlxsw_sp->router.nexthop_group_ht,
  1083. &nh_grp->ht_node,
  1084. mlxsw_sp_nexthop_group_ht_params);
  1085. }
  1086. static void mlxsw_sp_nexthop_group_remove(struct mlxsw_sp *mlxsw_sp,
  1087. struct mlxsw_sp_nexthop_group *nh_grp)
  1088. {
  1089. rhashtable_remove_fast(&mlxsw_sp->router.nexthop_group_ht,
  1090. &nh_grp->ht_node,
  1091. mlxsw_sp_nexthop_group_ht_params);
  1092. }
  1093. static struct mlxsw_sp_nexthop_group *
  1094. mlxsw_sp_nexthop_group_lookup(struct mlxsw_sp *mlxsw_sp,
  1095. struct mlxsw_sp_nexthop_group_key key)
  1096. {
  1097. return rhashtable_lookup_fast(&mlxsw_sp->router.nexthop_group_ht, &key,
  1098. mlxsw_sp_nexthop_group_ht_params);
  1099. }
  1100. static const struct rhashtable_params mlxsw_sp_nexthop_ht_params = {
  1101. .key_offset = offsetof(struct mlxsw_sp_nexthop, key),
  1102. .head_offset = offsetof(struct mlxsw_sp_nexthop, ht_node),
  1103. .key_len = sizeof(struct mlxsw_sp_nexthop_key),
  1104. };
  1105. static int mlxsw_sp_nexthop_insert(struct mlxsw_sp *mlxsw_sp,
  1106. struct mlxsw_sp_nexthop *nh)
  1107. {
  1108. return rhashtable_insert_fast(&mlxsw_sp->router.nexthop_ht,
  1109. &nh->ht_node, mlxsw_sp_nexthop_ht_params);
  1110. }
  1111. static void mlxsw_sp_nexthop_remove(struct mlxsw_sp *mlxsw_sp,
  1112. struct mlxsw_sp_nexthop *nh)
  1113. {
  1114. rhashtable_remove_fast(&mlxsw_sp->router.nexthop_ht, &nh->ht_node,
  1115. mlxsw_sp_nexthop_ht_params);
  1116. }
  1117. static struct mlxsw_sp_nexthop *
  1118. mlxsw_sp_nexthop_lookup(struct mlxsw_sp *mlxsw_sp,
  1119. struct mlxsw_sp_nexthop_key key)
  1120. {
  1121. return rhashtable_lookup_fast(&mlxsw_sp->router.nexthop_ht, &key,
  1122. mlxsw_sp_nexthop_ht_params);
  1123. }
  1124. static int mlxsw_sp_adj_index_mass_update_vr(struct mlxsw_sp *mlxsw_sp,
  1125. const struct mlxsw_sp_fib *fib,
  1126. u32 adj_index, u16 ecmp_size,
  1127. u32 new_adj_index,
  1128. u16 new_ecmp_size)
  1129. {
  1130. char raleu_pl[MLXSW_REG_RALEU_LEN];
  1131. mlxsw_reg_raleu_pack(raleu_pl,
  1132. (enum mlxsw_reg_ralxx_protocol) fib->proto,
  1133. fib->vr->id, adj_index, ecmp_size, new_adj_index,
  1134. new_ecmp_size);
  1135. return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(raleu), raleu_pl);
  1136. }
  1137. static int mlxsw_sp_adj_index_mass_update(struct mlxsw_sp *mlxsw_sp,
  1138. struct mlxsw_sp_nexthop_group *nh_grp,
  1139. u32 old_adj_index, u16 old_ecmp_size)
  1140. {
  1141. struct mlxsw_sp_fib_entry *fib_entry;
  1142. struct mlxsw_sp_fib *fib = NULL;
  1143. int err;
  1144. list_for_each_entry(fib_entry, &nh_grp->fib_list, nexthop_group_node) {
  1145. if (fib == fib_entry->fib_node->fib)
  1146. continue;
  1147. fib = fib_entry->fib_node->fib;
  1148. err = mlxsw_sp_adj_index_mass_update_vr(mlxsw_sp, fib,
  1149. old_adj_index,
  1150. old_ecmp_size,
  1151. nh_grp->adj_index,
  1152. nh_grp->ecmp_size);
  1153. if (err)
  1154. return err;
  1155. }
  1156. return 0;
  1157. }
  1158. static int mlxsw_sp_nexthop_mac_update(struct mlxsw_sp *mlxsw_sp, u32 adj_index,
  1159. struct mlxsw_sp_nexthop *nh)
  1160. {
  1161. struct mlxsw_sp_neigh_entry *neigh_entry = nh->neigh_entry;
  1162. char ratr_pl[MLXSW_REG_RATR_LEN];
  1163. mlxsw_reg_ratr_pack(ratr_pl, MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY,
  1164. true, adj_index, neigh_entry->rif);
  1165. mlxsw_reg_ratr_eth_entry_pack(ratr_pl, neigh_entry->ha);
  1166. return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ratr), ratr_pl);
  1167. }
  1168. static int
  1169. mlxsw_sp_nexthop_group_mac_update(struct mlxsw_sp *mlxsw_sp,
  1170. struct mlxsw_sp_nexthop_group *nh_grp,
  1171. bool reallocate)
  1172. {
  1173. u32 adj_index = nh_grp->adj_index; /* base */
  1174. struct mlxsw_sp_nexthop *nh;
  1175. int i;
  1176. int err;
  1177. for (i = 0; i < nh_grp->count; i++) {
  1178. nh = &nh_grp->nexthops[i];
  1179. if (!nh->should_offload) {
  1180. nh->offloaded = 0;
  1181. continue;
  1182. }
  1183. if (nh->update || reallocate) {
  1184. err = mlxsw_sp_nexthop_mac_update(mlxsw_sp,
  1185. adj_index, nh);
  1186. if (err)
  1187. return err;
  1188. nh->update = 0;
  1189. nh->offloaded = 1;
  1190. }
  1191. adj_index++;
  1192. }
  1193. return 0;
  1194. }
  1195. static int mlxsw_sp_fib_entry_update(struct mlxsw_sp *mlxsw_sp,
  1196. struct mlxsw_sp_fib_entry *fib_entry);
  1197. static int
  1198. mlxsw_sp_nexthop_fib_entries_update(struct mlxsw_sp *mlxsw_sp,
  1199. struct mlxsw_sp_nexthop_group *nh_grp)
  1200. {
  1201. struct mlxsw_sp_fib_entry *fib_entry;
  1202. int err;
  1203. list_for_each_entry(fib_entry, &nh_grp->fib_list, nexthop_group_node) {
  1204. err = mlxsw_sp_fib_entry_update(mlxsw_sp, fib_entry);
  1205. if (err)
  1206. return err;
  1207. }
  1208. return 0;
  1209. }
  1210. static void
  1211. mlxsw_sp_nexthop_group_refresh(struct mlxsw_sp *mlxsw_sp,
  1212. struct mlxsw_sp_nexthop_group *nh_grp)
  1213. {
  1214. struct mlxsw_sp_nexthop *nh;
  1215. bool offload_change = false;
  1216. u32 adj_index;
  1217. u16 ecmp_size = 0;
  1218. bool old_adj_index_valid;
  1219. u32 old_adj_index;
  1220. u16 old_ecmp_size;
  1221. int i;
  1222. int err;
  1223. if (!nh_grp->gateway) {
  1224. mlxsw_sp_nexthop_fib_entries_update(mlxsw_sp, nh_grp);
  1225. return;
  1226. }
  1227. for (i = 0; i < nh_grp->count; i++) {
  1228. nh = &nh_grp->nexthops[i];
  1229. if (nh->should_offload ^ nh->offloaded) {
  1230. offload_change = true;
  1231. if (nh->should_offload)
  1232. nh->update = 1;
  1233. }
  1234. if (nh->should_offload)
  1235. ecmp_size++;
  1236. }
  1237. if (!offload_change) {
  1238. /* Nothing was added or removed, so no need to reallocate. Just
  1239. * update MAC on existing adjacency indexes.
  1240. */
  1241. err = mlxsw_sp_nexthop_group_mac_update(mlxsw_sp, nh_grp,
  1242. false);
  1243. if (err) {
  1244. dev_warn(mlxsw_sp->bus_info->dev, "Failed to update neigh MAC in adjacency table.\n");
  1245. goto set_trap;
  1246. }
  1247. return;
  1248. }
  1249. if (!ecmp_size)
  1250. /* No neigh of this group is connected so we just set
  1251. * the trap and let everthing flow through kernel.
  1252. */
  1253. goto set_trap;
  1254. err = mlxsw_sp_kvdl_alloc(mlxsw_sp, ecmp_size, &adj_index);
  1255. if (err) {
  1256. /* We ran out of KVD linear space, just set the
  1257. * trap and let everything flow through kernel.
  1258. */
  1259. dev_warn(mlxsw_sp->bus_info->dev, "Failed to allocate KVD linear area for nexthop group.\n");
  1260. goto set_trap;
  1261. }
  1262. old_adj_index_valid = nh_grp->adj_index_valid;
  1263. old_adj_index = nh_grp->adj_index;
  1264. old_ecmp_size = nh_grp->ecmp_size;
  1265. nh_grp->adj_index_valid = 1;
  1266. nh_grp->adj_index = adj_index;
  1267. nh_grp->ecmp_size = ecmp_size;
  1268. err = mlxsw_sp_nexthop_group_mac_update(mlxsw_sp, nh_grp, true);
  1269. if (err) {
  1270. dev_warn(mlxsw_sp->bus_info->dev, "Failed to update neigh MAC in adjacency table.\n");
  1271. goto set_trap;
  1272. }
  1273. if (!old_adj_index_valid) {
  1274. /* The trap was set for fib entries, so we have to call
  1275. * fib entry update to unset it and use adjacency index.
  1276. */
  1277. err = mlxsw_sp_nexthop_fib_entries_update(mlxsw_sp, nh_grp);
  1278. if (err) {
  1279. dev_warn(mlxsw_sp->bus_info->dev, "Failed to add adjacency index to fib entries.\n");
  1280. goto set_trap;
  1281. }
  1282. return;
  1283. }
  1284. err = mlxsw_sp_adj_index_mass_update(mlxsw_sp, nh_grp,
  1285. old_adj_index, old_ecmp_size);
  1286. mlxsw_sp_kvdl_free(mlxsw_sp, old_adj_index);
  1287. if (err) {
  1288. dev_warn(mlxsw_sp->bus_info->dev, "Failed to mass-update adjacency index for nexthop group.\n");
  1289. goto set_trap;
  1290. }
  1291. return;
  1292. set_trap:
  1293. old_adj_index_valid = nh_grp->adj_index_valid;
  1294. nh_grp->adj_index_valid = 0;
  1295. for (i = 0; i < nh_grp->count; i++) {
  1296. nh = &nh_grp->nexthops[i];
  1297. nh->offloaded = 0;
  1298. }
  1299. err = mlxsw_sp_nexthop_fib_entries_update(mlxsw_sp, nh_grp);
  1300. if (err)
  1301. dev_warn(mlxsw_sp->bus_info->dev, "Failed to set traps for fib entries.\n");
  1302. if (old_adj_index_valid)
  1303. mlxsw_sp_kvdl_free(mlxsw_sp, nh_grp->adj_index);
  1304. }
  1305. static void __mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp_nexthop *nh,
  1306. bool removing)
  1307. {
  1308. if (!removing && !nh->should_offload)
  1309. nh->should_offload = 1;
  1310. else if (removing && nh->offloaded)
  1311. nh->should_offload = 0;
  1312. nh->update = 1;
  1313. }
  1314. static void
  1315. mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp *mlxsw_sp,
  1316. struct mlxsw_sp_neigh_entry *neigh_entry,
  1317. bool removing)
  1318. {
  1319. struct mlxsw_sp_nexthop *nh;
  1320. list_for_each_entry(nh, &neigh_entry->nexthop_list,
  1321. neigh_list_node) {
  1322. __mlxsw_sp_nexthop_neigh_update(nh, removing);
  1323. mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nh_grp);
  1324. }
  1325. }
  1326. static void mlxsw_sp_nexthop_rif_init(struct mlxsw_sp_nexthop *nh,
  1327. struct mlxsw_sp_rif *rif)
  1328. {
  1329. if (nh->rif)
  1330. return;
  1331. nh->rif = rif;
  1332. list_add(&nh->rif_list_node, &rif->nexthop_list);
  1333. }
  1334. static void mlxsw_sp_nexthop_rif_fini(struct mlxsw_sp_nexthop *nh)
  1335. {
  1336. if (!nh->rif)
  1337. return;
  1338. list_del(&nh->rif_list_node);
  1339. nh->rif = NULL;
  1340. }
  1341. static int mlxsw_sp_nexthop_neigh_init(struct mlxsw_sp *mlxsw_sp,
  1342. struct mlxsw_sp_nexthop *nh)
  1343. {
  1344. struct mlxsw_sp_neigh_entry *neigh_entry;
  1345. struct fib_nh *fib_nh = nh->key.fib_nh;
  1346. struct neighbour *n;
  1347. u8 nud_state, dead;
  1348. int err;
  1349. if (!nh->nh_grp->gateway || nh->neigh_entry)
  1350. return 0;
  1351. /* Take a reference of neigh here ensuring that neigh would
  1352. * not be detructed before the nexthop entry is finished.
  1353. * The reference is taken either in neigh_lookup() or
  1354. * in neigh_create() in case n is not found.
  1355. */
  1356. n = neigh_lookup(&arp_tbl, &fib_nh->nh_gw, fib_nh->nh_dev);
  1357. if (!n) {
  1358. n = neigh_create(&arp_tbl, &fib_nh->nh_gw, fib_nh->nh_dev);
  1359. if (IS_ERR(n))
  1360. return PTR_ERR(n);
  1361. neigh_event_send(n, NULL);
  1362. }
  1363. neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, n);
  1364. if (!neigh_entry) {
  1365. neigh_entry = mlxsw_sp_neigh_entry_create(mlxsw_sp, n);
  1366. if (IS_ERR(neigh_entry)) {
  1367. err = -EINVAL;
  1368. goto err_neigh_entry_create;
  1369. }
  1370. }
  1371. /* If that is the first nexthop connected to that neigh, add to
  1372. * nexthop_neighs_list
  1373. */
  1374. if (list_empty(&neigh_entry->nexthop_list))
  1375. list_add_tail(&neigh_entry->nexthop_neighs_list_node,
  1376. &mlxsw_sp->router.nexthop_neighs_list);
  1377. nh->neigh_entry = neigh_entry;
  1378. list_add_tail(&nh->neigh_list_node, &neigh_entry->nexthop_list);
  1379. read_lock_bh(&n->lock);
  1380. nud_state = n->nud_state;
  1381. dead = n->dead;
  1382. read_unlock_bh(&n->lock);
  1383. __mlxsw_sp_nexthop_neigh_update(nh, !(nud_state & NUD_VALID && !dead));
  1384. return 0;
  1385. err_neigh_entry_create:
  1386. neigh_release(n);
  1387. return err;
  1388. }
  1389. static void mlxsw_sp_nexthop_neigh_fini(struct mlxsw_sp *mlxsw_sp,
  1390. struct mlxsw_sp_nexthop *nh)
  1391. {
  1392. struct mlxsw_sp_neigh_entry *neigh_entry = nh->neigh_entry;
  1393. struct neighbour *n;
  1394. if (!neigh_entry)
  1395. return;
  1396. n = neigh_entry->key.n;
  1397. __mlxsw_sp_nexthop_neigh_update(nh, true);
  1398. list_del(&nh->neigh_list_node);
  1399. nh->neigh_entry = NULL;
  1400. /* If that is the last nexthop connected to that neigh, remove from
  1401. * nexthop_neighs_list
  1402. */
  1403. if (list_empty(&neigh_entry->nexthop_list))
  1404. list_del(&neigh_entry->nexthop_neighs_list_node);
  1405. if (!neigh_entry->connected && list_empty(&neigh_entry->nexthop_list))
  1406. mlxsw_sp_neigh_entry_destroy(mlxsw_sp, neigh_entry);
  1407. neigh_release(n);
  1408. }
  1409. static int mlxsw_sp_nexthop_init(struct mlxsw_sp *mlxsw_sp,
  1410. struct mlxsw_sp_nexthop_group *nh_grp,
  1411. struct mlxsw_sp_nexthop *nh,
  1412. struct fib_nh *fib_nh)
  1413. {
  1414. struct net_device *dev = fib_nh->nh_dev;
  1415. struct in_device *in_dev;
  1416. struct mlxsw_sp_rif *rif;
  1417. int err;
  1418. nh->nh_grp = nh_grp;
  1419. nh->key.fib_nh = fib_nh;
  1420. err = mlxsw_sp_nexthop_insert(mlxsw_sp, nh);
  1421. if (err)
  1422. return err;
  1423. if (!dev)
  1424. return 0;
  1425. in_dev = __in_dev_get_rtnl(dev);
  1426. if (in_dev && IN_DEV_IGNORE_ROUTES_WITH_LINKDOWN(in_dev) &&
  1427. fib_nh->nh_flags & RTNH_F_LINKDOWN)
  1428. return 0;
  1429. rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
  1430. if (!rif)
  1431. return 0;
  1432. mlxsw_sp_nexthop_rif_init(nh, rif);
  1433. err = mlxsw_sp_nexthop_neigh_init(mlxsw_sp, nh);
  1434. if (err)
  1435. goto err_nexthop_neigh_init;
  1436. return 0;
  1437. err_nexthop_neigh_init:
  1438. mlxsw_sp_nexthop_remove(mlxsw_sp, nh);
  1439. return err;
  1440. }
  1441. static void mlxsw_sp_nexthop_fini(struct mlxsw_sp *mlxsw_sp,
  1442. struct mlxsw_sp_nexthop *nh)
  1443. {
  1444. mlxsw_sp_nexthop_neigh_fini(mlxsw_sp, nh);
  1445. mlxsw_sp_nexthop_rif_fini(nh);
  1446. mlxsw_sp_nexthop_remove(mlxsw_sp, nh);
  1447. }
  1448. static void mlxsw_sp_nexthop_event(struct mlxsw_sp *mlxsw_sp,
  1449. unsigned long event, struct fib_nh *fib_nh)
  1450. {
  1451. struct mlxsw_sp_nexthop_key key;
  1452. struct mlxsw_sp_nexthop *nh;
  1453. struct mlxsw_sp_rif *rif;
  1454. if (mlxsw_sp->router.aborted)
  1455. return;
  1456. key.fib_nh = fib_nh;
  1457. nh = mlxsw_sp_nexthop_lookup(mlxsw_sp, key);
  1458. if (WARN_ON_ONCE(!nh))
  1459. return;
  1460. rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, fib_nh->nh_dev);
  1461. if (!rif)
  1462. return;
  1463. switch (event) {
  1464. case FIB_EVENT_NH_ADD:
  1465. mlxsw_sp_nexthop_rif_init(nh, rif);
  1466. mlxsw_sp_nexthop_neigh_init(mlxsw_sp, nh);
  1467. break;
  1468. case FIB_EVENT_NH_DEL:
  1469. mlxsw_sp_nexthop_neigh_fini(mlxsw_sp, nh);
  1470. mlxsw_sp_nexthop_rif_fini(nh);
  1471. break;
  1472. }
  1473. mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nh_grp);
  1474. }
  1475. static void mlxsw_sp_nexthop_rif_gone_sync(struct mlxsw_sp *mlxsw_sp,
  1476. struct mlxsw_sp_rif *rif)
  1477. {
  1478. struct mlxsw_sp_nexthop *nh, *tmp;
  1479. list_for_each_entry_safe(nh, tmp, &rif->nexthop_list, rif_list_node) {
  1480. mlxsw_sp_nexthop_neigh_fini(mlxsw_sp, nh);
  1481. mlxsw_sp_nexthop_rif_fini(nh);
  1482. mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nh_grp);
  1483. }
  1484. }
  1485. static struct mlxsw_sp_nexthop_group *
  1486. mlxsw_sp_nexthop_group_create(struct mlxsw_sp *mlxsw_sp, struct fib_info *fi)
  1487. {
  1488. struct mlxsw_sp_nexthop_group *nh_grp;
  1489. struct mlxsw_sp_nexthop *nh;
  1490. struct fib_nh *fib_nh;
  1491. size_t alloc_size;
  1492. int i;
  1493. int err;
  1494. alloc_size = sizeof(*nh_grp) +
  1495. fi->fib_nhs * sizeof(struct mlxsw_sp_nexthop);
  1496. nh_grp = kzalloc(alloc_size, GFP_KERNEL);
  1497. if (!nh_grp)
  1498. return ERR_PTR(-ENOMEM);
  1499. INIT_LIST_HEAD(&nh_grp->fib_list);
  1500. nh_grp->gateway = fi->fib_nh->nh_scope == RT_SCOPE_LINK;
  1501. nh_grp->count = fi->fib_nhs;
  1502. nh_grp->key.fi = fi;
  1503. for (i = 0; i < nh_grp->count; i++) {
  1504. nh = &nh_grp->nexthops[i];
  1505. fib_nh = &fi->fib_nh[i];
  1506. err = mlxsw_sp_nexthop_init(mlxsw_sp, nh_grp, nh, fib_nh);
  1507. if (err)
  1508. goto err_nexthop_init;
  1509. }
  1510. err = mlxsw_sp_nexthop_group_insert(mlxsw_sp, nh_grp);
  1511. if (err)
  1512. goto err_nexthop_group_insert;
  1513. mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh_grp);
  1514. return nh_grp;
  1515. err_nexthop_group_insert:
  1516. err_nexthop_init:
  1517. for (i--; i >= 0; i--) {
  1518. nh = &nh_grp->nexthops[i];
  1519. mlxsw_sp_nexthop_fini(mlxsw_sp, nh);
  1520. }
  1521. kfree(nh_grp);
  1522. return ERR_PTR(err);
  1523. }
  1524. static void
  1525. mlxsw_sp_nexthop_group_destroy(struct mlxsw_sp *mlxsw_sp,
  1526. struct mlxsw_sp_nexthop_group *nh_grp)
  1527. {
  1528. struct mlxsw_sp_nexthop *nh;
  1529. int i;
  1530. mlxsw_sp_nexthop_group_remove(mlxsw_sp, nh_grp);
  1531. for (i = 0; i < nh_grp->count; i++) {
  1532. nh = &nh_grp->nexthops[i];
  1533. mlxsw_sp_nexthop_fini(mlxsw_sp, nh);
  1534. }
  1535. mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh_grp);
  1536. WARN_ON_ONCE(nh_grp->adj_index_valid);
  1537. kfree(nh_grp);
  1538. }
  1539. static int mlxsw_sp_nexthop_group_get(struct mlxsw_sp *mlxsw_sp,
  1540. struct mlxsw_sp_fib_entry *fib_entry,
  1541. struct fib_info *fi)
  1542. {
  1543. struct mlxsw_sp_nexthop_group_key key;
  1544. struct mlxsw_sp_nexthop_group *nh_grp;
  1545. key.fi = fi;
  1546. nh_grp = mlxsw_sp_nexthop_group_lookup(mlxsw_sp, key);
  1547. if (!nh_grp) {
  1548. nh_grp = mlxsw_sp_nexthop_group_create(mlxsw_sp, fi);
  1549. if (IS_ERR(nh_grp))
  1550. return PTR_ERR(nh_grp);
  1551. }
  1552. list_add_tail(&fib_entry->nexthop_group_node, &nh_grp->fib_list);
  1553. fib_entry->nh_group = nh_grp;
  1554. return 0;
  1555. }
  1556. static void mlxsw_sp_nexthop_group_put(struct mlxsw_sp *mlxsw_sp,
  1557. struct mlxsw_sp_fib_entry *fib_entry)
  1558. {
  1559. struct mlxsw_sp_nexthop_group *nh_grp = fib_entry->nh_group;
  1560. list_del(&fib_entry->nexthop_group_node);
  1561. if (!list_empty(&nh_grp->fib_list))
  1562. return;
  1563. mlxsw_sp_nexthop_group_destroy(mlxsw_sp, nh_grp);
  1564. }
  1565. static bool
  1566. mlxsw_sp_fib_entry_should_offload(const struct mlxsw_sp_fib_entry *fib_entry)
  1567. {
  1568. struct mlxsw_sp_nexthop_group *nh_group = fib_entry->nh_group;
  1569. if (fib_entry->params.tos)
  1570. return false;
  1571. switch (fib_entry->type) {
  1572. case MLXSW_SP_FIB_ENTRY_TYPE_REMOTE:
  1573. return !!nh_group->adj_index_valid;
  1574. case MLXSW_SP_FIB_ENTRY_TYPE_LOCAL:
  1575. return !!nh_group->nh_rif;
  1576. default:
  1577. return false;
  1578. }
  1579. }
  1580. static void mlxsw_sp_fib_entry_offload_set(struct mlxsw_sp_fib_entry *fib_entry)
  1581. {
  1582. fib_entry->offloaded = true;
  1583. switch (fib_entry->fib_node->fib->proto) {
  1584. case MLXSW_SP_L3_PROTO_IPV4:
  1585. fib_info_offload_inc(fib_entry->nh_group->key.fi);
  1586. break;
  1587. case MLXSW_SP_L3_PROTO_IPV6:
  1588. WARN_ON_ONCE(1);
  1589. }
  1590. }
  1591. static void
  1592. mlxsw_sp_fib_entry_offload_unset(struct mlxsw_sp_fib_entry *fib_entry)
  1593. {
  1594. switch (fib_entry->fib_node->fib->proto) {
  1595. case MLXSW_SP_L3_PROTO_IPV4:
  1596. fib_info_offload_dec(fib_entry->nh_group->key.fi);
  1597. break;
  1598. case MLXSW_SP_L3_PROTO_IPV6:
  1599. WARN_ON_ONCE(1);
  1600. }
  1601. fib_entry->offloaded = false;
  1602. }
  1603. static void
  1604. mlxsw_sp_fib_entry_offload_refresh(struct mlxsw_sp_fib_entry *fib_entry,
  1605. enum mlxsw_reg_ralue_op op, int err)
  1606. {
  1607. switch (op) {
  1608. case MLXSW_REG_RALUE_OP_WRITE_DELETE:
  1609. if (!fib_entry->offloaded)
  1610. return;
  1611. return mlxsw_sp_fib_entry_offload_unset(fib_entry);
  1612. case MLXSW_REG_RALUE_OP_WRITE_WRITE:
  1613. if (err)
  1614. return;
  1615. if (mlxsw_sp_fib_entry_should_offload(fib_entry) &&
  1616. !fib_entry->offloaded)
  1617. mlxsw_sp_fib_entry_offload_set(fib_entry);
  1618. else if (!mlxsw_sp_fib_entry_should_offload(fib_entry) &&
  1619. fib_entry->offloaded)
  1620. mlxsw_sp_fib_entry_offload_unset(fib_entry);
  1621. return;
  1622. default:
  1623. return;
  1624. }
  1625. }
  1626. static int mlxsw_sp_fib_entry_op4_remote(struct mlxsw_sp *mlxsw_sp,
  1627. struct mlxsw_sp_fib_entry *fib_entry,
  1628. enum mlxsw_reg_ralue_op op)
  1629. {
  1630. char ralue_pl[MLXSW_REG_RALUE_LEN];
  1631. struct mlxsw_sp_fib *fib = fib_entry->fib_node->fib;
  1632. u32 *p_dip = (u32 *) fib_entry->fib_node->key.addr;
  1633. enum mlxsw_reg_ralue_trap_action trap_action;
  1634. u16 trap_id = 0;
  1635. u32 adjacency_index = 0;
  1636. u16 ecmp_size = 0;
  1637. /* In case the nexthop group adjacency index is valid, use it
  1638. * with provided ECMP size. Otherwise, setup trap and pass
  1639. * traffic to kernel.
  1640. */
  1641. if (mlxsw_sp_fib_entry_should_offload(fib_entry)) {
  1642. trap_action = MLXSW_REG_RALUE_TRAP_ACTION_NOP;
  1643. adjacency_index = fib_entry->nh_group->adj_index;
  1644. ecmp_size = fib_entry->nh_group->ecmp_size;
  1645. } else {
  1646. trap_action = MLXSW_REG_RALUE_TRAP_ACTION_TRAP;
  1647. trap_id = MLXSW_TRAP_ID_RTR_INGRESS0;
  1648. }
  1649. mlxsw_reg_ralue_pack4(ralue_pl,
  1650. (enum mlxsw_reg_ralxx_protocol) fib->proto, op,
  1651. fib->vr->id, fib_entry->fib_node->key.prefix_len,
  1652. *p_dip);
  1653. mlxsw_reg_ralue_act_remote_pack(ralue_pl, trap_action, trap_id,
  1654. adjacency_index, ecmp_size);
  1655. return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl);
  1656. }
  1657. static int mlxsw_sp_fib_entry_op4_local(struct mlxsw_sp *mlxsw_sp,
  1658. struct mlxsw_sp_fib_entry *fib_entry,
  1659. enum mlxsw_reg_ralue_op op)
  1660. {
  1661. struct mlxsw_sp_rif *rif = fib_entry->nh_group->nh_rif;
  1662. struct mlxsw_sp_fib *fib = fib_entry->fib_node->fib;
  1663. enum mlxsw_reg_ralue_trap_action trap_action;
  1664. char ralue_pl[MLXSW_REG_RALUE_LEN];
  1665. u32 *p_dip = (u32 *) fib_entry->fib_node->key.addr;
  1666. u16 trap_id = 0;
  1667. u16 rif_index = 0;
  1668. if (mlxsw_sp_fib_entry_should_offload(fib_entry)) {
  1669. trap_action = MLXSW_REG_RALUE_TRAP_ACTION_NOP;
  1670. rif_index = rif->rif_index;
  1671. } else {
  1672. trap_action = MLXSW_REG_RALUE_TRAP_ACTION_TRAP;
  1673. trap_id = MLXSW_TRAP_ID_RTR_INGRESS0;
  1674. }
  1675. mlxsw_reg_ralue_pack4(ralue_pl,
  1676. (enum mlxsw_reg_ralxx_protocol) fib->proto, op,
  1677. fib->vr->id, fib_entry->fib_node->key.prefix_len,
  1678. *p_dip);
  1679. mlxsw_reg_ralue_act_local_pack(ralue_pl, trap_action, trap_id,
  1680. rif_index);
  1681. return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl);
  1682. }
  1683. static int mlxsw_sp_fib_entry_op4_trap(struct mlxsw_sp *mlxsw_sp,
  1684. struct mlxsw_sp_fib_entry *fib_entry,
  1685. enum mlxsw_reg_ralue_op op)
  1686. {
  1687. struct mlxsw_sp_fib *fib = fib_entry->fib_node->fib;
  1688. char ralue_pl[MLXSW_REG_RALUE_LEN];
  1689. u32 *p_dip = (u32 *) fib_entry->fib_node->key.addr;
  1690. mlxsw_reg_ralue_pack4(ralue_pl,
  1691. (enum mlxsw_reg_ralxx_protocol) fib->proto, op,
  1692. fib->vr->id, fib_entry->fib_node->key.prefix_len,
  1693. *p_dip);
  1694. mlxsw_reg_ralue_act_ip2me_pack(ralue_pl);
  1695. return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl);
  1696. }
  1697. static int mlxsw_sp_fib_entry_op4(struct mlxsw_sp *mlxsw_sp,
  1698. struct mlxsw_sp_fib_entry *fib_entry,
  1699. enum mlxsw_reg_ralue_op op)
  1700. {
  1701. switch (fib_entry->type) {
  1702. case MLXSW_SP_FIB_ENTRY_TYPE_REMOTE:
  1703. return mlxsw_sp_fib_entry_op4_remote(mlxsw_sp, fib_entry, op);
  1704. case MLXSW_SP_FIB_ENTRY_TYPE_LOCAL:
  1705. return mlxsw_sp_fib_entry_op4_local(mlxsw_sp, fib_entry, op);
  1706. case MLXSW_SP_FIB_ENTRY_TYPE_TRAP:
  1707. return mlxsw_sp_fib_entry_op4_trap(mlxsw_sp, fib_entry, op);
  1708. }
  1709. return -EINVAL;
  1710. }
  1711. static int mlxsw_sp_fib_entry_op(struct mlxsw_sp *mlxsw_sp,
  1712. struct mlxsw_sp_fib_entry *fib_entry,
  1713. enum mlxsw_reg_ralue_op op)
  1714. {
  1715. int err = -EINVAL;
  1716. switch (fib_entry->fib_node->fib->proto) {
  1717. case MLXSW_SP_L3_PROTO_IPV4:
  1718. err = mlxsw_sp_fib_entry_op4(mlxsw_sp, fib_entry, op);
  1719. break;
  1720. case MLXSW_SP_L3_PROTO_IPV6:
  1721. return err;
  1722. }
  1723. mlxsw_sp_fib_entry_offload_refresh(fib_entry, op, err);
  1724. return err;
  1725. }
  1726. static int mlxsw_sp_fib_entry_update(struct mlxsw_sp *mlxsw_sp,
  1727. struct mlxsw_sp_fib_entry *fib_entry)
  1728. {
  1729. return mlxsw_sp_fib_entry_op(mlxsw_sp, fib_entry,
  1730. MLXSW_REG_RALUE_OP_WRITE_WRITE);
  1731. }
  1732. static int mlxsw_sp_fib_entry_del(struct mlxsw_sp *mlxsw_sp,
  1733. struct mlxsw_sp_fib_entry *fib_entry)
  1734. {
  1735. return mlxsw_sp_fib_entry_op(mlxsw_sp, fib_entry,
  1736. MLXSW_REG_RALUE_OP_WRITE_DELETE);
  1737. }
  1738. static int
  1739. mlxsw_sp_fib4_entry_type_set(struct mlxsw_sp *mlxsw_sp,
  1740. const struct fib_entry_notifier_info *fen_info,
  1741. struct mlxsw_sp_fib_entry *fib_entry)
  1742. {
  1743. struct fib_info *fi = fen_info->fi;
  1744. switch (fen_info->type) {
  1745. case RTN_BROADCAST: /* fall through */
  1746. case RTN_LOCAL:
  1747. fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP;
  1748. return 0;
  1749. case RTN_UNREACHABLE: /* fall through */
  1750. case RTN_BLACKHOLE: /* fall through */
  1751. case RTN_PROHIBIT:
  1752. /* Packets hitting these routes need to be trapped, but
  1753. * can do so with a lower priority than packets directed
  1754. * at the host, so use action type local instead of trap.
  1755. */
  1756. fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_LOCAL;
  1757. return 0;
  1758. case RTN_UNICAST:
  1759. if (fi->fib_nh->nh_scope != RT_SCOPE_LINK)
  1760. fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_LOCAL;
  1761. else
  1762. fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_REMOTE;
  1763. return 0;
  1764. default:
  1765. return -EINVAL;
  1766. }
  1767. }
  1768. static struct mlxsw_sp_fib_entry *
  1769. mlxsw_sp_fib4_entry_create(struct mlxsw_sp *mlxsw_sp,
  1770. struct mlxsw_sp_fib_node *fib_node,
  1771. const struct fib_entry_notifier_info *fen_info)
  1772. {
  1773. struct mlxsw_sp_fib_entry *fib_entry;
  1774. int err;
  1775. fib_entry = kzalloc(sizeof(*fib_entry), GFP_KERNEL);
  1776. if (!fib_entry) {
  1777. err = -ENOMEM;
  1778. goto err_fib_entry_alloc;
  1779. }
  1780. err = mlxsw_sp_fib4_entry_type_set(mlxsw_sp, fen_info, fib_entry);
  1781. if (err)
  1782. goto err_fib4_entry_type_set;
  1783. err = mlxsw_sp_nexthop_group_get(mlxsw_sp, fib_entry, fen_info->fi);
  1784. if (err)
  1785. goto err_nexthop_group_get;
  1786. fib_entry->params.prio = fen_info->fi->fib_priority;
  1787. fib_entry->params.tb_id = fen_info->tb_id;
  1788. fib_entry->params.type = fen_info->type;
  1789. fib_entry->params.tos = fen_info->tos;
  1790. fib_entry->fib_node = fib_node;
  1791. return fib_entry;
  1792. err_nexthop_group_get:
  1793. err_fib4_entry_type_set:
  1794. kfree(fib_entry);
  1795. err_fib_entry_alloc:
  1796. return ERR_PTR(err);
  1797. }
  1798. static void mlxsw_sp_fib4_entry_destroy(struct mlxsw_sp *mlxsw_sp,
  1799. struct mlxsw_sp_fib_entry *fib_entry)
  1800. {
  1801. mlxsw_sp_nexthop_group_put(mlxsw_sp, fib_entry);
  1802. kfree(fib_entry);
  1803. }
  1804. static struct mlxsw_sp_fib_node *
  1805. mlxsw_sp_fib4_node_get(struct mlxsw_sp *mlxsw_sp,
  1806. const struct fib_entry_notifier_info *fen_info);
  1807. static struct mlxsw_sp_fib_entry *
  1808. mlxsw_sp_fib4_entry_lookup(struct mlxsw_sp *mlxsw_sp,
  1809. const struct fib_entry_notifier_info *fen_info)
  1810. {
  1811. struct mlxsw_sp_fib_entry *fib_entry;
  1812. struct mlxsw_sp_fib_node *fib_node;
  1813. fib_node = mlxsw_sp_fib4_node_get(mlxsw_sp, fen_info);
  1814. if (IS_ERR(fib_node))
  1815. return NULL;
  1816. list_for_each_entry(fib_entry, &fib_node->entry_list, list) {
  1817. if (fib_entry->params.tb_id == fen_info->tb_id &&
  1818. fib_entry->params.tos == fen_info->tos &&
  1819. fib_entry->params.type == fen_info->type &&
  1820. fib_entry->nh_group->key.fi == fen_info->fi) {
  1821. return fib_entry;
  1822. }
  1823. }
  1824. return NULL;
  1825. }
  1826. static const struct rhashtable_params mlxsw_sp_fib_ht_params = {
  1827. .key_offset = offsetof(struct mlxsw_sp_fib_node, key),
  1828. .head_offset = offsetof(struct mlxsw_sp_fib_node, ht_node),
  1829. .key_len = sizeof(struct mlxsw_sp_fib_key),
  1830. .automatic_shrinking = true,
  1831. };
  1832. static int mlxsw_sp_fib_node_insert(struct mlxsw_sp_fib *fib,
  1833. struct mlxsw_sp_fib_node *fib_node)
  1834. {
  1835. return rhashtable_insert_fast(&fib->ht, &fib_node->ht_node,
  1836. mlxsw_sp_fib_ht_params);
  1837. }
  1838. static void mlxsw_sp_fib_node_remove(struct mlxsw_sp_fib *fib,
  1839. struct mlxsw_sp_fib_node *fib_node)
  1840. {
  1841. rhashtable_remove_fast(&fib->ht, &fib_node->ht_node,
  1842. mlxsw_sp_fib_ht_params);
  1843. }
  1844. static struct mlxsw_sp_fib_node *
  1845. mlxsw_sp_fib_node_lookup(struct mlxsw_sp_fib *fib, const void *addr,
  1846. size_t addr_len, unsigned char prefix_len)
  1847. {
  1848. struct mlxsw_sp_fib_key key;
  1849. memset(&key, 0, sizeof(key));
  1850. memcpy(key.addr, addr, addr_len);
  1851. key.prefix_len = prefix_len;
  1852. return rhashtable_lookup_fast(&fib->ht, &key, mlxsw_sp_fib_ht_params);
  1853. }
  1854. static struct mlxsw_sp_fib_node *
  1855. mlxsw_sp_fib_node_create(struct mlxsw_sp_fib *fib, const void *addr,
  1856. size_t addr_len, unsigned char prefix_len)
  1857. {
  1858. struct mlxsw_sp_fib_node *fib_node;
  1859. fib_node = kzalloc(sizeof(*fib_node), GFP_KERNEL);
  1860. if (!fib_node)
  1861. return NULL;
  1862. INIT_LIST_HEAD(&fib_node->entry_list);
  1863. list_add(&fib_node->list, &fib->node_list);
  1864. memcpy(fib_node->key.addr, addr, addr_len);
  1865. fib_node->key.prefix_len = prefix_len;
  1866. return fib_node;
  1867. }
  1868. static void mlxsw_sp_fib_node_destroy(struct mlxsw_sp_fib_node *fib_node)
  1869. {
  1870. list_del(&fib_node->list);
  1871. WARN_ON(!list_empty(&fib_node->entry_list));
  1872. kfree(fib_node);
  1873. }
  1874. static bool
  1875. mlxsw_sp_fib_node_entry_is_first(const struct mlxsw_sp_fib_node *fib_node,
  1876. const struct mlxsw_sp_fib_entry *fib_entry)
  1877. {
  1878. return list_first_entry(&fib_node->entry_list,
  1879. struct mlxsw_sp_fib_entry, list) == fib_entry;
  1880. }
  1881. static void mlxsw_sp_fib_node_prefix_inc(struct mlxsw_sp_fib_node *fib_node)
  1882. {
  1883. unsigned char prefix_len = fib_node->key.prefix_len;
  1884. struct mlxsw_sp_fib *fib = fib_node->fib;
  1885. if (fib->prefix_ref_count[prefix_len]++ == 0)
  1886. mlxsw_sp_prefix_usage_set(&fib->prefix_usage, prefix_len);
  1887. }
  1888. static void mlxsw_sp_fib_node_prefix_dec(struct mlxsw_sp_fib_node *fib_node)
  1889. {
  1890. unsigned char prefix_len = fib_node->key.prefix_len;
  1891. struct mlxsw_sp_fib *fib = fib_node->fib;
  1892. if (--fib->prefix_ref_count[prefix_len] == 0)
  1893. mlxsw_sp_prefix_usage_clear(&fib->prefix_usage, prefix_len);
  1894. }
  1895. static int mlxsw_sp_fib_node_init(struct mlxsw_sp *mlxsw_sp,
  1896. struct mlxsw_sp_fib_node *fib_node,
  1897. struct mlxsw_sp_fib *fib)
  1898. {
  1899. struct mlxsw_sp_prefix_usage req_prefix_usage;
  1900. struct mlxsw_sp_lpm_tree *lpm_tree;
  1901. int err;
  1902. err = mlxsw_sp_fib_node_insert(fib, fib_node);
  1903. if (err)
  1904. return err;
  1905. fib_node->fib = fib;
  1906. mlxsw_sp_prefix_usage_cpy(&req_prefix_usage, &fib->prefix_usage);
  1907. mlxsw_sp_prefix_usage_set(&req_prefix_usage, fib_node->key.prefix_len);
  1908. if (!mlxsw_sp_prefix_usage_none(&fib->prefix_usage)) {
  1909. err = mlxsw_sp_vr_lpm_tree_check(mlxsw_sp, fib,
  1910. &req_prefix_usage);
  1911. if (err)
  1912. goto err_tree_check;
  1913. } else {
  1914. lpm_tree = mlxsw_sp_lpm_tree_get(mlxsw_sp, &req_prefix_usage,
  1915. fib->proto);
  1916. if (IS_ERR(lpm_tree))
  1917. return PTR_ERR(lpm_tree);
  1918. fib->lpm_tree = lpm_tree;
  1919. err = mlxsw_sp_vr_lpm_tree_bind(mlxsw_sp, fib);
  1920. if (err)
  1921. goto err_tree_bind;
  1922. }
  1923. mlxsw_sp_fib_node_prefix_inc(fib_node);
  1924. return 0;
  1925. err_tree_bind:
  1926. fib->lpm_tree = NULL;
  1927. mlxsw_sp_lpm_tree_put(mlxsw_sp, lpm_tree);
  1928. err_tree_check:
  1929. fib_node->fib = NULL;
  1930. mlxsw_sp_fib_node_remove(fib, fib_node);
  1931. return err;
  1932. }
  1933. static void mlxsw_sp_fib_node_fini(struct mlxsw_sp *mlxsw_sp,
  1934. struct mlxsw_sp_fib_node *fib_node)
  1935. {
  1936. struct mlxsw_sp_lpm_tree *lpm_tree = fib_node->fib->lpm_tree;
  1937. struct mlxsw_sp_fib *fib = fib_node->fib;
  1938. mlxsw_sp_fib_node_prefix_dec(fib_node);
  1939. if (mlxsw_sp_prefix_usage_none(&fib->prefix_usage)) {
  1940. mlxsw_sp_vr_lpm_tree_unbind(mlxsw_sp, fib);
  1941. fib->lpm_tree = NULL;
  1942. mlxsw_sp_lpm_tree_put(mlxsw_sp, lpm_tree);
  1943. } else {
  1944. mlxsw_sp_vr_lpm_tree_check(mlxsw_sp, fib, &fib->prefix_usage);
  1945. }
  1946. fib_node->fib = NULL;
  1947. mlxsw_sp_fib_node_remove(fib, fib_node);
  1948. }
  1949. static struct mlxsw_sp_fib_node *
  1950. mlxsw_sp_fib4_node_get(struct mlxsw_sp *mlxsw_sp,
  1951. const struct fib_entry_notifier_info *fen_info)
  1952. {
  1953. struct mlxsw_sp_fib_node *fib_node;
  1954. struct mlxsw_sp_fib *fib;
  1955. struct mlxsw_sp_vr *vr;
  1956. int err;
  1957. vr = mlxsw_sp_vr_get(mlxsw_sp, fen_info->tb_id);
  1958. if (IS_ERR(vr))
  1959. return ERR_CAST(vr);
  1960. fib = mlxsw_sp_vr_fib(vr, MLXSW_SP_L3_PROTO_IPV4);
  1961. fib_node = mlxsw_sp_fib_node_lookup(fib, &fen_info->dst,
  1962. sizeof(fen_info->dst),
  1963. fen_info->dst_len);
  1964. if (fib_node)
  1965. return fib_node;
  1966. fib_node = mlxsw_sp_fib_node_create(fib, &fen_info->dst,
  1967. sizeof(fen_info->dst),
  1968. fen_info->dst_len);
  1969. if (!fib_node) {
  1970. err = -ENOMEM;
  1971. goto err_fib_node_create;
  1972. }
  1973. err = mlxsw_sp_fib_node_init(mlxsw_sp, fib_node, fib);
  1974. if (err)
  1975. goto err_fib_node_init;
  1976. return fib_node;
  1977. err_fib_node_init:
  1978. mlxsw_sp_fib_node_destroy(fib_node);
  1979. err_fib_node_create:
  1980. mlxsw_sp_vr_put(vr);
  1981. return ERR_PTR(err);
  1982. }
  1983. static void mlxsw_sp_fib4_node_put(struct mlxsw_sp *mlxsw_sp,
  1984. struct mlxsw_sp_fib_node *fib_node)
  1985. {
  1986. struct mlxsw_sp_vr *vr = fib_node->fib->vr;
  1987. if (!list_empty(&fib_node->entry_list))
  1988. return;
  1989. mlxsw_sp_fib_node_fini(mlxsw_sp, fib_node);
  1990. mlxsw_sp_fib_node_destroy(fib_node);
  1991. mlxsw_sp_vr_put(vr);
  1992. }
  1993. static struct mlxsw_sp_fib_entry *
  1994. mlxsw_sp_fib4_node_entry_find(const struct mlxsw_sp_fib_node *fib_node,
  1995. const struct mlxsw_sp_fib_entry_params *params)
  1996. {
  1997. struct mlxsw_sp_fib_entry *fib_entry;
  1998. list_for_each_entry(fib_entry, &fib_node->entry_list, list) {
  1999. if (fib_entry->params.tb_id > params->tb_id)
  2000. continue;
  2001. if (fib_entry->params.tb_id != params->tb_id)
  2002. break;
  2003. if (fib_entry->params.tos > params->tos)
  2004. continue;
  2005. if (fib_entry->params.prio >= params->prio ||
  2006. fib_entry->params.tos < params->tos)
  2007. return fib_entry;
  2008. }
  2009. return NULL;
  2010. }
  2011. static int mlxsw_sp_fib4_node_list_append(struct mlxsw_sp_fib_entry *fib_entry,
  2012. struct mlxsw_sp_fib_entry *new_entry)
  2013. {
  2014. struct mlxsw_sp_fib_node *fib_node;
  2015. if (WARN_ON(!fib_entry))
  2016. return -EINVAL;
  2017. fib_node = fib_entry->fib_node;
  2018. list_for_each_entry_from(fib_entry, &fib_node->entry_list, list) {
  2019. if (fib_entry->params.tb_id != new_entry->params.tb_id ||
  2020. fib_entry->params.tos != new_entry->params.tos ||
  2021. fib_entry->params.prio != new_entry->params.prio)
  2022. break;
  2023. }
  2024. list_add_tail(&new_entry->list, &fib_entry->list);
  2025. return 0;
  2026. }
  2027. static int
  2028. mlxsw_sp_fib4_node_list_insert(struct mlxsw_sp_fib_node *fib_node,
  2029. struct mlxsw_sp_fib_entry *new_entry,
  2030. bool replace, bool append)
  2031. {
  2032. struct mlxsw_sp_fib_entry *fib_entry;
  2033. fib_entry = mlxsw_sp_fib4_node_entry_find(fib_node, &new_entry->params);
  2034. if (append)
  2035. return mlxsw_sp_fib4_node_list_append(fib_entry, new_entry);
  2036. if (replace && WARN_ON(!fib_entry))
  2037. return -EINVAL;
  2038. /* Insert new entry before replaced one, so that we can later
  2039. * remove the second.
  2040. */
  2041. if (fib_entry) {
  2042. list_add_tail(&new_entry->list, &fib_entry->list);
  2043. } else {
  2044. struct mlxsw_sp_fib_entry *last;
  2045. list_for_each_entry(last, &fib_node->entry_list, list) {
  2046. if (new_entry->params.tb_id > last->params.tb_id)
  2047. break;
  2048. fib_entry = last;
  2049. }
  2050. if (fib_entry)
  2051. list_add(&new_entry->list, &fib_entry->list);
  2052. else
  2053. list_add(&new_entry->list, &fib_node->entry_list);
  2054. }
  2055. return 0;
  2056. }
  2057. static void
  2058. mlxsw_sp_fib4_node_list_remove(struct mlxsw_sp_fib_entry *fib_entry)
  2059. {
  2060. list_del(&fib_entry->list);
  2061. }
  2062. static int
  2063. mlxsw_sp_fib4_node_entry_add(struct mlxsw_sp *mlxsw_sp,
  2064. const struct mlxsw_sp_fib_node *fib_node,
  2065. struct mlxsw_sp_fib_entry *fib_entry)
  2066. {
  2067. if (!mlxsw_sp_fib_node_entry_is_first(fib_node, fib_entry))
  2068. return 0;
  2069. /* To prevent packet loss, overwrite the previously offloaded
  2070. * entry.
  2071. */
  2072. if (!list_is_singular(&fib_node->entry_list)) {
  2073. enum mlxsw_reg_ralue_op op = MLXSW_REG_RALUE_OP_WRITE_DELETE;
  2074. struct mlxsw_sp_fib_entry *n = list_next_entry(fib_entry, list);
  2075. mlxsw_sp_fib_entry_offload_refresh(n, op, 0);
  2076. }
  2077. return mlxsw_sp_fib_entry_update(mlxsw_sp, fib_entry);
  2078. }
  2079. static void
  2080. mlxsw_sp_fib4_node_entry_del(struct mlxsw_sp *mlxsw_sp,
  2081. const struct mlxsw_sp_fib_node *fib_node,
  2082. struct mlxsw_sp_fib_entry *fib_entry)
  2083. {
  2084. if (!mlxsw_sp_fib_node_entry_is_first(fib_node, fib_entry))
  2085. return;
  2086. /* Promote the next entry by overwriting the deleted entry */
  2087. if (!list_is_singular(&fib_node->entry_list)) {
  2088. struct mlxsw_sp_fib_entry *n = list_next_entry(fib_entry, list);
  2089. enum mlxsw_reg_ralue_op op = MLXSW_REG_RALUE_OP_WRITE_DELETE;
  2090. mlxsw_sp_fib_entry_update(mlxsw_sp, n);
  2091. mlxsw_sp_fib_entry_offload_refresh(fib_entry, op, 0);
  2092. return;
  2093. }
  2094. mlxsw_sp_fib_entry_del(mlxsw_sp, fib_entry);
  2095. }
  2096. static int mlxsw_sp_fib4_node_entry_link(struct mlxsw_sp *mlxsw_sp,
  2097. struct mlxsw_sp_fib_entry *fib_entry,
  2098. bool replace, bool append)
  2099. {
  2100. struct mlxsw_sp_fib_node *fib_node = fib_entry->fib_node;
  2101. int err;
  2102. err = mlxsw_sp_fib4_node_list_insert(fib_node, fib_entry, replace,
  2103. append);
  2104. if (err)
  2105. return err;
  2106. err = mlxsw_sp_fib4_node_entry_add(mlxsw_sp, fib_node, fib_entry);
  2107. if (err)
  2108. goto err_fib4_node_entry_add;
  2109. return 0;
  2110. err_fib4_node_entry_add:
  2111. mlxsw_sp_fib4_node_list_remove(fib_entry);
  2112. return err;
  2113. }
  2114. static void
  2115. mlxsw_sp_fib4_node_entry_unlink(struct mlxsw_sp *mlxsw_sp,
  2116. struct mlxsw_sp_fib_entry *fib_entry)
  2117. {
  2118. struct mlxsw_sp_fib_node *fib_node = fib_entry->fib_node;
  2119. mlxsw_sp_fib4_node_entry_del(mlxsw_sp, fib_node, fib_entry);
  2120. mlxsw_sp_fib4_node_list_remove(fib_entry);
  2121. }
  2122. static void mlxsw_sp_fib4_entry_replace(struct mlxsw_sp *mlxsw_sp,
  2123. struct mlxsw_sp_fib_entry *fib_entry,
  2124. bool replace)
  2125. {
  2126. struct mlxsw_sp_fib_node *fib_node = fib_entry->fib_node;
  2127. struct mlxsw_sp_fib_entry *replaced;
  2128. if (!replace)
  2129. return;
  2130. /* We inserted the new entry before replaced one */
  2131. replaced = list_next_entry(fib_entry, list);
  2132. mlxsw_sp_fib4_node_entry_unlink(mlxsw_sp, replaced);
  2133. mlxsw_sp_fib4_entry_destroy(mlxsw_sp, replaced);
  2134. mlxsw_sp_fib4_node_put(mlxsw_sp, fib_node);
  2135. }
  2136. static int
  2137. mlxsw_sp_router_fib4_add(struct mlxsw_sp *mlxsw_sp,
  2138. const struct fib_entry_notifier_info *fen_info,
  2139. bool replace, bool append)
  2140. {
  2141. struct mlxsw_sp_fib_entry *fib_entry;
  2142. struct mlxsw_sp_fib_node *fib_node;
  2143. int err;
  2144. if (mlxsw_sp->router.aborted)
  2145. return 0;
  2146. fib_node = mlxsw_sp_fib4_node_get(mlxsw_sp, fen_info);
  2147. if (IS_ERR(fib_node)) {
  2148. dev_warn(mlxsw_sp->bus_info->dev, "Failed to get FIB node\n");
  2149. return PTR_ERR(fib_node);
  2150. }
  2151. fib_entry = mlxsw_sp_fib4_entry_create(mlxsw_sp, fib_node, fen_info);
  2152. if (IS_ERR(fib_entry)) {
  2153. dev_warn(mlxsw_sp->bus_info->dev, "Failed to create FIB entry\n");
  2154. err = PTR_ERR(fib_entry);
  2155. goto err_fib4_entry_create;
  2156. }
  2157. err = mlxsw_sp_fib4_node_entry_link(mlxsw_sp, fib_entry, replace,
  2158. append);
  2159. if (err) {
  2160. dev_warn(mlxsw_sp->bus_info->dev, "Failed to link FIB entry to node\n");
  2161. goto err_fib4_node_entry_link;
  2162. }
  2163. mlxsw_sp_fib4_entry_replace(mlxsw_sp, fib_entry, replace);
  2164. return 0;
  2165. err_fib4_node_entry_link:
  2166. mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib_entry);
  2167. err_fib4_entry_create:
  2168. mlxsw_sp_fib4_node_put(mlxsw_sp, fib_node);
  2169. return err;
  2170. }
  2171. static void mlxsw_sp_router_fib4_del(struct mlxsw_sp *mlxsw_sp,
  2172. struct fib_entry_notifier_info *fen_info)
  2173. {
  2174. struct mlxsw_sp_fib_entry *fib_entry;
  2175. struct mlxsw_sp_fib_node *fib_node;
  2176. if (mlxsw_sp->router.aborted)
  2177. return;
  2178. fib_entry = mlxsw_sp_fib4_entry_lookup(mlxsw_sp, fen_info);
  2179. if (WARN_ON(!fib_entry))
  2180. return;
  2181. fib_node = fib_entry->fib_node;
  2182. mlxsw_sp_fib4_node_entry_unlink(mlxsw_sp, fib_entry);
  2183. mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib_entry);
  2184. mlxsw_sp_fib4_node_put(mlxsw_sp, fib_node);
  2185. }
  2186. static int mlxsw_sp_router_set_abort_trap(struct mlxsw_sp *mlxsw_sp)
  2187. {
  2188. char ralta_pl[MLXSW_REG_RALTA_LEN];
  2189. char ralst_pl[MLXSW_REG_RALST_LEN];
  2190. int i, err;
  2191. mlxsw_reg_ralta_pack(ralta_pl, true, MLXSW_REG_RALXX_PROTOCOL_IPV4,
  2192. MLXSW_SP_LPM_TREE_MIN);
  2193. err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralta), ralta_pl);
  2194. if (err)
  2195. return err;
  2196. mlxsw_reg_ralst_pack(ralst_pl, 0xff, MLXSW_SP_LPM_TREE_MIN);
  2197. err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralst), ralst_pl);
  2198. if (err)
  2199. return err;
  2200. for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) {
  2201. struct mlxsw_sp_vr *vr = &mlxsw_sp->router.vrs[i];
  2202. char raltb_pl[MLXSW_REG_RALTB_LEN];
  2203. char ralue_pl[MLXSW_REG_RALUE_LEN];
  2204. if (!mlxsw_sp_vr_is_used(vr))
  2205. continue;
  2206. mlxsw_reg_raltb_pack(raltb_pl, vr->id,
  2207. MLXSW_REG_RALXX_PROTOCOL_IPV4,
  2208. MLXSW_SP_LPM_TREE_MIN);
  2209. err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(raltb),
  2210. raltb_pl);
  2211. if (err)
  2212. return err;
  2213. mlxsw_reg_ralue_pack4(ralue_pl, MLXSW_SP_L3_PROTO_IPV4,
  2214. MLXSW_REG_RALUE_OP_WRITE_WRITE, vr->id, 0,
  2215. 0);
  2216. mlxsw_reg_ralue_act_ip2me_pack(ralue_pl);
  2217. err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue),
  2218. ralue_pl);
  2219. if (err)
  2220. return err;
  2221. }
  2222. return 0;
  2223. }
  2224. static void mlxsw_sp_fib4_node_flush(struct mlxsw_sp *mlxsw_sp,
  2225. struct mlxsw_sp_fib_node *fib_node)
  2226. {
  2227. struct mlxsw_sp_fib_entry *fib_entry, *tmp;
  2228. list_for_each_entry_safe(fib_entry, tmp, &fib_node->entry_list, list) {
  2229. bool do_break = &tmp->list == &fib_node->entry_list;
  2230. mlxsw_sp_fib4_node_entry_unlink(mlxsw_sp, fib_entry);
  2231. mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib_entry);
  2232. mlxsw_sp_fib4_node_put(mlxsw_sp, fib_node);
  2233. /* Break when entry list is empty and node was freed.
  2234. * Otherwise, we'll access freed memory in the next
  2235. * iteration.
  2236. */
  2237. if (do_break)
  2238. break;
  2239. }
  2240. }
  2241. static void mlxsw_sp_fib_node_flush(struct mlxsw_sp *mlxsw_sp,
  2242. struct mlxsw_sp_fib_node *fib_node)
  2243. {
  2244. switch (fib_node->fib->proto) {
  2245. case MLXSW_SP_L3_PROTO_IPV4:
  2246. mlxsw_sp_fib4_node_flush(mlxsw_sp, fib_node);
  2247. break;
  2248. case MLXSW_SP_L3_PROTO_IPV6:
  2249. WARN_ON_ONCE(1);
  2250. break;
  2251. }
  2252. }
  2253. static void mlxsw_sp_vr_fib_flush(struct mlxsw_sp *mlxsw_sp,
  2254. struct mlxsw_sp_vr *vr,
  2255. enum mlxsw_sp_l3proto proto)
  2256. {
  2257. struct mlxsw_sp_fib *fib = mlxsw_sp_vr_fib(vr, proto);
  2258. struct mlxsw_sp_fib_node *fib_node, *tmp;
  2259. list_for_each_entry_safe(fib_node, tmp, &fib->node_list, list) {
  2260. bool do_break = &tmp->list == &fib->node_list;
  2261. mlxsw_sp_fib_node_flush(mlxsw_sp, fib_node);
  2262. if (do_break)
  2263. break;
  2264. }
  2265. }
  2266. static void mlxsw_sp_router_fib_flush(struct mlxsw_sp *mlxsw_sp)
  2267. {
  2268. int i;
  2269. for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) {
  2270. struct mlxsw_sp_vr *vr = &mlxsw_sp->router.vrs[i];
  2271. if (!mlxsw_sp_vr_is_used(vr))
  2272. continue;
  2273. mlxsw_sp_vr_fib_flush(mlxsw_sp, vr, MLXSW_SP_L3_PROTO_IPV4);
  2274. }
  2275. }
  2276. static void mlxsw_sp_router_fib4_abort(struct mlxsw_sp *mlxsw_sp)
  2277. {
  2278. int err;
  2279. if (mlxsw_sp->router.aborted)
  2280. return;
  2281. dev_warn(mlxsw_sp->bus_info->dev, "FIB abort triggered. Note that FIB entries are no longer being offloaded to this device.\n");
  2282. mlxsw_sp_router_fib_flush(mlxsw_sp);
  2283. mlxsw_sp->router.aborted = true;
  2284. err = mlxsw_sp_router_set_abort_trap(mlxsw_sp);
  2285. if (err)
  2286. dev_warn(mlxsw_sp->bus_info->dev, "Failed to set abort trap.\n");
  2287. }
  2288. struct mlxsw_sp_fib_event_work {
  2289. struct work_struct work;
  2290. union {
  2291. struct fib_entry_notifier_info fen_info;
  2292. struct fib_rule_notifier_info fr_info;
  2293. struct fib_nh_notifier_info fnh_info;
  2294. };
  2295. struct mlxsw_sp *mlxsw_sp;
  2296. unsigned long event;
  2297. };
  2298. static void mlxsw_sp_router_fib_event_work(struct work_struct *work)
  2299. {
  2300. struct mlxsw_sp_fib_event_work *fib_work =
  2301. container_of(work, struct mlxsw_sp_fib_event_work, work);
  2302. struct mlxsw_sp *mlxsw_sp = fib_work->mlxsw_sp;
  2303. struct fib_rule *rule;
  2304. bool replace, append;
  2305. int err;
  2306. /* Protect internal structures from changes */
  2307. rtnl_lock();
  2308. switch (fib_work->event) {
  2309. case FIB_EVENT_ENTRY_REPLACE: /* fall through */
  2310. case FIB_EVENT_ENTRY_APPEND: /* fall through */
  2311. case FIB_EVENT_ENTRY_ADD:
  2312. replace = fib_work->event == FIB_EVENT_ENTRY_REPLACE;
  2313. append = fib_work->event == FIB_EVENT_ENTRY_APPEND;
  2314. err = mlxsw_sp_router_fib4_add(mlxsw_sp, &fib_work->fen_info,
  2315. replace, append);
  2316. if (err)
  2317. mlxsw_sp_router_fib4_abort(mlxsw_sp);
  2318. fib_info_put(fib_work->fen_info.fi);
  2319. break;
  2320. case FIB_EVENT_ENTRY_DEL:
  2321. mlxsw_sp_router_fib4_del(mlxsw_sp, &fib_work->fen_info);
  2322. fib_info_put(fib_work->fen_info.fi);
  2323. break;
  2324. case FIB_EVENT_RULE_ADD: /* fall through */
  2325. case FIB_EVENT_RULE_DEL:
  2326. rule = fib_work->fr_info.rule;
  2327. if (!fib4_rule_default(rule) && !rule->l3mdev)
  2328. mlxsw_sp_router_fib4_abort(mlxsw_sp);
  2329. fib_rule_put(rule);
  2330. break;
  2331. case FIB_EVENT_NH_ADD: /* fall through */
  2332. case FIB_EVENT_NH_DEL:
  2333. mlxsw_sp_nexthop_event(mlxsw_sp, fib_work->event,
  2334. fib_work->fnh_info.fib_nh);
  2335. fib_info_put(fib_work->fnh_info.fib_nh->nh_parent);
  2336. break;
  2337. }
  2338. rtnl_unlock();
  2339. kfree(fib_work);
  2340. }
  2341. /* Called with rcu_read_lock() */
  2342. static int mlxsw_sp_router_fib_event(struct notifier_block *nb,
  2343. unsigned long event, void *ptr)
  2344. {
  2345. struct mlxsw_sp *mlxsw_sp = container_of(nb, struct mlxsw_sp, fib_nb);
  2346. struct mlxsw_sp_fib_event_work *fib_work;
  2347. struct fib_notifier_info *info = ptr;
  2348. if (!net_eq(info->net, &init_net))
  2349. return NOTIFY_DONE;
  2350. fib_work = kzalloc(sizeof(*fib_work), GFP_ATOMIC);
  2351. if (WARN_ON(!fib_work))
  2352. return NOTIFY_BAD;
  2353. INIT_WORK(&fib_work->work, mlxsw_sp_router_fib_event_work);
  2354. fib_work->mlxsw_sp = mlxsw_sp;
  2355. fib_work->event = event;
  2356. switch (event) {
  2357. case FIB_EVENT_ENTRY_REPLACE: /* fall through */
  2358. case FIB_EVENT_ENTRY_APPEND: /* fall through */
  2359. case FIB_EVENT_ENTRY_ADD: /* fall through */
  2360. case FIB_EVENT_ENTRY_DEL:
  2361. memcpy(&fib_work->fen_info, ptr, sizeof(fib_work->fen_info));
  2362. /* Take referece on fib_info to prevent it from being
  2363. * freed while work is queued. Release it afterwards.
  2364. */
  2365. fib_info_hold(fib_work->fen_info.fi);
  2366. break;
  2367. case FIB_EVENT_RULE_ADD: /* fall through */
  2368. case FIB_EVENT_RULE_DEL:
  2369. memcpy(&fib_work->fr_info, ptr, sizeof(fib_work->fr_info));
  2370. fib_rule_get(fib_work->fr_info.rule);
  2371. break;
  2372. case FIB_EVENT_NH_ADD: /* fall through */
  2373. case FIB_EVENT_NH_DEL:
  2374. memcpy(&fib_work->fnh_info, ptr, sizeof(fib_work->fnh_info));
  2375. fib_info_hold(fib_work->fnh_info.fib_nh->nh_parent);
  2376. break;
  2377. }
  2378. mlxsw_core_schedule_work(&fib_work->work);
  2379. return NOTIFY_DONE;
  2380. }
  2381. static struct mlxsw_sp_rif *
  2382. mlxsw_sp_rif_find_by_dev(const struct mlxsw_sp *mlxsw_sp,
  2383. const struct net_device *dev)
  2384. {
  2385. int i;
  2386. for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++)
  2387. if (mlxsw_sp->rifs[i] && mlxsw_sp->rifs[i]->dev == dev)
  2388. return mlxsw_sp->rifs[i];
  2389. return NULL;
  2390. }
  2391. static int mlxsw_sp_router_rif_disable(struct mlxsw_sp *mlxsw_sp, u16 rif)
  2392. {
  2393. char ritr_pl[MLXSW_REG_RITR_LEN];
  2394. int err;
  2395. mlxsw_reg_ritr_rif_pack(ritr_pl, rif);
  2396. err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
  2397. if (WARN_ON_ONCE(err))
  2398. return err;
  2399. mlxsw_reg_ritr_enable_set(ritr_pl, false);
  2400. return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
  2401. }
  2402. static void mlxsw_sp_router_rif_gone_sync(struct mlxsw_sp *mlxsw_sp,
  2403. struct mlxsw_sp_rif *rif)
  2404. {
  2405. mlxsw_sp_router_rif_disable(mlxsw_sp, rif->rif_index);
  2406. mlxsw_sp_nexthop_rif_gone_sync(mlxsw_sp, rif);
  2407. mlxsw_sp_neigh_rif_gone_sync(mlxsw_sp, rif);
  2408. }
  2409. static bool mlxsw_sp_rif_should_config(struct mlxsw_sp_rif *rif,
  2410. const struct in_device *in_dev,
  2411. unsigned long event)
  2412. {
  2413. switch (event) {
  2414. case NETDEV_UP:
  2415. if (!rif)
  2416. return true;
  2417. return false;
  2418. case NETDEV_DOWN:
  2419. if (rif && !in_dev->ifa_list &&
  2420. !netif_is_l3_slave(rif->dev))
  2421. return true;
  2422. /* It is possible we already removed the RIF ourselves
  2423. * if it was assigned to a netdev that is now a bridge
  2424. * or LAG slave.
  2425. */
  2426. return false;
  2427. }
  2428. return false;
  2429. }
  2430. #define MLXSW_SP_INVALID_INDEX_RIF 0xffff
  2431. static int mlxsw_sp_avail_rif_get(struct mlxsw_sp *mlxsw_sp)
  2432. {
  2433. int i;
  2434. for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++)
  2435. if (!mlxsw_sp->rifs[i])
  2436. return i;
  2437. return MLXSW_SP_INVALID_INDEX_RIF;
  2438. }
  2439. static void mlxsw_sp_vport_rif_sp_attr_get(struct mlxsw_sp_port *mlxsw_sp_vport,
  2440. bool *p_lagged, u16 *p_system_port)
  2441. {
  2442. u8 local_port = mlxsw_sp_vport->local_port;
  2443. *p_lagged = mlxsw_sp_vport->lagged;
  2444. *p_system_port = *p_lagged ? mlxsw_sp_vport->lag_id : local_port;
  2445. }
  2446. static int mlxsw_sp_vport_rif_sp_op(struct mlxsw_sp_port *mlxsw_sp_vport,
  2447. u16 vr_id, struct net_device *l3_dev,
  2448. u16 rif_index, bool create)
  2449. {
  2450. struct mlxsw_sp *mlxsw_sp = mlxsw_sp_vport->mlxsw_sp;
  2451. bool lagged = mlxsw_sp_vport->lagged;
  2452. char ritr_pl[MLXSW_REG_RITR_LEN];
  2453. u16 system_port;
  2454. mlxsw_reg_ritr_pack(ritr_pl, create, MLXSW_REG_RITR_SP_IF, rif_index,
  2455. vr_id, l3_dev->mtu, l3_dev->dev_addr);
  2456. mlxsw_sp_vport_rif_sp_attr_get(mlxsw_sp_vport, &lagged, &system_port);
  2457. mlxsw_reg_ritr_sp_if_pack(ritr_pl, lagged, system_port,
  2458. mlxsw_sp_vport_vid_get(mlxsw_sp_vport));
  2459. return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
  2460. }
  2461. static void mlxsw_sp_vport_rif_sp_leave(struct mlxsw_sp_port *mlxsw_sp_vport);
  2462. static u16 mlxsw_sp_rif_sp_to_fid(u16 rif_index)
  2463. {
  2464. return MLXSW_SP_RFID_BASE + rif_index;
  2465. }
  2466. static struct mlxsw_sp_fid *
  2467. mlxsw_sp_rfid_alloc(u16 fid, struct net_device *l3_dev)
  2468. {
  2469. struct mlxsw_sp_fid *f;
  2470. f = kzalloc(sizeof(*f), GFP_KERNEL);
  2471. if (!f)
  2472. return NULL;
  2473. f->leave = mlxsw_sp_vport_rif_sp_leave;
  2474. f->ref_count = 0;
  2475. f->dev = l3_dev;
  2476. f->fid = fid;
  2477. return f;
  2478. }
  2479. static struct mlxsw_sp_rif *
  2480. mlxsw_sp_rif_alloc(u16 rif_index, u16 vr_id, struct net_device *l3_dev,
  2481. struct mlxsw_sp_fid *f)
  2482. {
  2483. struct mlxsw_sp_rif *rif;
  2484. rif = kzalloc(sizeof(*rif), GFP_KERNEL);
  2485. if (!rif)
  2486. return NULL;
  2487. INIT_LIST_HEAD(&rif->nexthop_list);
  2488. INIT_LIST_HEAD(&rif->neigh_list);
  2489. ether_addr_copy(rif->addr, l3_dev->dev_addr);
  2490. rif->mtu = l3_dev->mtu;
  2491. rif->vr_id = vr_id;
  2492. rif->dev = l3_dev;
  2493. rif->rif_index = rif_index;
  2494. rif->f = f;
  2495. return rif;
  2496. }
  2497. u16 mlxsw_sp_rif_index(const struct mlxsw_sp_rif *rif)
  2498. {
  2499. return rif->rif_index;
  2500. }
  2501. int mlxsw_sp_rif_dev_ifindex(const struct mlxsw_sp_rif *rif)
  2502. {
  2503. return rif->dev->ifindex;
  2504. }
  2505. static struct mlxsw_sp_rif *
  2506. mlxsw_sp_vport_rif_sp_create(struct mlxsw_sp_port *mlxsw_sp_vport,
  2507. struct net_device *l3_dev)
  2508. {
  2509. struct mlxsw_sp *mlxsw_sp = mlxsw_sp_vport->mlxsw_sp;
  2510. u32 tb_id = l3mdev_fib_table(l3_dev);
  2511. struct mlxsw_sp_vr *vr;
  2512. struct mlxsw_sp_fid *f;
  2513. struct mlxsw_sp_rif *rif;
  2514. u16 fid, rif_index;
  2515. int err;
  2516. rif_index = mlxsw_sp_avail_rif_get(mlxsw_sp);
  2517. if (rif_index == MLXSW_SP_INVALID_INDEX_RIF)
  2518. return ERR_PTR(-ERANGE);
  2519. vr = mlxsw_sp_vr_get(mlxsw_sp, tb_id ? : RT_TABLE_MAIN);
  2520. if (IS_ERR(vr))
  2521. return ERR_CAST(vr);
  2522. err = mlxsw_sp_vport_rif_sp_op(mlxsw_sp_vport, vr->id, l3_dev,
  2523. rif_index, true);
  2524. if (err)
  2525. goto err_vport_rif_sp_op;
  2526. fid = mlxsw_sp_rif_sp_to_fid(rif_index);
  2527. err = mlxsw_sp_rif_fdb_op(mlxsw_sp, l3_dev->dev_addr, fid, true);
  2528. if (err)
  2529. goto err_rif_fdb_op;
  2530. f = mlxsw_sp_rfid_alloc(fid, l3_dev);
  2531. if (!f) {
  2532. err = -ENOMEM;
  2533. goto err_rfid_alloc;
  2534. }
  2535. rif = mlxsw_sp_rif_alloc(rif_index, vr->id, l3_dev, f);
  2536. if (!rif) {
  2537. err = -ENOMEM;
  2538. goto err_rif_alloc;
  2539. }
  2540. if (devlink_dpipe_table_counter_enabled(priv_to_devlink(mlxsw_sp->core),
  2541. MLXSW_SP_DPIPE_TABLE_NAME_ERIF)) {
  2542. err = mlxsw_sp_rif_counter_alloc(mlxsw_sp, rif,
  2543. MLXSW_SP_RIF_COUNTER_EGRESS);
  2544. if (err)
  2545. netdev_dbg(mlxsw_sp_vport->dev,
  2546. "Counter alloc Failed err=%d\n", err);
  2547. }
  2548. f->rif = rif;
  2549. mlxsw_sp->rifs[rif_index] = rif;
  2550. vr->rif_count++;
  2551. return rif;
  2552. err_rif_alloc:
  2553. kfree(f);
  2554. err_rfid_alloc:
  2555. mlxsw_sp_rif_fdb_op(mlxsw_sp, l3_dev->dev_addr, fid, false);
  2556. err_rif_fdb_op:
  2557. mlxsw_sp_vport_rif_sp_op(mlxsw_sp_vport, vr->id, l3_dev, rif_index,
  2558. false);
  2559. err_vport_rif_sp_op:
  2560. mlxsw_sp_vr_put(vr);
  2561. return ERR_PTR(err);
  2562. }
  2563. static void mlxsw_sp_vport_rif_sp_destroy(struct mlxsw_sp_port *mlxsw_sp_vport,
  2564. struct mlxsw_sp_rif *rif)
  2565. {
  2566. struct mlxsw_sp *mlxsw_sp = mlxsw_sp_vport->mlxsw_sp;
  2567. struct mlxsw_sp_vr *vr = &mlxsw_sp->router.vrs[rif->vr_id];
  2568. struct net_device *l3_dev = rif->dev;
  2569. struct mlxsw_sp_fid *f = rif->f;
  2570. u16 rif_index = rif->rif_index;
  2571. u16 fid = f->fid;
  2572. mlxsw_sp_router_rif_gone_sync(mlxsw_sp, rif);
  2573. mlxsw_sp_rif_counter_free(mlxsw_sp, rif, MLXSW_SP_RIF_COUNTER_EGRESS);
  2574. mlxsw_sp_rif_counter_free(mlxsw_sp, rif, MLXSW_SP_RIF_COUNTER_INGRESS);
  2575. vr->rif_count--;
  2576. mlxsw_sp->rifs[rif_index] = NULL;
  2577. f->rif = NULL;
  2578. kfree(rif);
  2579. kfree(f);
  2580. mlxsw_sp_rif_fdb_op(mlxsw_sp, l3_dev->dev_addr, fid, false);
  2581. mlxsw_sp_vport_rif_sp_op(mlxsw_sp_vport, vr->id, l3_dev, rif_index,
  2582. false);
  2583. mlxsw_sp_vr_put(vr);
  2584. }
  2585. static int mlxsw_sp_vport_rif_sp_join(struct mlxsw_sp_port *mlxsw_sp_vport,
  2586. struct net_device *l3_dev)
  2587. {
  2588. struct mlxsw_sp *mlxsw_sp = mlxsw_sp_vport->mlxsw_sp;
  2589. struct mlxsw_sp_rif *rif;
  2590. rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev);
  2591. if (!rif) {
  2592. rif = mlxsw_sp_vport_rif_sp_create(mlxsw_sp_vport, l3_dev);
  2593. if (IS_ERR(rif))
  2594. return PTR_ERR(rif);
  2595. }
  2596. mlxsw_sp_vport_fid_set(mlxsw_sp_vport, rif->f);
  2597. rif->f->ref_count++;
  2598. netdev_dbg(mlxsw_sp_vport->dev, "Joined FID=%d\n", rif->f->fid);
  2599. return 0;
  2600. }
  2601. static void mlxsw_sp_vport_rif_sp_leave(struct mlxsw_sp_port *mlxsw_sp_vport)
  2602. {
  2603. struct mlxsw_sp_fid *f = mlxsw_sp_vport_fid_get(mlxsw_sp_vport);
  2604. netdev_dbg(mlxsw_sp_vport->dev, "Left FID=%d\n", f->fid);
  2605. mlxsw_sp_vport_fid_set(mlxsw_sp_vport, NULL);
  2606. if (--f->ref_count == 0)
  2607. mlxsw_sp_vport_rif_sp_destroy(mlxsw_sp_vport, f->rif);
  2608. }
  2609. static int mlxsw_sp_inetaddr_vport_event(struct net_device *l3_dev,
  2610. struct net_device *port_dev,
  2611. unsigned long event, u16 vid)
  2612. {
  2613. struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(port_dev);
  2614. struct mlxsw_sp_port *mlxsw_sp_vport;
  2615. mlxsw_sp_vport = mlxsw_sp_port_vport_find(mlxsw_sp_port, vid);
  2616. if (WARN_ON(!mlxsw_sp_vport))
  2617. return -EINVAL;
  2618. switch (event) {
  2619. case NETDEV_UP:
  2620. return mlxsw_sp_vport_rif_sp_join(mlxsw_sp_vport, l3_dev);
  2621. case NETDEV_DOWN:
  2622. mlxsw_sp_vport_rif_sp_leave(mlxsw_sp_vport);
  2623. break;
  2624. }
  2625. return 0;
  2626. }
  2627. static int mlxsw_sp_inetaddr_port_event(struct net_device *port_dev,
  2628. unsigned long event)
  2629. {
  2630. if (netif_is_bridge_port(port_dev) ||
  2631. netif_is_lag_port(port_dev) ||
  2632. netif_is_ovs_port(port_dev))
  2633. return 0;
  2634. return mlxsw_sp_inetaddr_vport_event(port_dev, port_dev, event, 1);
  2635. }
  2636. static int __mlxsw_sp_inetaddr_lag_event(struct net_device *l3_dev,
  2637. struct net_device *lag_dev,
  2638. unsigned long event, u16 vid)
  2639. {
  2640. struct net_device *port_dev;
  2641. struct list_head *iter;
  2642. int err;
  2643. netdev_for_each_lower_dev(lag_dev, port_dev, iter) {
  2644. if (mlxsw_sp_port_dev_check(port_dev)) {
  2645. err = mlxsw_sp_inetaddr_vport_event(l3_dev, port_dev,
  2646. event, vid);
  2647. if (err)
  2648. return err;
  2649. }
  2650. }
  2651. return 0;
  2652. }
  2653. static int mlxsw_sp_inetaddr_lag_event(struct net_device *lag_dev,
  2654. unsigned long event)
  2655. {
  2656. if (netif_is_bridge_port(lag_dev))
  2657. return 0;
  2658. return __mlxsw_sp_inetaddr_lag_event(lag_dev, lag_dev, event, 1);
  2659. }
  2660. static struct mlxsw_sp_fid *mlxsw_sp_bridge_fid_get(struct mlxsw_sp *mlxsw_sp,
  2661. struct net_device *l3_dev)
  2662. {
  2663. u16 fid;
  2664. if (is_vlan_dev(l3_dev))
  2665. fid = vlan_dev_vlan_id(l3_dev);
  2666. else if (mlxsw_sp->master_bridge.dev == l3_dev)
  2667. fid = 1;
  2668. else
  2669. return mlxsw_sp_vfid_find(mlxsw_sp, l3_dev);
  2670. return mlxsw_sp_fid_find(mlxsw_sp, fid);
  2671. }
  2672. static u8 mlxsw_sp_router_port(const struct mlxsw_sp *mlxsw_sp)
  2673. {
  2674. return mlxsw_core_max_ports(mlxsw_sp->core) + 1;
  2675. }
  2676. static enum mlxsw_flood_table_type mlxsw_sp_flood_table_type_get(u16 fid)
  2677. {
  2678. return mlxsw_sp_fid_is_vfid(fid) ? MLXSW_REG_SFGC_TABLE_TYPE_FID :
  2679. MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFEST;
  2680. }
  2681. static u16 mlxsw_sp_flood_table_index_get(u16 fid)
  2682. {
  2683. return mlxsw_sp_fid_is_vfid(fid) ? mlxsw_sp_fid_to_vfid(fid) : fid;
  2684. }
  2685. static int mlxsw_sp_router_port_flood_set(struct mlxsw_sp *mlxsw_sp, u16 fid,
  2686. bool set)
  2687. {
  2688. u8 router_port = mlxsw_sp_router_port(mlxsw_sp);
  2689. enum mlxsw_flood_table_type table_type;
  2690. char *sftr_pl;
  2691. u16 index;
  2692. int err;
  2693. sftr_pl = kmalloc(MLXSW_REG_SFTR_LEN, GFP_KERNEL);
  2694. if (!sftr_pl)
  2695. return -ENOMEM;
  2696. table_type = mlxsw_sp_flood_table_type_get(fid);
  2697. index = mlxsw_sp_flood_table_index_get(fid);
  2698. mlxsw_reg_sftr_pack(sftr_pl, MLXSW_SP_FLOOD_TABLE_BC, index, table_type,
  2699. 1, router_port, set);
  2700. err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sftr), sftr_pl);
  2701. kfree(sftr_pl);
  2702. return err;
  2703. }
  2704. static enum mlxsw_reg_ritr_if_type mlxsw_sp_rif_type_get(u16 fid)
  2705. {
  2706. if (mlxsw_sp_fid_is_vfid(fid))
  2707. return MLXSW_REG_RITR_FID_IF;
  2708. else
  2709. return MLXSW_REG_RITR_VLAN_IF;
  2710. }
  2711. static int mlxsw_sp_rif_bridge_op(struct mlxsw_sp *mlxsw_sp, u16 vr_id,
  2712. struct net_device *l3_dev,
  2713. u16 fid, u16 rif,
  2714. bool create)
  2715. {
  2716. enum mlxsw_reg_ritr_if_type rif_type;
  2717. char ritr_pl[MLXSW_REG_RITR_LEN];
  2718. rif_type = mlxsw_sp_rif_type_get(fid);
  2719. mlxsw_reg_ritr_pack(ritr_pl, create, rif_type, rif, vr_id, l3_dev->mtu,
  2720. l3_dev->dev_addr);
  2721. mlxsw_reg_ritr_fid_set(ritr_pl, rif_type, fid);
  2722. return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
  2723. }
  2724. static int mlxsw_sp_rif_bridge_create(struct mlxsw_sp *mlxsw_sp,
  2725. struct net_device *l3_dev,
  2726. struct mlxsw_sp_fid *f)
  2727. {
  2728. u32 tb_id = l3mdev_fib_table(l3_dev);
  2729. struct mlxsw_sp_rif *rif;
  2730. struct mlxsw_sp_vr *vr;
  2731. u16 rif_index;
  2732. int err;
  2733. rif_index = mlxsw_sp_avail_rif_get(mlxsw_sp);
  2734. if (rif_index == MLXSW_SP_INVALID_INDEX_RIF)
  2735. return -ERANGE;
  2736. vr = mlxsw_sp_vr_get(mlxsw_sp, tb_id ? : RT_TABLE_MAIN);
  2737. if (IS_ERR(vr))
  2738. return PTR_ERR(vr);
  2739. err = mlxsw_sp_router_port_flood_set(mlxsw_sp, f->fid, true);
  2740. if (err)
  2741. goto err_port_flood_set;
  2742. err = mlxsw_sp_rif_bridge_op(mlxsw_sp, vr->id, l3_dev, f->fid,
  2743. rif_index, true);
  2744. if (err)
  2745. goto err_rif_bridge_op;
  2746. err = mlxsw_sp_rif_fdb_op(mlxsw_sp, l3_dev->dev_addr, f->fid, true);
  2747. if (err)
  2748. goto err_rif_fdb_op;
  2749. rif = mlxsw_sp_rif_alloc(rif_index, vr->id, l3_dev, f);
  2750. if (!rif) {
  2751. err = -ENOMEM;
  2752. goto err_rif_alloc;
  2753. }
  2754. f->rif = rif;
  2755. mlxsw_sp->rifs[rif_index] = rif;
  2756. vr->rif_count++;
  2757. netdev_dbg(l3_dev, "RIF=%d created\n", rif_index);
  2758. return 0;
  2759. err_rif_alloc:
  2760. mlxsw_sp_rif_fdb_op(mlxsw_sp, l3_dev->dev_addr, f->fid, false);
  2761. err_rif_fdb_op:
  2762. mlxsw_sp_rif_bridge_op(mlxsw_sp, vr->id, l3_dev, f->fid, rif_index,
  2763. false);
  2764. err_rif_bridge_op:
  2765. mlxsw_sp_router_port_flood_set(mlxsw_sp, f->fid, false);
  2766. err_port_flood_set:
  2767. mlxsw_sp_vr_put(vr);
  2768. return err;
  2769. }
  2770. void mlxsw_sp_rif_bridge_destroy(struct mlxsw_sp *mlxsw_sp,
  2771. struct mlxsw_sp_rif *rif)
  2772. {
  2773. struct mlxsw_sp_vr *vr = &mlxsw_sp->router.vrs[rif->vr_id];
  2774. struct net_device *l3_dev = rif->dev;
  2775. struct mlxsw_sp_fid *f = rif->f;
  2776. u16 rif_index = rif->rif_index;
  2777. mlxsw_sp_router_rif_gone_sync(mlxsw_sp, rif);
  2778. vr->rif_count--;
  2779. mlxsw_sp->rifs[rif_index] = NULL;
  2780. f->rif = NULL;
  2781. kfree(rif);
  2782. mlxsw_sp_rif_fdb_op(mlxsw_sp, l3_dev->dev_addr, f->fid, false);
  2783. mlxsw_sp_rif_bridge_op(mlxsw_sp, vr->id, l3_dev, f->fid, rif_index,
  2784. false);
  2785. mlxsw_sp_router_port_flood_set(mlxsw_sp, f->fid, false);
  2786. mlxsw_sp_vr_put(vr);
  2787. netdev_dbg(l3_dev, "RIF=%d destroyed\n", rif_index);
  2788. }
  2789. static int mlxsw_sp_inetaddr_bridge_event(struct net_device *l3_dev,
  2790. struct net_device *br_dev,
  2791. unsigned long event)
  2792. {
  2793. struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(l3_dev);
  2794. struct mlxsw_sp_fid *f;
  2795. /* FID can either be an actual FID if the L3 device is the
  2796. * VLAN-aware bridge or a VLAN device on top. Otherwise, the
  2797. * L3 device is a VLAN-unaware bridge and we get a vFID.
  2798. */
  2799. f = mlxsw_sp_bridge_fid_get(mlxsw_sp, l3_dev);
  2800. if (WARN_ON(!f))
  2801. return -EINVAL;
  2802. switch (event) {
  2803. case NETDEV_UP:
  2804. return mlxsw_sp_rif_bridge_create(mlxsw_sp, l3_dev, f);
  2805. case NETDEV_DOWN:
  2806. mlxsw_sp_rif_bridge_destroy(mlxsw_sp, f->rif);
  2807. break;
  2808. }
  2809. return 0;
  2810. }
  2811. static int mlxsw_sp_inetaddr_vlan_event(struct net_device *vlan_dev,
  2812. unsigned long event)
  2813. {
  2814. struct net_device *real_dev = vlan_dev_real_dev(vlan_dev);
  2815. struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(vlan_dev);
  2816. u16 vid = vlan_dev_vlan_id(vlan_dev);
  2817. if (mlxsw_sp_port_dev_check(real_dev))
  2818. return mlxsw_sp_inetaddr_vport_event(vlan_dev, real_dev, event,
  2819. vid);
  2820. else if (netif_is_lag_master(real_dev))
  2821. return __mlxsw_sp_inetaddr_lag_event(vlan_dev, real_dev, event,
  2822. vid);
  2823. else if (netif_is_bridge_master(real_dev) &&
  2824. mlxsw_sp->master_bridge.dev == real_dev)
  2825. return mlxsw_sp_inetaddr_bridge_event(vlan_dev, real_dev,
  2826. event);
  2827. return 0;
  2828. }
  2829. static int __mlxsw_sp_inetaddr_event(struct net_device *dev,
  2830. unsigned long event)
  2831. {
  2832. if (mlxsw_sp_port_dev_check(dev))
  2833. return mlxsw_sp_inetaddr_port_event(dev, event);
  2834. else if (netif_is_lag_master(dev))
  2835. return mlxsw_sp_inetaddr_lag_event(dev, event);
  2836. else if (netif_is_bridge_master(dev))
  2837. return mlxsw_sp_inetaddr_bridge_event(dev, dev, event);
  2838. else if (is_vlan_dev(dev))
  2839. return mlxsw_sp_inetaddr_vlan_event(dev, event);
  2840. else
  2841. return 0;
  2842. }
  2843. int mlxsw_sp_inetaddr_event(struct notifier_block *unused,
  2844. unsigned long event, void *ptr)
  2845. {
  2846. struct in_ifaddr *ifa = (struct in_ifaddr *) ptr;
  2847. struct net_device *dev = ifa->ifa_dev->dev;
  2848. struct mlxsw_sp *mlxsw_sp;
  2849. struct mlxsw_sp_rif *rif;
  2850. int err = 0;
  2851. mlxsw_sp = mlxsw_sp_lower_get(dev);
  2852. if (!mlxsw_sp)
  2853. goto out;
  2854. rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
  2855. if (!mlxsw_sp_rif_should_config(rif, ifa->ifa_dev, event))
  2856. goto out;
  2857. err = __mlxsw_sp_inetaddr_event(dev, event);
  2858. out:
  2859. return notifier_from_errno(err);
  2860. }
  2861. static int mlxsw_sp_rif_edit(struct mlxsw_sp *mlxsw_sp, u16 rif_index,
  2862. const char *mac, int mtu)
  2863. {
  2864. char ritr_pl[MLXSW_REG_RITR_LEN];
  2865. int err;
  2866. mlxsw_reg_ritr_rif_pack(ritr_pl, rif_index);
  2867. err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
  2868. if (err)
  2869. return err;
  2870. mlxsw_reg_ritr_mtu_set(ritr_pl, mtu);
  2871. mlxsw_reg_ritr_if_mac_memcpy_to(ritr_pl, mac);
  2872. mlxsw_reg_ritr_op_set(ritr_pl, MLXSW_REG_RITR_RIF_CREATE);
  2873. return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
  2874. }
  2875. int mlxsw_sp_netdevice_router_port_event(struct net_device *dev)
  2876. {
  2877. struct mlxsw_sp *mlxsw_sp;
  2878. struct mlxsw_sp_rif *rif;
  2879. int err;
  2880. mlxsw_sp = mlxsw_sp_lower_get(dev);
  2881. if (!mlxsw_sp)
  2882. return 0;
  2883. rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
  2884. if (!rif)
  2885. return 0;
  2886. err = mlxsw_sp_rif_fdb_op(mlxsw_sp, rif->addr, rif->f->fid, false);
  2887. if (err)
  2888. return err;
  2889. err = mlxsw_sp_rif_edit(mlxsw_sp, rif->rif_index, dev->dev_addr,
  2890. dev->mtu);
  2891. if (err)
  2892. goto err_rif_edit;
  2893. err = mlxsw_sp_rif_fdb_op(mlxsw_sp, dev->dev_addr, rif->f->fid, true);
  2894. if (err)
  2895. goto err_rif_fdb_op;
  2896. ether_addr_copy(rif->addr, dev->dev_addr);
  2897. rif->mtu = dev->mtu;
  2898. netdev_dbg(dev, "Updated RIF=%d\n", rif->rif_index);
  2899. return 0;
  2900. err_rif_fdb_op:
  2901. mlxsw_sp_rif_edit(mlxsw_sp, rif->rif_index, rif->addr, rif->mtu);
  2902. err_rif_edit:
  2903. mlxsw_sp_rif_fdb_op(mlxsw_sp, rif->addr, rif->f->fid, true);
  2904. return err;
  2905. }
  2906. static int mlxsw_sp_port_vrf_join(struct mlxsw_sp *mlxsw_sp,
  2907. struct net_device *l3_dev)
  2908. {
  2909. struct mlxsw_sp_rif *rif;
  2910. /* If netdev is already associated with a RIF, then we need to
  2911. * destroy it and create a new one with the new virtual router ID.
  2912. */
  2913. rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev);
  2914. if (rif)
  2915. __mlxsw_sp_inetaddr_event(l3_dev, NETDEV_DOWN);
  2916. return __mlxsw_sp_inetaddr_event(l3_dev, NETDEV_UP);
  2917. }
  2918. static void mlxsw_sp_port_vrf_leave(struct mlxsw_sp *mlxsw_sp,
  2919. struct net_device *l3_dev)
  2920. {
  2921. struct mlxsw_sp_rif *rif;
  2922. rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev);
  2923. if (!rif)
  2924. return;
  2925. __mlxsw_sp_inetaddr_event(l3_dev, NETDEV_DOWN);
  2926. }
  2927. int mlxsw_sp_netdevice_vrf_event(struct net_device *l3_dev, unsigned long event,
  2928. struct netdev_notifier_changeupper_info *info)
  2929. {
  2930. struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(l3_dev);
  2931. int err = 0;
  2932. if (!mlxsw_sp)
  2933. return 0;
  2934. switch (event) {
  2935. case NETDEV_PRECHANGEUPPER:
  2936. return 0;
  2937. case NETDEV_CHANGEUPPER:
  2938. if (info->linking)
  2939. err = mlxsw_sp_port_vrf_join(mlxsw_sp, l3_dev);
  2940. else
  2941. mlxsw_sp_port_vrf_leave(mlxsw_sp, l3_dev);
  2942. break;
  2943. }
  2944. return err;
  2945. }
  2946. static void mlxsw_sp_router_fib_dump_flush(struct notifier_block *nb)
  2947. {
  2948. struct mlxsw_sp *mlxsw_sp = container_of(nb, struct mlxsw_sp, fib_nb);
  2949. /* Flush pending FIB notifications and then flush the device's
  2950. * table before requesting another dump. The FIB notification
  2951. * block is unregistered, so no need to take RTNL.
  2952. */
  2953. mlxsw_core_flush_owq();
  2954. mlxsw_sp_router_fib_flush(mlxsw_sp);
  2955. }
  2956. static int __mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp)
  2957. {
  2958. char rgcr_pl[MLXSW_REG_RGCR_LEN];
  2959. u64 max_rifs;
  2960. int err;
  2961. if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_RIFS))
  2962. return -EIO;
  2963. max_rifs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS);
  2964. mlxsw_sp->rifs = kcalloc(max_rifs, sizeof(struct mlxsw_sp_rif *),
  2965. GFP_KERNEL);
  2966. if (!mlxsw_sp->rifs)
  2967. return -ENOMEM;
  2968. mlxsw_reg_rgcr_pack(rgcr_pl, true);
  2969. mlxsw_reg_rgcr_max_router_interfaces_set(rgcr_pl, max_rifs);
  2970. err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rgcr), rgcr_pl);
  2971. if (err)
  2972. goto err_rgcr_fail;
  2973. return 0;
  2974. err_rgcr_fail:
  2975. kfree(mlxsw_sp->rifs);
  2976. return err;
  2977. }
  2978. static void __mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp)
  2979. {
  2980. char rgcr_pl[MLXSW_REG_RGCR_LEN];
  2981. int i;
  2982. mlxsw_reg_rgcr_pack(rgcr_pl, false);
  2983. mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rgcr), rgcr_pl);
  2984. for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++)
  2985. WARN_ON_ONCE(mlxsw_sp->rifs[i]);
  2986. kfree(mlxsw_sp->rifs);
  2987. }
  2988. int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp)
  2989. {
  2990. int err;
  2991. INIT_LIST_HEAD(&mlxsw_sp->router.nexthop_neighs_list);
  2992. err = __mlxsw_sp_router_init(mlxsw_sp);
  2993. if (err)
  2994. return err;
  2995. err = rhashtable_init(&mlxsw_sp->router.nexthop_ht,
  2996. &mlxsw_sp_nexthop_ht_params);
  2997. if (err)
  2998. goto err_nexthop_ht_init;
  2999. err = rhashtable_init(&mlxsw_sp->router.nexthop_group_ht,
  3000. &mlxsw_sp_nexthop_group_ht_params);
  3001. if (err)
  3002. goto err_nexthop_group_ht_init;
  3003. err = mlxsw_sp_lpm_init(mlxsw_sp);
  3004. if (err)
  3005. goto err_lpm_init;
  3006. err = mlxsw_sp_vrs_init(mlxsw_sp);
  3007. if (err)
  3008. goto err_vrs_init;
  3009. err = mlxsw_sp_neigh_init(mlxsw_sp);
  3010. if (err)
  3011. goto err_neigh_init;
  3012. mlxsw_sp->fib_nb.notifier_call = mlxsw_sp_router_fib_event;
  3013. err = register_fib_notifier(&mlxsw_sp->fib_nb,
  3014. mlxsw_sp_router_fib_dump_flush);
  3015. if (err)
  3016. goto err_register_fib_notifier;
  3017. return 0;
  3018. err_register_fib_notifier:
  3019. mlxsw_sp_neigh_fini(mlxsw_sp);
  3020. err_neigh_init:
  3021. mlxsw_sp_vrs_fini(mlxsw_sp);
  3022. err_vrs_init:
  3023. mlxsw_sp_lpm_fini(mlxsw_sp);
  3024. err_lpm_init:
  3025. rhashtable_destroy(&mlxsw_sp->router.nexthop_group_ht);
  3026. err_nexthop_group_ht_init:
  3027. rhashtable_destroy(&mlxsw_sp->router.nexthop_ht);
  3028. err_nexthop_ht_init:
  3029. __mlxsw_sp_router_fini(mlxsw_sp);
  3030. return err;
  3031. }
  3032. void mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp)
  3033. {
  3034. unregister_fib_notifier(&mlxsw_sp->fib_nb);
  3035. mlxsw_sp_neigh_fini(mlxsw_sp);
  3036. mlxsw_sp_vrs_fini(mlxsw_sp);
  3037. mlxsw_sp_lpm_fini(mlxsw_sp);
  3038. rhashtable_destroy(&mlxsw_sp->router.nexthop_group_ht);
  3039. rhashtable_destroy(&mlxsw_sp->router.nexthop_ht);
  3040. __mlxsw_sp_router_fini(mlxsw_sp);
  3041. }