fs.c 79 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897
  1. // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
  2. /*
  3. * Copyright (c) 2018, Mellanox Technologies inc. All rights reserved.
  4. */
  5. #include <rdma/ib_user_verbs.h>
  6. #include <rdma/ib_verbs.h>
  7. #include <rdma/uverbs_types.h>
  8. #include <rdma/uverbs_ioctl.h>
  9. #include <rdma/uverbs_std_types.h>
  10. #include <rdma/mlx5_user_ioctl_cmds.h>
  11. #include <rdma/mlx5_user_ioctl_verbs.h>
  12. #include <rdma/ib_hdrs.h>
  13. #include <rdma/ib_umem.h>
  14. #include <linux/mlx5/driver.h>
  15. #include <linux/mlx5/fs.h>
  16. #include <linux/mlx5/fs_helpers.h>
  17. #include <linux/mlx5/eswitch.h>
  18. #include <net/inet_ecn.h>
  19. #include "mlx5_ib.h"
  20. #include "counters.h"
  21. #include "devx.h"
  22. #include "fs.h"
  23. #define UVERBS_MODULE_NAME mlx5_ib
  24. #include <rdma/uverbs_named_ioctl.h>
  25. enum {
  26. MATCH_CRITERIA_ENABLE_OUTER_BIT,
  27. MATCH_CRITERIA_ENABLE_MISC_BIT,
  28. MATCH_CRITERIA_ENABLE_INNER_BIT,
  29. MATCH_CRITERIA_ENABLE_MISC2_BIT
  30. };
  31. #define HEADER_IS_ZERO(match_criteria, headers) \
  32. !(memchr_inv(MLX5_ADDR_OF(fte_match_param, match_criteria, headers), \
  33. 0, MLX5_FLD_SZ_BYTES(fte_match_param, headers))) \
  34. static u8 get_match_criteria_enable(u32 *match_criteria)
  35. {
  36. u8 match_criteria_enable;
  37. match_criteria_enable =
  38. (!HEADER_IS_ZERO(match_criteria, outer_headers)) <<
  39. MATCH_CRITERIA_ENABLE_OUTER_BIT;
  40. match_criteria_enable |=
  41. (!HEADER_IS_ZERO(match_criteria, misc_parameters)) <<
  42. MATCH_CRITERIA_ENABLE_MISC_BIT;
  43. match_criteria_enable |=
  44. (!HEADER_IS_ZERO(match_criteria, inner_headers)) <<
  45. MATCH_CRITERIA_ENABLE_INNER_BIT;
  46. match_criteria_enable |=
  47. (!HEADER_IS_ZERO(match_criteria, misc_parameters_2)) <<
  48. MATCH_CRITERIA_ENABLE_MISC2_BIT;
  49. return match_criteria_enable;
  50. }
  51. static int set_proto(void *outer_c, void *outer_v, u8 mask, u8 val)
  52. {
  53. u8 entry_mask;
  54. u8 entry_val;
  55. int err = 0;
  56. if (!mask)
  57. goto out;
  58. entry_mask = MLX5_GET(fte_match_set_lyr_2_4, outer_c,
  59. ip_protocol);
  60. entry_val = MLX5_GET(fte_match_set_lyr_2_4, outer_v,
  61. ip_protocol);
  62. if (!entry_mask) {
  63. MLX5_SET(fte_match_set_lyr_2_4, outer_c, ip_protocol, mask);
  64. MLX5_SET(fte_match_set_lyr_2_4, outer_v, ip_protocol, val);
  65. goto out;
  66. }
  67. /* Don't override existing ip protocol */
  68. if (mask != entry_mask || val != entry_val)
  69. err = -EINVAL;
  70. out:
  71. return err;
  72. }
  73. static void set_flow_label(void *misc_c, void *misc_v, u32 mask, u32 val,
  74. bool inner)
  75. {
  76. if (inner) {
  77. MLX5_SET(fte_match_set_misc,
  78. misc_c, inner_ipv6_flow_label, mask);
  79. MLX5_SET(fte_match_set_misc,
  80. misc_v, inner_ipv6_flow_label, val);
  81. } else {
  82. MLX5_SET(fte_match_set_misc,
  83. misc_c, outer_ipv6_flow_label, mask);
  84. MLX5_SET(fte_match_set_misc,
  85. misc_v, outer_ipv6_flow_label, val);
  86. }
  87. }
  88. static void set_tos(void *outer_c, void *outer_v, u8 mask, u8 val)
  89. {
  90. MLX5_SET(fte_match_set_lyr_2_4, outer_c, ip_ecn, mask);
  91. MLX5_SET(fte_match_set_lyr_2_4, outer_v, ip_ecn, val);
  92. MLX5_SET(fte_match_set_lyr_2_4, outer_c, ip_dscp, mask >> 2);
  93. MLX5_SET(fte_match_set_lyr_2_4, outer_v, ip_dscp, val >> 2);
  94. }
  95. static int check_mpls_supp_fields(u32 field_support, const __be32 *set_mask)
  96. {
  97. if (MLX5_GET(fte_match_mpls, set_mask, mpls_label) &&
  98. !(field_support & MLX5_FIELD_SUPPORT_MPLS_LABEL))
  99. return -EOPNOTSUPP;
  100. if (MLX5_GET(fte_match_mpls, set_mask, mpls_exp) &&
  101. !(field_support & MLX5_FIELD_SUPPORT_MPLS_EXP))
  102. return -EOPNOTSUPP;
  103. if (MLX5_GET(fte_match_mpls, set_mask, mpls_s_bos) &&
  104. !(field_support & MLX5_FIELD_SUPPORT_MPLS_S_BOS))
  105. return -EOPNOTSUPP;
  106. if (MLX5_GET(fte_match_mpls, set_mask, mpls_ttl) &&
  107. !(field_support & MLX5_FIELD_SUPPORT_MPLS_TTL))
  108. return -EOPNOTSUPP;
  109. return 0;
  110. }
  111. #define LAST_ETH_FIELD vlan_tag
  112. #define LAST_IB_FIELD sl
  113. #define LAST_IPV4_FIELD tos
  114. #define LAST_IPV6_FIELD traffic_class
  115. #define LAST_TCP_UDP_FIELD src_port
  116. #define LAST_TUNNEL_FIELD tunnel_id
  117. #define LAST_FLOW_TAG_FIELD tag_id
  118. #define LAST_DROP_FIELD size
  119. #define LAST_COUNTERS_FIELD counters
  120. /* Field is the last supported field */
  121. #define FIELDS_NOT_SUPPORTED(filter, field) \
  122. memchr_inv((void *)&filter.field + sizeof(filter.field), 0, \
  123. sizeof(filter) - offsetofend(typeof(filter), field))
  124. int parse_flow_flow_action(struct mlx5_ib_flow_action *maction,
  125. bool is_egress,
  126. struct mlx5_flow_act *action)
  127. {
  128. switch (maction->ib_action.type) {
  129. case IB_FLOW_ACTION_UNSPECIFIED:
  130. if (maction->flow_action_raw.sub_type ==
  131. MLX5_IB_FLOW_ACTION_MODIFY_HEADER) {
  132. if (action->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
  133. return -EINVAL;
  134. action->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
  135. action->modify_hdr =
  136. maction->flow_action_raw.modify_hdr;
  137. return 0;
  138. }
  139. if (maction->flow_action_raw.sub_type ==
  140. MLX5_IB_FLOW_ACTION_DECAP) {
  141. if (action->action & MLX5_FLOW_CONTEXT_ACTION_DECAP)
  142. return -EINVAL;
  143. action->action |= MLX5_FLOW_CONTEXT_ACTION_DECAP;
  144. return 0;
  145. }
  146. if (maction->flow_action_raw.sub_type ==
  147. MLX5_IB_FLOW_ACTION_PACKET_REFORMAT) {
  148. if (action->action &
  149. MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT)
  150. return -EINVAL;
  151. action->action |=
  152. MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT;
  153. action->pkt_reformat =
  154. maction->flow_action_raw.pkt_reformat;
  155. return 0;
  156. }
  157. fallthrough;
  158. default:
  159. return -EOPNOTSUPP;
  160. }
  161. }
  162. static int parse_flow_attr(struct mlx5_core_dev *mdev,
  163. struct mlx5_flow_spec *spec,
  164. const union ib_flow_spec *ib_spec,
  165. const struct ib_flow_attr *flow_attr,
  166. struct mlx5_flow_act *action, u32 prev_type)
  167. {
  168. struct mlx5_flow_context *flow_context = &spec->flow_context;
  169. u32 *match_c = spec->match_criteria;
  170. u32 *match_v = spec->match_value;
  171. void *misc_params_c = MLX5_ADDR_OF(fte_match_param, match_c,
  172. misc_parameters);
  173. void *misc_params_v = MLX5_ADDR_OF(fte_match_param, match_v,
  174. misc_parameters);
  175. void *misc_params2_c = MLX5_ADDR_OF(fte_match_param, match_c,
  176. misc_parameters_2);
  177. void *misc_params2_v = MLX5_ADDR_OF(fte_match_param, match_v,
  178. misc_parameters_2);
  179. void *headers_c;
  180. void *headers_v;
  181. int match_ipv;
  182. int ret;
  183. if (ib_spec->type & IB_FLOW_SPEC_INNER) {
  184. headers_c = MLX5_ADDR_OF(fte_match_param, match_c,
  185. inner_headers);
  186. headers_v = MLX5_ADDR_OF(fte_match_param, match_v,
  187. inner_headers);
  188. match_ipv = MLX5_CAP_FLOWTABLE_NIC_RX(mdev,
  189. ft_field_support.inner_ip_version);
  190. } else {
  191. headers_c = MLX5_ADDR_OF(fte_match_param, match_c,
  192. outer_headers);
  193. headers_v = MLX5_ADDR_OF(fte_match_param, match_v,
  194. outer_headers);
  195. match_ipv = MLX5_CAP_FLOWTABLE_NIC_RX(mdev,
  196. ft_field_support.outer_ip_version);
  197. }
  198. switch (ib_spec->type & ~IB_FLOW_SPEC_INNER) {
  199. case IB_FLOW_SPEC_ETH:
  200. if (FIELDS_NOT_SUPPORTED(ib_spec->eth.mask, LAST_ETH_FIELD))
  201. return -EOPNOTSUPP;
  202. ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
  203. dmac_47_16),
  204. ib_spec->eth.mask.dst_mac);
  205. ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
  206. dmac_47_16),
  207. ib_spec->eth.val.dst_mac);
  208. ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
  209. smac_47_16),
  210. ib_spec->eth.mask.src_mac);
  211. ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
  212. smac_47_16),
  213. ib_spec->eth.val.src_mac);
  214. if (ib_spec->eth.mask.vlan_tag) {
  215. MLX5_SET(fte_match_set_lyr_2_4, headers_c,
  216. cvlan_tag, 1);
  217. MLX5_SET(fte_match_set_lyr_2_4, headers_v,
  218. cvlan_tag, 1);
  219. MLX5_SET(fte_match_set_lyr_2_4, headers_c,
  220. first_vid, ntohs(ib_spec->eth.mask.vlan_tag));
  221. MLX5_SET(fte_match_set_lyr_2_4, headers_v,
  222. first_vid, ntohs(ib_spec->eth.val.vlan_tag));
  223. MLX5_SET(fte_match_set_lyr_2_4, headers_c,
  224. first_cfi,
  225. ntohs(ib_spec->eth.mask.vlan_tag) >> 12);
  226. MLX5_SET(fte_match_set_lyr_2_4, headers_v,
  227. first_cfi,
  228. ntohs(ib_spec->eth.val.vlan_tag) >> 12);
  229. MLX5_SET(fte_match_set_lyr_2_4, headers_c,
  230. first_prio,
  231. ntohs(ib_spec->eth.mask.vlan_tag) >> 13);
  232. MLX5_SET(fte_match_set_lyr_2_4, headers_v,
  233. first_prio,
  234. ntohs(ib_spec->eth.val.vlan_tag) >> 13);
  235. }
  236. MLX5_SET(fte_match_set_lyr_2_4, headers_c,
  237. ethertype, ntohs(ib_spec->eth.mask.ether_type));
  238. MLX5_SET(fte_match_set_lyr_2_4, headers_v,
  239. ethertype, ntohs(ib_spec->eth.val.ether_type));
  240. break;
  241. case IB_FLOW_SPEC_IPV4:
  242. if (FIELDS_NOT_SUPPORTED(ib_spec->ipv4.mask, LAST_IPV4_FIELD))
  243. return -EOPNOTSUPP;
  244. if (match_ipv) {
  245. MLX5_SET(fte_match_set_lyr_2_4, headers_c,
  246. ip_version, 0xf);
  247. MLX5_SET(fte_match_set_lyr_2_4, headers_v,
  248. ip_version, MLX5_FS_IPV4_VERSION);
  249. } else {
  250. MLX5_SET(fte_match_set_lyr_2_4, headers_c,
  251. ethertype, 0xffff);
  252. MLX5_SET(fte_match_set_lyr_2_4, headers_v,
  253. ethertype, ETH_P_IP);
  254. }
  255. memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
  256. src_ipv4_src_ipv6.ipv4_layout.ipv4),
  257. &ib_spec->ipv4.mask.src_ip,
  258. sizeof(ib_spec->ipv4.mask.src_ip));
  259. memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
  260. src_ipv4_src_ipv6.ipv4_layout.ipv4),
  261. &ib_spec->ipv4.val.src_ip,
  262. sizeof(ib_spec->ipv4.val.src_ip));
  263. memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
  264. dst_ipv4_dst_ipv6.ipv4_layout.ipv4),
  265. &ib_spec->ipv4.mask.dst_ip,
  266. sizeof(ib_spec->ipv4.mask.dst_ip));
  267. memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
  268. dst_ipv4_dst_ipv6.ipv4_layout.ipv4),
  269. &ib_spec->ipv4.val.dst_ip,
  270. sizeof(ib_spec->ipv4.val.dst_ip));
  271. set_tos(headers_c, headers_v,
  272. ib_spec->ipv4.mask.tos, ib_spec->ipv4.val.tos);
  273. if (set_proto(headers_c, headers_v,
  274. ib_spec->ipv4.mask.proto,
  275. ib_spec->ipv4.val.proto))
  276. return -EINVAL;
  277. break;
  278. case IB_FLOW_SPEC_IPV6:
  279. if (FIELDS_NOT_SUPPORTED(ib_spec->ipv6.mask, LAST_IPV6_FIELD))
  280. return -EOPNOTSUPP;
  281. if (match_ipv) {
  282. MLX5_SET(fte_match_set_lyr_2_4, headers_c,
  283. ip_version, 0xf);
  284. MLX5_SET(fte_match_set_lyr_2_4, headers_v,
  285. ip_version, MLX5_FS_IPV6_VERSION);
  286. } else {
  287. MLX5_SET(fte_match_set_lyr_2_4, headers_c,
  288. ethertype, 0xffff);
  289. MLX5_SET(fte_match_set_lyr_2_4, headers_v,
  290. ethertype, ETH_P_IPV6);
  291. }
  292. memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
  293. src_ipv4_src_ipv6.ipv6_layout.ipv6),
  294. &ib_spec->ipv6.mask.src_ip,
  295. sizeof(ib_spec->ipv6.mask.src_ip));
  296. memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
  297. src_ipv4_src_ipv6.ipv6_layout.ipv6),
  298. &ib_spec->ipv6.val.src_ip,
  299. sizeof(ib_spec->ipv6.val.src_ip));
  300. memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
  301. dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
  302. &ib_spec->ipv6.mask.dst_ip,
  303. sizeof(ib_spec->ipv6.mask.dst_ip));
  304. memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
  305. dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
  306. &ib_spec->ipv6.val.dst_ip,
  307. sizeof(ib_spec->ipv6.val.dst_ip));
  308. set_tos(headers_c, headers_v,
  309. ib_spec->ipv6.mask.traffic_class,
  310. ib_spec->ipv6.val.traffic_class);
  311. if (set_proto(headers_c, headers_v,
  312. ib_spec->ipv6.mask.next_hdr,
  313. ib_spec->ipv6.val.next_hdr))
  314. return -EINVAL;
  315. set_flow_label(misc_params_c, misc_params_v,
  316. ntohl(ib_spec->ipv6.mask.flow_label),
  317. ntohl(ib_spec->ipv6.val.flow_label),
  318. ib_spec->type & IB_FLOW_SPEC_INNER);
  319. break;
  320. case IB_FLOW_SPEC_ESP:
  321. return -EOPNOTSUPP;
  322. case IB_FLOW_SPEC_TCP:
  323. if (FIELDS_NOT_SUPPORTED(ib_spec->tcp_udp.mask,
  324. LAST_TCP_UDP_FIELD))
  325. return -EOPNOTSUPP;
  326. if (set_proto(headers_c, headers_v, 0xff, IPPROTO_TCP))
  327. return -EINVAL;
  328. MLX5_SET(fte_match_set_lyr_2_4, headers_c, tcp_sport,
  329. ntohs(ib_spec->tcp_udp.mask.src_port));
  330. MLX5_SET(fte_match_set_lyr_2_4, headers_v, tcp_sport,
  331. ntohs(ib_spec->tcp_udp.val.src_port));
  332. MLX5_SET(fte_match_set_lyr_2_4, headers_c, tcp_dport,
  333. ntohs(ib_spec->tcp_udp.mask.dst_port));
  334. MLX5_SET(fte_match_set_lyr_2_4, headers_v, tcp_dport,
  335. ntohs(ib_spec->tcp_udp.val.dst_port));
  336. break;
  337. case IB_FLOW_SPEC_UDP:
  338. if (FIELDS_NOT_SUPPORTED(ib_spec->tcp_udp.mask,
  339. LAST_TCP_UDP_FIELD))
  340. return -EOPNOTSUPP;
  341. if (set_proto(headers_c, headers_v, 0xff, IPPROTO_UDP))
  342. return -EINVAL;
  343. MLX5_SET(fte_match_set_lyr_2_4, headers_c, udp_sport,
  344. ntohs(ib_spec->tcp_udp.mask.src_port));
  345. MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_sport,
  346. ntohs(ib_spec->tcp_udp.val.src_port));
  347. MLX5_SET(fte_match_set_lyr_2_4, headers_c, udp_dport,
  348. ntohs(ib_spec->tcp_udp.mask.dst_port));
  349. MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport,
  350. ntohs(ib_spec->tcp_udp.val.dst_port));
  351. break;
  352. case IB_FLOW_SPEC_GRE:
  353. if (ib_spec->gre.mask.c_ks_res0_ver)
  354. return -EOPNOTSUPP;
  355. if (set_proto(headers_c, headers_v, 0xff, IPPROTO_GRE))
  356. return -EINVAL;
  357. MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_protocol,
  358. 0xff);
  359. MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
  360. IPPROTO_GRE);
  361. MLX5_SET(fte_match_set_misc, misc_params_c, gre_protocol,
  362. ntohs(ib_spec->gre.mask.protocol));
  363. MLX5_SET(fte_match_set_misc, misc_params_v, gre_protocol,
  364. ntohs(ib_spec->gre.val.protocol));
  365. memcpy(MLX5_ADDR_OF(fte_match_set_misc, misc_params_c,
  366. gre_key.nvgre.hi),
  367. &ib_spec->gre.mask.key,
  368. sizeof(ib_spec->gre.mask.key));
  369. memcpy(MLX5_ADDR_OF(fte_match_set_misc, misc_params_v,
  370. gre_key.nvgre.hi),
  371. &ib_spec->gre.val.key,
  372. sizeof(ib_spec->gre.val.key));
  373. break;
  374. case IB_FLOW_SPEC_MPLS:
  375. switch (prev_type) {
  376. case IB_FLOW_SPEC_UDP:
  377. if (check_mpls_supp_fields(MLX5_CAP_FLOWTABLE_NIC_RX(mdev,
  378. ft_field_support.outer_first_mpls_over_udp),
  379. &ib_spec->mpls.mask.tag))
  380. return -EOPNOTSUPP;
  381. memcpy(MLX5_ADDR_OF(fte_match_set_misc2, misc_params2_v,
  382. outer_first_mpls_over_udp),
  383. &ib_spec->mpls.val.tag,
  384. sizeof(ib_spec->mpls.val.tag));
  385. memcpy(MLX5_ADDR_OF(fte_match_set_misc2, misc_params2_c,
  386. outer_first_mpls_over_udp),
  387. &ib_spec->mpls.mask.tag,
  388. sizeof(ib_spec->mpls.mask.tag));
  389. break;
  390. case IB_FLOW_SPEC_GRE:
  391. if (check_mpls_supp_fields(MLX5_CAP_FLOWTABLE_NIC_RX(mdev,
  392. ft_field_support.outer_first_mpls_over_gre),
  393. &ib_spec->mpls.mask.tag))
  394. return -EOPNOTSUPP;
  395. memcpy(MLX5_ADDR_OF(fte_match_set_misc2, misc_params2_v,
  396. outer_first_mpls_over_gre),
  397. &ib_spec->mpls.val.tag,
  398. sizeof(ib_spec->mpls.val.tag));
  399. memcpy(MLX5_ADDR_OF(fte_match_set_misc2, misc_params2_c,
  400. outer_first_mpls_over_gre),
  401. &ib_spec->mpls.mask.tag,
  402. sizeof(ib_spec->mpls.mask.tag));
  403. break;
  404. default:
  405. if (ib_spec->type & IB_FLOW_SPEC_INNER) {
  406. if (check_mpls_supp_fields(MLX5_CAP_FLOWTABLE_NIC_RX(mdev,
  407. ft_field_support.inner_first_mpls),
  408. &ib_spec->mpls.mask.tag))
  409. return -EOPNOTSUPP;
  410. memcpy(MLX5_ADDR_OF(fte_match_set_misc2, misc_params2_v,
  411. inner_first_mpls),
  412. &ib_spec->mpls.val.tag,
  413. sizeof(ib_spec->mpls.val.tag));
  414. memcpy(MLX5_ADDR_OF(fte_match_set_misc2, misc_params2_c,
  415. inner_first_mpls),
  416. &ib_spec->mpls.mask.tag,
  417. sizeof(ib_spec->mpls.mask.tag));
  418. } else {
  419. if (check_mpls_supp_fields(MLX5_CAP_FLOWTABLE_NIC_RX(mdev,
  420. ft_field_support.outer_first_mpls),
  421. &ib_spec->mpls.mask.tag))
  422. return -EOPNOTSUPP;
  423. memcpy(MLX5_ADDR_OF(fte_match_set_misc2, misc_params2_v,
  424. outer_first_mpls),
  425. &ib_spec->mpls.val.tag,
  426. sizeof(ib_spec->mpls.val.tag));
  427. memcpy(MLX5_ADDR_OF(fte_match_set_misc2, misc_params2_c,
  428. outer_first_mpls),
  429. &ib_spec->mpls.mask.tag,
  430. sizeof(ib_spec->mpls.mask.tag));
  431. }
  432. }
  433. break;
  434. case IB_FLOW_SPEC_VXLAN_TUNNEL:
  435. if (FIELDS_NOT_SUPPORTED(ib_spec->tunnel.mask,
  436. LAST_TUNNEL_FIELD))
  437. return -EOPNOTSUPP;
  438. MLX5_SET(fte_match_set_misc, misc_params_c, vxlan_vni,
  439. ntohl(ib_spec->tunnel.mask.tunnel_id));
  440. MLX5_SET(fte_match_set_misc, misc_params_v, vxlan_vni,
  441. ntohl(ib_spec->tunnel.val.tunnel_id));
  442. break;
  443. case IB_FLOW_SPEC_ACTION_TAG:
  444. if (FIELDS_NOT_SUPPORTED(ib_spec->flow_tag,
  445. LAST_FLOW_TAG_FIELD))
  446. return -EOPNOTSUPP;
  447. if (ib_spec->flow_tag.tag_id >= BIT(24))
  448. return -EINVAL;
  449. flow_context->flow_tag = ib_spec->flow_tag.tag_id;
  450. flow_context->flags |= FLOW_CONTEXT_HAS_TAG;
  451. break;
  452. case IB_FLOW_SPEC_ACTION_DROP:
  453. if (FIELDS_NOT_SUPPORTED(ib_spec->drop,
  454. LAST_DROP_FIELD))
  455. return -EOPNOTSUPP;
  456. action->action |= MLX5_FLOW_CONTEXT_ACTION_DROP;
  457. break;
  458. case IB_FLOW_SPEC_ACTION_HANDLE:
  459. ret = parse_flow_flow_action(to_mflow_act(ib_spec->action.act),
  460. flow_attr->flags & IB_FLOW_ATTR_FLAGS_EGRESS, action);
  461. if (ret)
  462. return ret;
  463. break;
  464. case IB_FLOW_SPEC_ACTION_COUNT:
  465. if (FIELDS_NOT_SUPPORTED(ib_spec->flow_count,
  466. LAST_COUNTERS_FIELD))
  467. return -EOPNOTSUPP;
  468. /* for now support only one counters spec per flow */
  469. if (action->action & MLX5_FLOW_CONTEXT_ACTION_COUNT)
  470. return -EINVAL;
  471. action->counters = ib_spec->flow_count.counters;
  472. action->action |= MLX5_FLOW_CONTEXT_ACTION_COUNT;
  473. break;
  474. default:
  475. return -EINVAL;
  476. }
  477. return 0;
  478. }
  479. /* If a flow could catch both multicast and unicast packets,
  480. * it won't fall into the multicast flow steering table and this rule
  481. * could steal other multicast packets.
  482. */
  483. static bool flow_is_multicast_only(const struct ib_flow_attr *ib_attr)
  484. {
  485. union ib_flow_spec *flow_spec;
  486. if (ib_attr->type != IB_FLOW_ATTR_NORMAL ||
  487. ib_attr->num_of_specs < 1)
  488. return false;
  489. flow_spec = (union ib_flow_spec *)(ib_attr + 1);
  490. if (flow_spec->type == IB_FLOW_SPEC_IPV4) {
  491. struct ib_flow_spec_ipv4 *ipv4_spec;
  492. ipv4_spec = (struct ib_flow_spec_ipv4 *)flow_spec;
  493. if (ipv4_is_multicast(ipv4_spec->val.dst_ip))
  494. return true;
  495. return false;
  496. }
  497. if (flow_spec->type == IB_FLOW_SPEC_ETH) {
  498. struct ib_flow_spec_eth *eth_spec;
  499. eth_spec = (struct ib_flow_spec_eth *)flow_spec;
  500. return is_multicast_ether_addr(eth_spec->mask.dst_mac) &&
  501. is_multicast_ether_addr(eth_spec->val.dst_mac);
  502. }
  503. return false;
  504. }
  505. static bool is_valid_ethertype(struct mlx5_core_dev *mdev,
  506. const struct ib_flow_attr *flow_attr,
  507. bool check_inner)
  508. {
  509. union ib_flow_spec *ib_spec = (union ib_flow_spec *)(flow_attr + 1);
  510. int match_ipv = check_inner ?
  511. MLX5_CAP_FLOWTABLE_NIC_RX(mdev,
  512. ft_field_support.inner_ip_version) :
  513. MLX5_CAP_FLOWTABLE_NIC_RX(mdev,
  514. ft_field_support.outer_ip_version);
  515. int inner_bit = check_inner ? IB_FLOW_SPEC_INNER : 0;
  516. bool ipv4_spec_valid, ipv6_spec_valid;
  517. unsigned int ip_spec_type = 0;
  518. bool has_ethertype = false;
  519. unsigned int spec_index;
  520. bool mask_valid = true;
  521. u16 eth_type = 0;
  522. bool type_valid;
  523. /* Validate that ethertype is correct */
  524. for (spec_index = 0; spec_index < flow_attr->num_of_specs; spec_index++) {
  525. if ((ib_spec->type == (IB_FLOW_SPEC_ETH | inner_bit)) &&
  526. ib_spec->eth.mask.ether_type) {
  527. mask_valid = (ib_spec->eth.mask.ether_type ==
  528. htons(0xffff));
  529. has_ethertype = true;
  530. eth_type = ntohs(ib_spec->eth.val.ether_type);
  531. } else if ((ib_spec->type == (IB_FLOW_SPEC_IPV4 | inner_bit)) ||
  532. (ib_spec->type == (IB_FLOW_SPEC_IPV6 | inner_bit))) {
  533. ip_spec_type = ib_spec->type;
  534. }
  535. ib_spec = (void *)ib_spec + ib_spec->size;
  536. }
  537. type_valid = (!has_ethertype) || (!ip_spec_type);
  538. if (!type_valid && mask_valid) {
  539. ipv4_spec_valid = (eth_type == ETH_P_IP) &&
  540. (ip_spec_type == (IB_FLOW_SPEC_IPV4 | inner_bit));
  541. ipv6_spec_valid = (eth_type == ETH_P_IPV6) &&
  542. (ip_spec_type == (IB_FLOW_SPEC_IPV6 | inner_bit));
  543. type_valid = (ipv4_spec_valid) || (ipv6_spec_valid) ||
  544. (((eth_type == ETH_P_MPLS_UC) ||
  545. (eth_type == ETH_P_MPLS_MC)) && match_ipv);
  546. }
  547. return type_valid;
  548. }
  549. static bool is_valid_attr(struct mlx5_core_dev *mdev,
  550. const struct ib_flow_attr *flow_attr)
  551. {
  552. return is_valid_ethertype(mdev, flow_attr, false) &&
  553. is_valid_ethertype(mdev, flow_attr, true);
  554. }
  555. static void put_flow_table(struct mlx5_ib_dev *dev,
  556. struct mlx5_ib_flow_prio *prio, bool ft_added)
  557. {
  558. prio->refcount -= !!ft_added;
  559. if (!prio->refcount) {
  560. mlx5_destroy_flow_table(prio->flow_table);
  561. prio->flow_table = NULL;
  562. }
  563. }
  564. static int mlx5_ib_destroy_flow(struct ib_flow *flow_id)
  565. {
  566. struct mlx5_ib_flow_handler *handler = container_of(flow_id,
  567. struct mlx5_ib_flow_handler,
  568. ibflow);
  569. struct mlx5_ib_flow_handler *iter, *tmp;
  570. struct mlx5_ib_dev *dev = handler->dev;
  571. mutex_lock(&dev->flow_db->lock);
  572. list_for_each_entry_safe(iter, tmp, &handler->list, list) {
  573. mlx5_del_flow_rules(iter->rule);
  574. put_flow_table(dev, iter->prio, true);
  575. list_del(&iter->list);
  576. kfree(iter);
  577. }
  578. mlx5_del_flow_rules(handler->rule);
  579. put_flow_table(dev, handler->prio, true);
  580. mlx5_ib_counters_clear_description(handler->ibcounters);
  581. mutex_unlock(&dev->flow_db->lock);
  582. if (handler->flow_matcher)
  583. atomic_dec(&handler->flow_matcher->usecnt);
  584. kfree(handler);
  585. return 0;
  586. }
  587. static int ib_prio_to_core_prio(unsigned int priority, bool dont_trap)
  588. {
  589. priority *= 2;
  590. if (!dont_trap)
  591. priority++;
  592. return priority;
  593. }
  594. enum flow_table_type {
  595. MLX5_IB_FT_RX,
  596. MLX5_IB_FT_TX
  597. };
  598. #define MLX5_FS_MAX_TYPES 6
  599. #define MLX5_FS_MAX_ENTRIES BIT(16)
  600. static bool mlx5_ib_shared_ft_allowed(struct ib_device *device)
  601. {
  602. struct mlx5_ib_dev *dev = to_mdev(device);
  603. return MLX5_CAP_GEN(dev->mdev, shared_object_to_user_object_allowed);
  604. }
  605. static struct mlx5_ib_flow_prio *_get_prio(struct mlx5_ib_dev *dev,
  606. struct mlx5_flow_namespace *ns,
  607. struct mlx5_ib_flow_prio *prio,
  608. int priority,
  609. int num_entries, int num_groups,
  610. u32 flags)
  611. {
  612. struct mlx5_flow_table_attr ft_attr = {};
  613. struct mlx5_flow_table *ft;
  614. ft_attr.prio = priority;
  615. ft_attr.max_fte = num_entries;
  616. ft_attr.flags = flags;
  617. ft_attr.autogroup.max_num_groups = num_groups;
  618. ft = mlx5_create_auto_grouped_flow_table(ns, &ft_attr);
  619. if (IS_ERR(ft))
  620. return ERR_CAST(ft);
  621. prio->flow_table = ft;
  622. prio->refcount = 0;
  623. return prio;
  624. }
  625. static struct mlx5_ib_flow_prio *get_flow_table(struct mlx5_ib_dev *dev,
  626. struct ib_flow_attr *flow_attr,
  627. enum flow_table_type ft_type)
  628. {
  629. bool dont_trap = flow_attr->flags & IB_FLOW_ATTR_FLAGS_DONT_TRAP;
  630. struct mlx5_flow_namespace *ns = NULL;
  631. enum mlx5_flow_namespace_type fn_type;
  632. struct mlx5_ib_flow_prio *prio;
  633. struct mlx5_flow_table *ft;
  634. int max_table_size;
  635. int num_entries;
  636. int num_groups;
  637. bool esw_encap;
  638. u32 flags = 0;
  639. int priority;
  640. max_table_size = BIT(MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev,
  641. log_max_ft_size));
  642. esw_encap = mlx5_eswitch_get_encap_mode(dev->mdev) !=
  643. DEVLINK_ESWITCH_ENCAP_MODE_NONE;
  644. switch (flow_attr->type) {
  645. case IB_FLOW_ATTR_NORMAL:
  646. if (flow_is_multicast_only(flow_attr) && !dont_trap)
  647. priority = MLX5_IB_FLOW_MCAST_PRIO;
  648. else
  649. priority = ib_prio_to_core_prio(flow_attr->priority,
  650. dont_trap);
  651. if (ft_type == MLX5_IB_FT_RX) {
  652. fn_type = MLX5_FLOW_NAMESPACE_BYPASS;
  653. prio = &dev->flow_db->prios[priority];
  654. if (!dev->is_rep && !esw_encap &&
  655. MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev, decap))
  656. flags |= MLX5_FLOW_TABLE_TUNNEL_EN_DECAP;
  657. if (!dev->is_rep && !esw_encap &&
  658. MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev,
  659. reformat_l3_tunnel_to_l2))
  660. flags |= MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT;
  661. } else {
  662. max_table_size = BIT(MLX5_CAP_FLOWTABLE_NIC_TX(
  663. dev->mdev, log_max_ft_size));
  664. fn_type = MLX5_FLOW_NAMESPACE_EGRESS;
  665. prio = &dev->flow_db->egress_prios[priority];
  666. if (!dev->is_rep && !esw_encap &&
  667. MLX5_CAP_FLOWTABLE_NIC_TX(dev->mdev, reformat))
  668. flags |= MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT;
  669. }
  670. ns = mlx5_get_flow_namespace(dev->mdev, fn_type);
  671. num_entries = MLX5_FS_MAX_ENTRIES;
  672. num_groups = MLX5_FS_MAX_TYPES;
  673. break;
  674. case IB_FLOW_ATTR_ALL_DEFAULT:
  675. case IB_FLOW_ATTR_MC_DEFAULT:
  676. ns = mlx5_get_flow_namespace(dev->mdev,
  677. MLX5_FLOW_NAMESPACE_LEFTOVERS);
  678. build_leftovers_ft_param(&priority, &num_entries, &num_groups);
  679. prio = &dev->flow_db->prios[MLX5_IB_FLOW_LEFTOVERS_PRIO];
  680. break;
  681. case IB_FLOW_ATTR_SNIFFER:
  682. if (!MLX5_CAP_FLOWTABLE(dev->mdev,
  683. allow_sniffer_and_nic_rx_shared_tir))
  684. return ERR_PTR(-EOPNOTSUPP);
  685. ns = mlx5_get_flow_namespace(
  686. dev->mdev, ft_type == MLX5_IB_FT_RX ?
  687. MLX5_FLOW_NAMESPACE_SNIFFER_RX :
  688. MLX5_FLOW_NAMESPACE_SNIFFER_TX);
  689. prio = &dev->flow_db->sniffer[ft_type];
  690. priority = 0;
  691. num_entries = 1;
  692. num_groups = 1;
  693. break;
  694. default:
  695. break;
  696. }
  697. if (!ns)
  698. return ERR_PTR(-EOPNOTSUPP);
  699. max_table_size = min_t(int, num_entries, max_table_size);
  700. ft = prio->flow_table;
  701. if (!ft)
  702. return _get_prio(dev, ns, prio, priority, max_table_size,
  703. num_groups, flags);
  704. return prio;
  705. }
  706. enum {
  707. RDMA_RX_ECN_OPCOUNTER_PRIO,
  708. RDMA_RX_CNP_OPCOUNTER_PRIO,
  709. };
  710. enum {
  711. RDMA_TX_CNP_OPCOUNTER_PRIO,
  712. };
  713. static int set_vhca_port_spec(struct mlx5_ib_dev *dev, u32 port_num,
  714. struct mlx5_flow_spec *spec)
  715. {
  716. if (!MLX5_CAP_FLOWTABLE_RDMA_RX(dev->mdev,
  717. ft_field_support.source_vhca_port) ||
  718. !MLX5_CAP_FLOWTABLE_RDMA_TX(dev->mdev,
  719. ft_field_support.source_vhca_port))
  720. return -EOPNOTSUPP;
  721. MLX5_SET_TO_ONES(fte_match_param, &spec->match_criteria,
  722. misc_parameters.source_vhca_port);
  723. MLX5_SET(fte_match_param, &spec->match_value,
  724. misc_parameters.source_vhca_port, port_num);
  725. return 0;
  726. }
  727. static int set_ecn_ce_spec(struct mlx5_ib_dev *dev, u32 port_num,
  728. struct mlx5_flow_spec *spec, int ipv)
  729. {
  730. if (!MLX5_CAP_FLOWTABLE_RDMA_RX(dev->mdev,
  731. ft_field_support.outer_ip_version))
  732. return -EOPNOTSUPP;
  733. if (mlx5_core_mp_enabled(dev->mdev) &&
  734. set_vhca_port_spec(dev, port_num, spec))
  735. return -EOPNOTSUPP;
  736. MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
  737. outer_headers.ip_ecn);
  738. MLX5_SET(fte_match_param, spec->match_value, outer_headers.ip_ecn,
  739. INET_ECN_CE);
  740. MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
  741. outer_headers.ip_version);
  742. MLX5_SET(fte_match_param, spec->match_value, outer_headers.ip_version,
  743. ipv);
  744. spec->match_criteria_enable =
  745. get_match_criteria_enable(spec->match_criteria);
  746. return 0;
  747. }
  748. static int set_cnp_spec(struct mlx5_ib_dev *dev, u32 port_num,
  749. struct mlx5_flow_spec *spec)
  750. {
  751. if (mlx5_core_mp_enabled(dev->mdev) &&
  752. set_vhca_port_spec(dev, port_num, spec))
  753. return -EOPNOTSUPP;
  754. MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
  755. misc_parameters.bth_opcode);
  756. MLX5_SET(fte_match_param, spec->match_value, misc_parameters.bth_opcode,
  757. IB_BTH_OPCODE_CNP);
  758. spec->match_criteria_enable =
  759. get_match_criteria_enable(spec->match_criteria);
  760. return 0;
  761. }
  762. int mlx5_ib_fs_add_op_fc(struct mlx5_ib_dev *dev, u32 port_num,
  763. struct mlx5_ib_op_fc *opfc,
  764. enum mlx5_ib_optional_counter_type type)
  765. {
  766. enum mlx5_flow_namespace_type fn_type;
  767. int priority, i, err, spec_num;
  768. struct mlx5_flow_act flow_act = {};
  769. struct mlx5_flow_destination dst;
  770. struct mlx5_flow_namespace *ns;
  771. struct mlx5_ib_flow_prio *prio;
  772. struct mlx5_flow_spec *spec;
  773. spec = kcalloc(MAX_OPFC_RULES, sizeof(*spec), GFP_KERNEL);
  774. if (!spec)
  775. return -ENOMEM;
  776. switch (type) {
  777. case MLX5_IB_OPCOUNTER_CC_RX_CE_PKTS:
  778. if (set_ecn_ce_spec(dev, port_num, &spec[0],
  779. MLX5_FS_IPV4_VERSION) ||
  780. set_ecn_ce_spec(dev, port_num, &spec[1],
  781. MLX5_FS_IPV6_VERSION)) {
  782. err = -EOPNOTSUPP;
  783. goto free;
  784. }
  785. spec_num = 2;
  786. fn_type = MLX5_FLOW_NAMESPACE_RDMA_RX_COUNTERS;
  787. priority = RDMA_RX_ECN_OPCOUNTER_PRIO;
  788. break;
  789. case MLX5_IB_OPCOUNTER_CC_RX_CNP_PKTS:
  790. if (!MLX5_CAP_FLOWTABLE(dev->mdev,
  791. ft_field_support_2_nic_receive_rdma.bth_opcode) ||
  792. set_cnp_spec(dev, port_num, &spec[0])) {
  793. err = -EOPNOTSUPP;
  794. goto free;
  795. }
  796. spec_num = 1;
  797. fn_type = MLX5_FLOW_NAMESPACE_RDMA_RX_COUNTERS;
  798. priority = RDMA_RX_CNP_OPCOUNTER_PRIO;
  799. break;
  800. case MLX5_IB_OPCOUNTER_CC_TX_CNP_PKTS:
  801. if (!MLX5_CAP_FLOWTABLE(dev->mdev,
  802. ft_field_support_2_nic_transmit_rdma.bth_opcode) ||
  803. set_cnp_spec(dev, port_num, &spec[0])) {
  804. err = -EOPNOTSUPP;
  805. goto free;
  806. }
  807. spec_num = 1;
  808. fn_type = MLX5_FLOW_NAMESPACE_RDMA_TX_COUNTERS;
  809. priority = RDMA_TX_CNP_OPCOUNTER_PRIO;
  810. break;
  811. default:
  812. err = -EOPNOTSUPP;
  813. goto free;
  814. }
  815. ns = mlx5_get_flow_namespace(dev->mdev, fn_type);
  816. if (!ns) {
  817. err = -EOPNOTSUPP;
  818. goto free;
  819. }
  820. prio = &dev->flow_db->opfcs[type];
  821. if (!prio->flow_table) {
  822. prio = _get_prio(dev, ns, prio, priority,
  823. dev->num_ports * MAX_OPFC_RULES, 1, 0);
  824. if (IS_ERR(prio)) {
  825. err = PTR_ERR(prio);
  826. goto free;
  827. }
  828. }
  829. dst.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
  830. dst.counter_id = mlx5_fc_id(opfc->fc);
  831. flow_act.action =
  832. MLX5_FLOW_CONTEXT_ACTION_COUNT | MLX5_FLOW_CONTEXT_ACTION_ALLOW;
  833. for (i = 0; i < spec_num; i++) {
  834. opfc->rule[i] = mlx5_add_flow_rules(prio->flow_table, &spec[i],
  835. &flow_act, &dst, 1);
  836. if (IS_ERR(opfc->rule[i])) {
  837. err = PTR_ERR(opfc->rule[i]);
  838. goto del_rules;
  839. }
  840. }
  841. prio->refcount += spec_num;
  842. kfree(spec);
  843. return 0;
  844. del_rules:
  845. for (i -= 1; i >= 0; i--)
  846. mlx5_del_flow_rules(opfc->rule[i]);
  847. put_flow_table(dev, prio, false);
  848. free:
  849. kfree(spec);
  850. return err;
  851. }
  852. void mlx5_ib_fs_remove_op_fc(struct mlx5_ib_dev *dev,
  853. struct mlx5_ib_op_fc *opfc,
  854. enum mlx5_ib_optional_counter_type type)
  855. {
  856. int i;
  857. for (i = 0; i < MAX_OPFC_RULES && opfc->rule[i]; i++) {
  858. mlx5_del_flow_rules(opfc->rule[i]);
  859. put_flow_table(dev, &dev->flow_db->opfcs[type], true);
  860. }
  861. }
  862. static void set_underlay_qp(struct mlx5_ib_dev *dev,
  863. struct mlx5_flow_spec *spec,
  864. u32 underlay_qpn)
  865. {
  866. void *misc_params_c = MLX5_ADDR_OF(fte_match_param,
  867. spec->match_criteria,
  868. misc_parameters);
  869. void *misc_params_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
  870. misc_parameters);
  871. if (underlay_qpn &&
  872. MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev,
  873. ft_field_support.bth_dst_qp)) {
  874. MLX5_SET(fte_match_set_misc,
  875. misc_params_v, bth_dst_qp, underlay_qpn);
  876. MLX5_SET(fte_match_set_misc,
  877. misc_params_c, bth_dst_qp, 0xffffff);
  878. }
  879. }
  880. static void mlx5_ib_set_rule_source_port(struct mlx5_ib_dev *dev,
  881. struct mlx5_flow_spec *spec,
  882. struct mlx5_eswitch_rep *rep)
  883. {
  884. struct mlx5_eswitch *esw = dev->mdev->priv.eswitch;
  885. void *misc;
  886. if (mlx5_eswitch_vport_match_metadata_enabled(esw)) {
  887. misc = MLX5_ADDR_OF(fte_match_param, spec->match_value,
  888. misc_parameters_2);
  889. MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0,
  890. mlx5_eswitch_get_vport_metadata_for_match(rep->esw,
  891. rep->vport));
  892. misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
  893. misc_parameters_2);
  894. MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0,
  895. mlx5_eswitch_get_vport_metadata_mask());
  896. } else {
  897. misc = MLX5_ADDR_OF(fte_match_param, spec->match_value,
  898. misc_parameters);
  899. MLX5_SET(fte_match_set_misc, misc, source_port, rep->vport);
  900. misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
  901. misc_parameters);
  902. MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port);
  903. }
  904. }
  905. static struct mlx5_ib_flow_handler *_create_flow_rule(struct mlx5_ib_dev *dev,
  906. struct mlx5_ib_flow_prio *ft_prio,
  907. const struct ib_flow_attr *flow_attr,
  908. struct mlx5_flow_destination *dst,
  909. u32 underlay_qpn,
  910. struct mlx5_ib_create_flow *ucmd)
  911. {
  912. struct mlx5_flow_table *ft = ft_prio->flow_table;
  913. struct mlx5_ib_flow_handler *handler;
  914. struct mlx5_flow_act flow_act = {};
  915. struct mlx5_flow_spec *spec;
  916. struct mlx5_flow_destination dest_arr[2] = {};
  917. struct mlx5_flow_destination *rule_dst = dest_arr;
  918. const void *ib_flow = (const void *)flow_attr + sizeof(*flow_attr);
  919. unsigned int spec_index;
  920. u32 prev_type = 0;
  921. int err = 0;
  922. int dest_num = 0;
  923. bool is_egress = flow_attr->flags & IB_FLOW_ATTR_FLAGS_EGRESS;
  924. if (!is_valid_attr(dev->mdev, flow_attr))
  925. return ERR_PTR(-EINVAL);
  926. if (dev->is_rep && is_egress)
  927. return ERR_PTR(-EINVAL);
  928. spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
  929. handler = kzalloc(sizeof(*handler), GFP_KERNEL);
  930. if (!handler || !spec) {
  931. err = -ENOMEM;
  932. goto free;
  933. }
  934. INIT_LIST_HEAD(&handler->list);
  935. for (spec_index = 0; spec_index < flow_attr->num_of_specs; spec_index++) {
  936. err = parse_flow_attr(dev->mdev, spec,
  937. ib_flow, flow_attr, &flow_act,
  938. prev_type);
  939. if (err < 0)
  940. goto free;
  941. prev_type = ((union ib_flow_spec *)ib_flow)->type;
  942. ib_flow += ((union ib_flow_spec *)ib_flow)->size;
  943. }
  944. if (dst && !(flow_act.action & MLX5_FLOW_CONTEXT_ACTION_DROP)) {
  945. memcpy(&dest_arr[0], dst, sizeof(*dst));
  946. dest_num++;
  947. }
  948. if (!flow_is_multicast_only(flow_attr))
  949. set_underlay_qp(dev, spec, underlay_qpn);
  950. if (dev->is_rep && flow_attr->type != IB_FLOW_ATTR_SNIFFER) {
  951. struct mlx5_eswitch_rep *rep;
  952. rep = dev->port[flow_attr->port - 1].rep;
  953. if (!rep) {
  954. err = -EINVAL;
  955. goto free;
  956. }
  957. mlx5_ib_set_rule_source_port(dev, spec, rep);
  958. }
  959. spec->match_criteria_enable = get_match_criteria_enable(spec->match_criteria);
  960. if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
  961. struct mlx5_ib_mcounters *mcounters;
  962. err = mlx5_ib_flow_counters_set_data(flow_act.counters, ucmd);
  963. if (err)
  964. goto free;
  965. mcounters = to_mcounters(flow_act.counters);
  966. handler->ibcounters = flow_act.counters;
  967. dest_arr[dest_num].type =
  968. MLX5_FLOW_DESTINATION_TYPE_COUNTER;
  969. dest_arr[dest_num].counter_id =
  970. mlx5_fc_id(mcounters->hw_cntrs_hndl);
  971. dest_num++;
  972. }
  973. if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_DROP) {
  974. if (!dest_num)
  975. rule_dst = NULL;
  976. } else {
  977. if (flow_attr->flags & IB_FLOW_ATTR_FLAGS_DONT_TRAP)
  978. flow_act.action |=
  979. MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO;
  980. if (is_egress)
  981. flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_ALLOW;
  982. else if (dest_num)
  983. flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
  984. }
  985. if ((spec->flow_context.flags & FLOW_CONTEXT_HAS_TAG) &&
  986. (flow_attr->type == IB_FLOW_ATTR_ALL_DEFAULT ||
  987. flow_attr->type == IB_FLOW_ATTR_MC_DEFAULT)) {
  988. mlx5_ib_warn(dev, "Flow tag %u and attribute type %x isn't allowed in leftovers\n",
  989. spec->flow_context.flow_tag, flow_attr->type);
  990. err = -EINVAL;
  991. goto free;
  992. }
  993. handler->rule = mlx5_add_flow_rules(ft, spec,
  994. &flow_act,
  995. rule_dst, dest_num);
  996. if (IS_ERR(handler->rule)) {
  997. err = PTR_ERR(handler->rule);
  998. goto free;
  999. }
  1000. ft_prio->refcount++;
  1001. handler->prio = ft_prio;
  1002. handler->dev = dev;
  1003. ft_prio->flow_table = ft;
  1004. free:
  1005. if (err && handler) {
  1006. mlx5_ib_counters_clear_description(handler->ibcounters);
  1007. kfree(handler);
  1008. }
  1009. kvfree(spec);
  1010. return err ? ERR_PTR(err) : handler;
  1011. }
  1012. static struct mlx5_ib_flow_handler *create_flow_rule(struct mlx5_ib_dev *dev,
  1013. struct mlx5_ib_flow_prio *ft_prio,
  1014. const struct ib_flow_attr *flow_attr,
  1015. struct mlx5_flow_destination *dst)
  1016. {
  1017. return _create_flow_rule(dev, ft_prio, flow_attr, dst, 0, NULL);
  1018. }
  1019. enum {
  1020. LEFTOVERS_MC,
  1021. LEFTOVERS_UC,
  1022. };
  1023. static struct mlx5_ib_flow_handler *create_leftovers_rule(struct mlx5_ib_dev *dev,
  1024. struct mlx5_ib_flow_prio *ft_prio,
  1025. struct ib_flow_attr *flow_attr,
  1026. struct mlx5_flow_destination *dst)
  1027. {
  1028. struct mlx5_ib_flow_handler *handler_ucast = NULL;
  1029. struct mlx5_ib_flow_handler *handler = NULL;
  1030. static struct {
  1031. struct ib_flow_attr flow_attr;
  1032. struct ib_flow_spec_eth eth_flow;
  1033. } leftovers_specs[] = {
  1034. [LEFTOVERS_MC] = {
  1035. .flow_attr = {
  1036. .num_of_specs = 1,
  1037. .size = sizeof(leftovers_specs[0])
  1038. },
  1039. .eth_flow = {
  1040. .type = IB_FLOW_SPEC_ETH,
  1041. .size = sizeof(struct ib_flow_spec_eth),
  1042. .mask = {.dst_mac = {0x1} },
  1043. .val = {.dst_mac = {0x1} }
  1044. }
  1045. },
  1046. [LEFTOVERS_UC] = {
  1047. .flow_attr = {
  1048. .num_of_specs = 1,
  1049. .size = sizeof(leftovers_specs[0])
  1050. },
  1051. .eth_flow = {
  1052. .type = IB_FLOW_SPEC_ETH,
  1053. .size = sizeof(struct ib_flow_spec_eth),
  1054. .mask = {.dst_mac = {0x1} },
  1055. .val = {.dst_mac = {} }
  1056. }
  1057. }
  1058. };
  1059. handler = create_flow_rule(dev, ft_prio,
  1060. &leftovers_specs[LEFTOVERS_MC].flow_attr,
  1061. dst);
  1062. if (!IS_ERR(handler) &&
  1063. flow_attr->type == IB_FLOW_ATTR_ALL_DEFAULT) {
  1064. handler_ucast = create_flow_rule(dev, ft_prio,
  1065. &leftovers_specs[LEFTOVERS_UC].flow_attr,
  1066. dst);
  1067. if (IS_ERR(handler_ucast)) {
  1068. mlx5_del_flow_rules(handler->rule);
  1069. ft_prio->refcount--;
  1070. kfree(handler);
  1071. handler = handler_ucast;
  1072. } else {
  1073. list_add(&handler_ucast->list, &handler->list);
  1074. }
  1075. }
  1076. return handler;
  1077. }
  1078. static struct mlx5_ib_flow_handler *create_sniffer_rule(struct mlx5_ib_dev *dev,
  1079. struct mlx5_ib_flow_prio *ft_rx,
  1080. struct mlx5_ib_flow_prio *ft_tx,
  1081. struct mlx5_flow_destination *dst)
  1082. {
  1083. struct mlx5_ib_flow_handler *handler_rx;
  1084. struct mlx5_ib_flow_handler *handler_tx;
  1085. int err;
  1086. static const struct ib_flow_attr flow_attr = {
  1087. .num_of_specs = 0,
  1088. .type = IB_FLOW_ATTR_SNIFFER,
  1089. .size = sizeof(flow_attr)
  1090. };
  1091. handler_rx = create_flow_rule(dev, ft_rx, &flow_attr, dst);
  1092. if (IS_ERR(handler_rx)) {
  1093. err = PTR_ERR(handler_rx);
  1094. goto err;
  1095. }
  1096. handler_tx = create_flow_rule(dev, ft_tx, &flow_attr, dst);
  1097. if (IS_ERR(handler_tx)) {
  1098. err = PTR_ERR(handler_tx);
  1099. goto err_tx;
  1100. }
  1101. list_add(&handler_tx->list, &handler_rx->list);
  1102. return handler_rx;
  1103. err_tx:
  1104. mlx5_del_flow_rules(handler_rx->rule);
  1105. ft_rx->refcount--;
  1106. kfree(handler_rx);
  1107. err:
  1108. return ERR_PTR(err);
  1109. }
  1110. static struct ib_flow *mlx5_ib_create_flow(struct ib_qp *qp,
  1111. struct ib_flow_attr *flow_attr,
  1112. struct ib_udata *udata)
  1113. {
  1114. struct mlx5_ib_dev *dev = to_mdev(qp->device);
  1115. struct mlx5_ib_qp *mqp = to_mqp(qp);
  1116. struct mlx5_ib_flow_handler *handler = NULL;
  1117. struct mlx5_flow_destination *dst = NULL;
  1118. struct mlx5_ib_flow_prio *ft_prio_tx = NULL;
  1119. struct mlx5_ib_flow_prio *ft_prio;
  1120. bool is_egress = flow_attr->flags & IB_FLOW_ATTR_FLAGS_EGRESS;
  1121. struct mlx5_ib_create_flow *ucmd = NULL, ucmd_hdr;
  1122. size_t min_ucmd_sz, required_ucmd_sz;
  1123. int err;
  1124. int underlay_qpn;
  1125. if (udata && udata->inlen) {
  1126. min_ucmd_sz = offsetofend(struct mlx5_ib_create_flow, reserved);
  1127. if (udata->inlen < min_ucmd_sz)
  1128. return ERR_PTR(-EOPNOTSUPP);
  1129. err = ib_copy_from_udata(&ucmd_hdr, udata, min_ucmd_sz);
  1130. if (err)
  1131. return ERR_PTR(err);
  1132. /* currently supports only one counters data */
  1133. if (ucmd_hdr.ncounters_data > 1)
  1134. return ERR_PTR(-EINVAL);
  1135. required_ucmd_sz = min_ucmd_sz +
  1136. sizeof(struct mlx5_ib_flow_counters_data) *
  1137. ucmd_hdr.ncounters_data;
  1138. if (udata->inlen > required_ucmd_sz &&
  1139. !ib_is_udata_cleared(udata, required_ucmd_sz,
  1140. udata->inlen - required_ucmd_sz))
  1141. return ERR_PTR(-EOPNOTSUPP);
  1142. ucmd = kzalloc(required_ucmd_sz, GFP_KERNEL);
  1143. if (!ucmd)
  1144. return ERR_PTR(-ENOMEM);
  1145. err = ib_copy_from_udata(ucmd, udata, required_ucmd_sz);
  1146. if (err)
  1147. goto free_ucmd;
  1148. }
  1149. if (flow_attr->priority > MLX5_IB_FLOW_LAST_PRIO) {
  1150. err = -ENOMEM;
  1151. goto free_ucmd;
  1152. }
  1153. if (flow_attr->flags &
  1154. ~(IB_FLOW_ATTR_FLAGS_DONT_TRAP | IB_FLOW_ATTR_FLAGS_EGRESS)) {
  1155. err = -EINVAL;
  1156. goto free_ucmd;
  1157. }
  1158. if (is_egress &&
  1159. (flow_attr->type == IB_FLOW_ATTR_ALL_DEFAULT ||
  1160. flow_attr->type == IB_FLOW_ATTR_MC_DEFAULT)) {
  1161. err = -EINVAL;
  1162. goto free_ucmd;
  1163. }
  1164. dst = kzalloc(sizeof(*dst), GFP_KERNEL);
  1165. if (!dst) {
  1166. err = -ENOMEM;
  1167. goto free_ucmd;
  1168. }
  1169. mutex_lock(&dev->flow_db->lock);
  1170. ft_prio = get_flow_table(dev, flow_attr,
  1171. is_egress ? MLX5_IB_FT_TX : MLX5_IB_FT_RX);
  1172. if (IS_ERR(ft_prio)) {
  1173. err = PTR_ERR(ft_prio);
  1174. goto unlock;
  1175. }
  1176. if (flow_attr->type == IB_FLOW_ATTR_SNIFFER) {
  1177. ft_prio_tx = get_flow_table(dev, flow_attr, MLX5_IB_FT_TX);
  1178. if (IS_ERR(ft_prio_tx)) {
  1179. err = PTR_ERR(ft_prio_tx);
  1180. ft_prio_tx = NULL;
  1181. goto destroy_ft;
  1182. }
  1183. }
  1184. if (is_egress) {
  1185. dst->type = MLX5_FLOW_DESTINATION_TYPE_PORT;
  1186. } else {
  1187. dst->type = MLX5_FLOW_DESTINATION_TYPE_TIR;
  1188. if (mqp->is_rss)
  1189. dst->tir_num = mqp->rss_qp.tirn;
  1190. else
  1191. dst->tir_num = mqp->raw_packet_qp.rq.tirn;
  1192. }
  1193. switch (flow_attr->type) {
  1194. case IB_FLOW_ATTR_NORMAL:
  1195. underlay_qpn = (mqp->flags & IB_QP_CREATE_SOURCE_QPN) ?
  1196. mqp->underlay_qpn :
  1197. 0;
  1198. handler = _create_flow_rule(dev, ft_prio, flow_attr, dst,
  1199. underlay_qpn, ucmd);
  1200. break;
  1201. case IB_FLOW_ATTR_ALL_DEFAULT:
  1202. case IB_FLOW_ATTR_MC_DEFAULT:
  1203. handler = create_leftovers_rule(dev, ft_prio, flow_attr, dst);
  1204. break;
  1205. case IB_FLOW_ATTR_SNIFFER:
  1206. handler = create_sniffer_rule(dev, ft_prio, ft_prio_tx, dst);
  1207. break;
  1208. default:
  1209. err = -EINVAL;
  1210. goto destroy_ft;
  1211. }
  1212. if (IS_ERR(handler)) {
  1213. err = PTR_ERR(handler);
  1214. handler = NULL;
  1215. goto destroy_ft;
  1216. }
  1217. mutex_unlock(&dev->flow_db->lock);
  1218. kfree(dst);
  1219. kfree(ucmd);
  1220. return &handler->ibflow;
  1221. destroy_ft:
  1222. put_flow_table(dev, ft_prio, false);
  1223. if (ft_prio_tx)
  1224. put_flow_table(dev, ft_prio_tx, false);
  1225. unlock:
  1226. mutex_unlock(&dev->flow_db->lock);
  1227. kfree(dst);
  1228. free_ucmd:
  1229. kfree(ucmd);
  1230. return ERR_PTR(err);
  1231. }
  1232. static struct mlx5_ib_flow_prio *
  1233. _get_flow_table(struct mlx5_ib_dev *dev, u16 user_priority,
  1234. enum mlx5_flow_namespace_type ns_type,
  1235. bool mcast)
  1236. {
  1237. struct mlx5_flow_namespace *ns = NULL;
  1238. struct mlx5_ib_flow_prio *prio = NULL;
  1239. int max_table_size = 0;
  1240. bool esw_encap;
  1241. u32 flags = 0;
  1242. int priority;
  1243. if (mcast)
  1244. priority = MLX5_IB_FLOW_MCAST_PRIO;
  1245. else
  1246. priority = ib_prio_to_core_prio(user_priority, false);
  1247. esw_encap = mlx5_eswitch_get_encap_mode(dev->mdev) !=
  1248. DEVLINK_ESWITCH_ENCAP_MODE_NONE;
  1249. switch (ns_type) {
  1250. case MLX5_FLOW_NAMESPACE_BYPASS:
  1251. max_table_size = BIT(
  1252. MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev, log_max_ft_size));
  1253. if (MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev, decap) && !esw_encap)
  1254. flags |= MLX5_FLOW_TABLE_TUNNEL_EN_DECAP;
  1255. if (MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev,
  1256. reformat_l3_tunnel_to_l2) &&
  1257. !esw_encap)
  1258. flags |= MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT;
  1259. break;
  1260. case MLX5_FLOW_NAMESPACE_EGRESS:
  1261. max_table_size = BIT(
  1262. MLX5_CAP_FLOWTABLE_NIC_TX(dev->mdev, log_max_ft_size));
  1263. if (MLX5_CAP_FLOWTABLE_NIC_TX(dev->mdev, reformat) &&
  1264. !esw_encap)
  1265. flags |= MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT;
  1266. break;
  1267. case MLX5_FLOW_NAMESPACE_FDB_BYPASS:
  1268. max_table_size = BIT(
  1269. MLX5_CAP_ESW_FLOWTABLE_FDB(dev->mdev, log_max_ft_size));
  1270. if (MLX5_CAP_ESW_FLOWTABLE_FDB(dev->mdev, decap) && esw_encap)
  1271. flags |= MLX5_FLOW_TABLE_TUNNEL_EN_DECAP;
  1272. if (MLX5_CAP_ESW_FLOWTABLE_FDB(dev->mdev,
  1273. reformat_l3_tunnel_to_l2) &&
  1274. esw_encap)
  1275. flags |= MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT;
  1276. priority = user_priority;
  1277. break;
  1278. case MLX5_FLOW_NAMESPACE_RDMA_RX:
  1279. max_table_size = BIT(
  1280. MLX5_CAP_FLOWTABLE_RDMA_RX(dev->mdev, log_max_ft_size));
  1281. priority = user_priority;
  1282. break;
  1283. case MLX5_FLOW_NAMESPACE_RDMA_TX:
  1284. max_table_size = BIT(
  1285. MLX5_CAP_FLOWTABLE_RDMA_TX(dev->mdev, log_max_ft_size));
  1286. priority = user_priority;
  1287. break;
  1288. default:
  1289. break;
  1290. }
  1291. max_table_size = min_t(int, max_table_size, MLX5_FS_MAX_ENTRIES);
  1292. ns = mlx5_get_flow_namespace(dev->mdev, ns_type);
  1293. if (!ns)
  1294. return ERR_PTR(-EOPNOTSUPP);
  1295. switch (ns_type) {
  1296. case MLX5_FLOW_NAMESPACE_BYPASS:
  1297. prio = &dev->flow_db->prios[priority];
  1298. break;
  1299. case MLX5_FLOW_NAMESPACE_EGRESS:
  1300. prio = &dev->flow_db->egress_prios[priority];
  1301. break;
  1302. case MLX5_FLOW_NAMESPACE_FDB_BYPASS:
  1303. prio = &dev->flow_db->fdb[priority];
  1304. break;
  1305. case MLX5_FLOW_NAMESPACE_RDMA_RX:
  1306. prio = &dev->flow_db->rdma_rx[priority];
  1307. break;
  1308. case MLX5_FLOW_NAMESPACE_RDMA_TX:
  1309. prio = &dev->flow_db->rdma_tx[priority];
  1310. break;
  1311. default: return ERR_PTR(-EINVAL);
  1312. }
  1313. if (!prio)
  1314. return ERR_PTR(-EINVAL);
  1315. if (prio->flow_table)
  1316. return prio;
  1317. return _get_prio(dev, ns, prio, priority, max_table_size,
  1318. MLX5_FS_MAX_TYPES, flags);
  1319. }
  1320. static struct mlx5_ib_flow_handler *
  1321. _create_raw_flow_rule(struct mlx5_ib_dev *dev,
  1322. struct mlx5_ib_flow_prio *ft_prio,
  1323. struct mlx5_flow_destination *dst,
  1324. struct mlx5_ib_flow_matcher *fs_matcher,
  1325. struct mlx5_flow_context *flow_context,
  1326. struct mlx5_flow_act *flow_act,
  1327. void *cmd_in, int inlen,
  1328. int dst_num)
  1329. {
  1330. struct mlx5_ib_flow_handler *handler;
  1331. struct mlx5_flow_spec *spec;
  1332. struct mlx5_flow_table *ft = ft_prio->flow_table;
  1333. int err = 0;
  1334. spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
  1335. handler = kzalloc(sizeof(*handler), GFP_KERNEL);
  1336. if (!handler || !spec) {
  1337. err = -ENOMEM;
  1338. goto free;
  1339. }
  1340. INIT_LIST_HEAD(&handler->list);
  1341. memcpy(spec->match_value, cmd_in, inlen);
  1342. memcpy(spec->match_criteria, fs_matcher->matcher_mask.match_params,
  1343. fs_matcher->mask_len);
  1344. spec->match_criteria_enable = fs_matcher->match_criteria_enable;
  1345. spec->flow_context = *flow_context;
  1346. handler->rule = mlx5_add_flow_rules(ft, spec,
  1347. flow_act, dst, dst_num);
  1348. if (IS_ERR(handler->rule)) {
  1349. err = PTR_ERR(handler->rule);
  1350. goto free;
  1351. }
  1352. ft_prio->refcount++;
  1353. handler->prio = ft_prio;
  1354. handler->dev = dev;
  1355. ft_prio->flow_table = ft;
  1356. free:
  1357. if (err)
  1358. kfree(handler);
  1359. kvfree(spec);
  1360. return err ? ERR_PTR(err) : handler;
  1361. }
  1362. static bool raw_fs_is_multicast(struct mlx5_ib_flow_matcher *fs_matcher,
  1363. void *match_v)
  1364. {
  1365. void *match_c;
  1366. void *match_v_set_lyr_2_4, *match_c_set_lyr_2_4;
  1367. void *dmac, *dmac_mask;
  1368. void *ipv4, *ipv4_mask;
  1369. if (!(fs_matcher->match_criteria_enable &
  1370. (1 << MATCH_CRITERIA_ENABLE_OUTER_BIT)))
  1371. return false;
  1372. match_c = fs_matcher->matcher_mask.match_params;
  1373. match_v_set_lyr_2_4 = MLX5_ADDR_OF(fte_match_param, match_v,
  1374. outer_headers);
  1375. match_c_set_lyr_2_4 = MLX5_ADDR_OF(fte_match_param, match_c,
  1376. outer_headers);
  1377. dmac = MLX5_ADDR_OF(fte_match_set_lyr_2_4, match_v_set_lyr_2_4,
  1378. dmac_47_16);
  1379. dmac_mask = MLX5_ADDR_OF(fte_match_set_lyr_2_4, match_c_set_lyr_2_4,
  1380. dmac_47_16);
  1381. if (is_multicast_ether_addr(dmac) &&
  1382. is_multicast_ether_addr(dmac_mask))
  1383. return true;
  1384. ipv4 = MLX5_ADDR_OF(fte_match_set_lyr_2_4, match_v_set_lyr_2_4,
  1385. dst_ipv4_dst_ipv6.ipv4_layout.ipv4);
  1386. ipv4_mask = MLX5_ADDR_OF(fte_match_set_lyr_2_4, match_c_set_lyr_2_4,
  1387. dst_ipv4_dst_ipv6.ipv4_layout.ipv4);
  1388. if (ipv4_is_multicast(*(__be32 *)(ipv4)) &&
  1389. ipv4_is_multicast(*(__be32 *)(ipv4_mask)))
  1390. return true;
  1391. return false;
  1392. }
  1393. static struct mlx5_ib_flow_handler *raw_fs_rule_add(
  1394. struct mlx5_ib_dev *dev, struct mlx5_ib_flow_matcher *fs_matcher,
  1395. struct mlx5_flow_context *flow_context, struct mlx5_flow_act *flow_act,
  1396. u32 counter_id, void *cmd_in, int inlen, int dest_id, int dest_type)
  1397. {
  1398. struct mlx5_flow_destination *dst;
  1399. struct mlx5_ib_flow_prio *ft_prio;
  1400. struct mlx5_ib_flow_handler *handler;
  1401. int dst_num = 0;
  1402. bool mcast;
  1403. int err;
  1404. if (fs_matcher->flow_type != MLX5_IB_FLOW_TYPE_NORMAL)
  1405. return ERR_PTR(-EOPNOTSUPP);
  1406. if (fs_matcher->priority > MLX5_IB_FLOW_LAST_PRIO)
  1407. return ERR_PTR(-ENOMEM);
  1408. dst = kcalloc(2, sizeof(*dst), GFP_KERNEL);
  1409. if (!dst)
  1410. return ERR_PTR(-ENOMEM);
  1411. mcast = raw_fs_is_multicast(fs_matcher, cmd_in);
  1412. mutex_lock(&dev->flow_db->lock);
  1413. ft_prio = _get_flow_table(dev, fs_matcher->priority,
  1414. fs_matcher->ns_type, mcast);
  1415. if (IS_ERR(ft_prio)) {
  1416. err = PTR_ERR(ft_prio);
  1417. goto unlock;
  1418. }
  1419. switch (dest_type) {
  1420. case MLX5_FLOW_DESTINATION_TYPE_TIR:
  1421. dst[dst_num].type = dest_type;
  1422. dst[dst_num++].tir_num = dest_id;
  1423. flow_act->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
  1424. break;
  1425. case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE:
  1426. dst[dst_num].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE_NUM;
  1427. dst[dst_num++].ft_num = dest_id;
  1428. flow_act->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
  1429. break;
  1430. case MLX5_FLOW_DESTINATION_TYPE_PORT:
  1431. dst[dst_num++].type = MLX5_FLOW_DESTINATION_TYPE_PORT;
  1432. flow_act->action |= MLX5_FLOW_CONTEXT_ACTION_ALLOW;
  1433. break;
  1434. default:
  1435. break;
  1436. }
  1437. if (flow_act->action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
  1438. dst[dst_num].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
  1439. dst[dst_num].counter_id = counter_id;
  1440. dst_num++;
  1441. }
  1442. handler = _create_raw_flow_rule(dev, ft_prio, dst_num ? dst : NULL,
  1443. fs_matcher, flow_context, flow_act,
  1444. cmd_in, inlen, dst_num);
  1445. if (IS_ERR(handler)) {
  1446. err = PTR_ERR(handler);
  1447. goto destroy_ft;
  1448. }
  1449. mutex_unlock(&dev->flow_db->lock);
  1450. atomic_inc(&fs_matcher->usecnt);
  1451. handler->flow_matcher = fs_matcher;
  1452. kfree(dst);
  1453. return handler;
  1454. destroy_ft:
  1455. put_flow_table(dev, ft_prio, false);
  1456. unlock:
  1457. mutex_unlock(&dev->flow_db->lock);
  1458. kfree(dst);
  1459. return ERR_PTR(err);
  1460. }
  1461. static void destroy_flow_action_raw(struct mlx5_ib_flow_action *maction)
  1462. {
  1463. switch (maction->flow_action_raw.sub_type) {
  1464. case MLX5_IB_FLOW_ACTION_MODIFY_HEADER:
  1465. mlx5_modify_header_dealloc(maction->flow_action_raw.dev->mdev,
  1466. maction->flow_action_raw.modify_hdr);
  1467. break;
  1468. case MLX5_IB_FLOW_ACTION_PACKET_REFORMAT:
  1469. mlx5_packet_reformat_dealloc(maction->flow_action_raw.dev->mdev,
  1470. maction->flow_action_raw.pkt_reformat);
  1471. break;
  1472. case MLX5_IB_FLOW_ACTION_DECAP:
  1473. break;
  1474. default:
  1475. break;
  1476. }
  1477. }
  1478. static int mlx5_ib_destroy_flow_action(struct ib_flow_action *action)
  1479. {
  1480. struct mlx5_ib_flow_action *maction = to_mflow_act(action);
  1481. switch (action->type) {
  1482. case IB_FLOW_ACTION_UNSPECIFIED:
  1483. destroy_flow_action_raw(maction);
  1484. break;
  1485. default:
  1486. WARN_ON(true);
  1487. break;
  1488. }
  1489. kfree(maction);
  1490. return 0;
  1491. }
  1492. static int
  1493. mlx5_ib_ft_type_to_namespace(enum mlx5_ib_uapi_flow_table_type table_type,
  1494. enum mlx5_flow_namespace_type *namespace)
  1495. {
  1496. switch (table_type) {
  1497. case MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_RX:
  1498. *namespace = MLX5_FLOW_NAMESPACE_BYPASS;
  1499. break;
  1500. case MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_TX:
  1501. *namespace = MLX5_FLOW_NAMESPACE_EGRESS;
  1502. break;
  1503. case MLX5_IB_UAPI_FLOW_TABLE_TYPE_FDB:
  1504. *namespace = MLX5_FLOW_NAMESPACE_FDB_BYPASS;
  1505. break;
  1506. case MLX5_IB_UAPI_FLOW_TABLE_TYPE_RDMA_RX:
  1507. *namespace = MLX5_FLOW_NAMESPACE_RDMA_RX;
  1508. break;
  1509. case MLX5_IB_UAPI_FLOW_TABLE_TYPE_RDMA_TX:
  1510. *namespace = MLX5_FLOW_NAMESPACE_RDMA_TX;
  1511. break;
  1512. default:
  1513. return -EINVAL;
  1514. }
  1515. return 0;
  1516. }
  1517. static const struct uverbs_attr_spec mlx5_ib_flow_type[] = {
  1518. [MLX5_IB_FLOW_TYPE_NORMAL] = {
  1519. .type = UVERBS_ATTR_TYPE_PTR_IN,
  1520. .u.ptr = {
  1521. .len = sizeof(u16), /* data is priority */
  1522. .min_len = sizeof(u16),
  1523. }
  1524. },
  1525. [MLX5_IB_FLOW_TYPE_SNIFFER] = {
  1526. .type = UVERBS_ATTR_TYPE_PTR_IN,
  1527. UVERBS_ATTR_NO_DATA(),
  1528. },
  1529. [MLX5_IB_FLOW_TYPE_ALL_DEFAULT] = {
  1530. .type = UVERBS_ATTR_TYPE_PTR_IN,
  1531. UVERBS_ATTR_NO_DATA(),
  1532. },
  1533. [MLX5_IB_FLOW_TYPE_MC_DEFAULT] = {
  1534. .type = UVERBS_ATTR_TYPE_PTR_IN,
  1535. UVERBS_ATTR_NO_DATA(),
  1536. },
  1537. };
  1538. static bool is_flow_dest(void *obj, int *dest_id, int *dest_type)
  1539. {
  1540. struct devx_obj *devx_obj = obj;
  1541. u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, devx_obj->dinbox, opcode);
  1542. switch (opcode) {
  1543. case MLX5_CMD_OP_DESTROY_TIR:
  1544. *dest_type = MLX5_FLOW_DESTINATION_TYPE_TIR;
  1545. *dest_id = MLX5_GET(general_obj_in_cmd_hdr, devx_obj->dinbox,
  1546. obj_id);
  1547. return true;
  1548. case MLX5_CMD_OP_DESTROY_FLOW_TABLE:
  1549. *dest_type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
  1550. *dest_id = MLX5_GET(destroy_flow_table_in, devx_obj->dinbox,
  1551. table_id);
  1552. return true;
  1553. default:
  1554. return false;
  1555. }
  1556. }
  1557. static int get_dests(struct uverbs_attr_bundle *attrs,
  1558. struct mlx5_ib_flow_matcher *fs_matcher, int *dest_id,
  1559. int *dest_type, struct ib_qp **qp, u32 *flags)
  1560. {
  1561. bool dest_devx, dest_qp;
  1562. void *devx_obj;
  1563. int err;
  1564. dest_devx = uverbs_attr_is_valid(attrs,
  1565. MLX5_IB_ATTR_CREATE_FLOW_DEST_DEVX);
  1566. dest_qp = uverbs_attr_is_valid(attrs,
  1567. MLX5_IB_ATTR_CREATE_FLOW_DEST_QP);
  1568. *flags = 0;
  1569. err = uverbs_get_flags32(flags, attrs, MLX5_IB_ATTR_CREATE_FLOW_FLAGS,
  1570. MLX5_IB_ATTR_CREATE_FLOW_FLAGS_DEFAULT_MISS |
  1571. MLX5_IB_ATTR_CREATE_FLOW_FLAGS_DROP);
  1572. if (err)
  1573. return err;
  1574. /* Both flags are not allowed */
  1575. if (*flags & MLX5_IB_ATTR_CREATE_FLOW_FLAGS_DEFAULT_MISS &&
  1576. *flags & MLX5_IB_ATTR_CREATE_FLOW_FLAGS_DROP)
  1577. return -EINVAL;
  1578. if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_BYPASS) {
  1579. if (dest_devx && (dest_qp || *flags))
  1580. return -EINVAL;
  1581. else if (dest_qp && *flags)
  1582. return -EINVAL;
  1583. }
  1584. /* Allow only DEVX object, drop as dest for FDB */
  1585. if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_FDB_BYPASS &&
  1586. !(dest_devx || (*flags & MLX5_IB_ATTR_CREATE_FLOW_FLAGS_DROP)))
  1587. return -EINVAL;
  1588. /* Allow only DEVX object or QP as dest when inserting to RDMA_RX */
  1589. if ((fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_RDMA_RX) &&
  1590. ((!dest_devx && !dest_qp) || (dest_devx && dest_qp)))
  1591. return -EINVAL;
  1592. *qp = NULL;
  1593. if (dest_devx) {
  1594. devx_obj =
  1595. uverbs_attr_get_obj(attrs,
  1596. MLX5_IB_ATTR_CREATE_FLOW_DEST_DEVX);
  1597. /* Verify that the given DEVX object is a flow
  1598. * steering destination.
  1599. */
  1600. if (!is_flow_dest(devx_obj, dest_id, dest_type))
  1601. return -EINVAL;
  1602. /* Allow only flow table as dest when inserting to FDB or RDMA_RX */
  1603. if ((fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_FDB_BYPASS ||
  1604. fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_RDMA_RX) &&
  1605. *dest_type != MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE)
  1606. return -EINVAL;
  1607. } else if (dest_qp) {
  1608. struct mlx5_ib_qp *mqp;
  1609. *qp = uverbs_attr_get_obj(attrs,
  1610. MLX5_IB_ATTR_CREATE_FLOW_DEST_QP);
  1611. if (IS_ERR(*qp))
  1612. return PTR_ERR(*qp);
  1613. if ((*qp)->qp_type != IB_QPT_RAW_PACKET)
  1614. return -EINVAL;
  1615. mqp = to_mqp(*qp);
  1616. if (mqp->is_rss)
  1617. *dest_id = mqp->rss_qp.tirn;
  1618. else
  1619. *dest_id = mqp->raw_packet_qp.rq.tirn;
  1620. *dest_type = MLX5_FLOW_DESTINATION_TYPE_TIR;
  1621. } else if ((fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_EGRESS ||
  1622. fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_RDMA_TX) &&
  1623. !(*flags & MLX5_IB_ATTR_CREATE_FLOW_FLAGS_DROP)) {
  1624. *dest_type = MLX5_FLOW_DESTINATION_TYPE_PORT;
  1625. }
  1626. if (*dest_type == MLX5_FLOW_DESTINATION_TYPE_TIR &&
  1627. (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_EGRESS ||
  1628. fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_RDMA_TX))
  1629. return -EINVAL;
  1630. return 0;
  1631. }
  1632. static bool is_flow_counter(void *obj, u32 offset, u32 *counter_id)
  1633. {
  1634. struct devx_obj *devx_obj = obj;
  1635. u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, devx_obj->dinbox, opcode);
  1636. if (opcode == MLX5_CMD_OP_DEALLOC_FLOW_COUNTER) {
  1637. if (offset && offset >= devx_obj->flow_counter_bulk_size)
  1638. return false;
  1639. *counter_id = MLX5_GET(dealloc_flow_counter_in,
  1640. devx_obj->dinbox,
  1641. flow_counter_id);
  1642. *counter_id += offset;
  1643. return true;
  1644. }
  1645. return false;
  1646. }
  1647. #define MLX5_IB_CREATE_FLOW_MAX_FLOW_ACTIONS 2
  1648. static int UVERBS_HANDLER(MLX5_IB_METHOD_CREATE_FLOW)(
  1649. struct uverbs_attr_bundle *attrs)
  1650. {
  1651. struct mlx5_flow_context flow_context = {.flow_tag =
  1652. MLX5_FS_DEFAULT_FLOW_TAG};
  1653. u32 *offset_attr, offset = 0, counter_id = 0;
  1654. int dest_id, dest_type = -1, inlen, len, ret, i;
  1655. struct mlx5_ib_flow_handler *flow_handler;
  1656. struct mlx5_ib_flow_matcher *fs_matcher;
  1657. struct ib_uobject **arr_flow_actions;
  1658. struct ib_uflow_resources *uflow_res;
  1659. struct mlx5_flow_act flow_act = {};
  1660. struct ib_qp *qp = NULL;
  1661. void *devx_obj, *cmd_in;
  1662. struct ib_uobject *uobj;
  1663. struct mlx5_ib_dev *dev;
  1664. u32 flags;
  1665. if (!capable(CAP_NET_RAW))
  1666. return -EPERM;
  1667. fs_matcher = uverbs_attr_get_obj(attrs,
  1668. MLX5_IB_ATTR_CREATE_FLOW_MATCHER);
  1669. uobj = uverbs_attr_get_uobject(attrs, MLX5_IB_ATTR_CREATE_FLOW_HANDLE);
  1670. dev = mlx5_udata_to_mdev(&attrs->driver_udata);
  1671. if (get_dests(attrs, fs_matcher, &dest_id, &dest_type, &qp, &flags))
  1672. return -EINVAL;
  1673. if (flags & MLX5_IB_ATTR_CREATE_FLOW_FLAGS_DEFAULT_MISS)
  1674. flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_NS;
  1675. if (flags & MLX5_IB_ATTR_CREATE_FLOW_FLAGS_DROP)
  1676. flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_DROP;
  1677. len = uverbs_attr_get_uobjs_arr(attrs,
  1678. MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX, &arr_flow_actions);
  1679. if (len) {
  1680. devx_obj = arr_flow_actions[0]->object;
  1681. if (uverbs_attr_is_valid(attrs,
  1682. MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX_OFFSET)) {
  1683. int num_offsets = uverbs_attr_ptr_get_array_size(
  1684. attrs,
  1685. MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX_OFFSET,
  1686. sizeof(u32));
  1687. if (num_offsets != 1)
  1688. return -EINVAL;
  1689. offset_attr = uverbs_attr_get_alloced_ptr(
  1690. attrs,
  1691. MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX_OFFSET);
  1692. offset = *offset_attr;
  1693. }
  1694. if (!is_flow_counter(devx_obj, offset, &counter_id))
  1695. return -EINVAL;
  1696. flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_COUNT;
  1697. }
  1698. cmd_in = uverbs_attr_get_alloced_ptr(
  1699. attrs, MLX5_IB_ATTR_CREATE_FLOW_MATCH_VALUE);
  1700. inlen = uverbs_attr_get_len(attrs,
  1701. MLX5_IB_ATTR_CREATE_FLOW_MATCH_VALUE);
  1702. uflow_res = flow_resources_alloc(MLX5_IB_CREATE_FLOW_MAX_FLOW_ACTIONS);
  1703. if (!uflow_res)
  1704. return -ENOMEM;
  1705. len = uverbs_attr_get_uobjs_arr(attrs,
  1706. MLX5_IB_ATTR_CREATE_FLOW_ARR_FLOW_ACTIONS, &arr_flow_actions);
  1707. for (i = 0; i < len; i++) {
  1708. struct mlx5_ib_flow_action *maction =
  1709. to_mflow_act(arr_flow_actions[i]->object);
  1710. ret = parse_flow_flow_action(maction, false, &flow_act);
  1711. if (ret)
  1712. goto err_out;
  1713. flow_resources_add(uflow_res, IB_FLOW_SPEC_ACTION_HANDLE,
  1714. arr_flow_actions[i]->object);
  1715. }
  1716. ret = uverbs_copy_from(&flow_context.flow_tag, attrs,
  1717. MLX5_IB_ATTR_CREATE_FLOW_TAG);
  1718. if (!ret) {
  1719. if (flow_context.flow_tag >= BIT(24)) {
  1720. ret = -EINVAL;
  1721. goto err_out;
  1722. }
  1723. flow_context.flags |= FLOW_CONTEXT_HAS_TAG;
  1724. }
  1725. flow_handler =
  1726. raw_fs_rule_add(dev, fs_matcher, &flow_context, &flow_act,
  1727. counter_id, cmd_in, inlen, dest_id, dest_type);
  1728. if (IS_ERR(flow_handler)) {
  1729. ret = PTR_ERR(flow_handler);
  1730. goto err_out;
  1731. }
  1732. ib_set_flow(uobj, &flow_handler->ibflow, qp, &dev->ib_dev, uflow_res);
  1733. return 0;
  1734. err_out:
  1735. ib_uverbs_flow_resources_free(uflow_res);
  1736. return ret;
  1737. }
  1738. static int flow_matcher_cleanup(struct ib_uobject *uobject,
  1739. enum rdma_remove_reason why,
  1740. struct uverbs_attr_bundle *attrs)
  1741. {
  1742. struct mlx5_ib_flow_matcher *obj = uobject->object;
  1743. if (atomic_read(&obj->usecnt))
  1744. return -EBUSY;
  1745. kfree(obj);
  1746. return 0;
  1747. }
  1748. static int steering_anchor_create_ft(struct mlx5_ib_dev *dev,
  1749. struct mlx5_ib_flow_prio *ft_prio,
  1750. enum mlx5_flow_namespace_type ns_type)
  1751. {
  1752. struct mlx5_flow_table_attr ft_attr = {};
  1753. struct mlx5_flow_namespace *ns;
  1754. struct mlx5_flow_table *ft;
  1755. if (ft_prio->anchor.ft)
  1756. return 0;
  1757. ns = mlx5_get_flow_namespace(dev->mdev, ns_type);
  1758. if (!ns)
  1759. return -EOPNOTSUPP;
  1760. ft_attr.flags = MLX5_FLOW_TABLE_UNMANAGED;
  1761. ft_attr.uid = MLX5_SHARED_RESOURCE_UID;
  1762. ft_attr.prio = 0;
  1763. ft_attr.max_fte = 2;
  1764. ft_attr.level = 1;
  1765. ft = mlx5_create_flow_table(ns, &ft_attr);
  1766. if (IS_ERR(ft))
  1767. return PTR_ERR(ft);
  1768. ft_prio->anchor.ft = ft;
  1769. return 0;
  1770. }
  1771. static void steering_anchor_destroy_ft(struct mlx5_ib_flow_prio *ft_prio)
  1772. {
  1773. if (ft_prio->anchor.ft) {
  1774. mlx5_destroy_flow_table(ft_prio->anchor.ft);
  1775. ft_prio->anchor.ft = NULL;
  1776. }
  1777. }
  1778. static int
  1779. steering_anchor_create_fg_drop(struct mlx5_ib_flow_prio *ft_prio)
  1780. {
  1781. int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
  1782. struct mlx5_flow_group *fg;
  1783. void *flow_group_in;
  1784. int err = 0;
  1785. if (ft_prio->anchor.fg_drop)
  1786. return 0;
  1787. flow_group_in = kvzalloc(inlen, GFP_KERNEL);
  1788. if (!flow_group_in)
  1789. return -ENOMEM;
  1790. MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 1);
  1791. MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 1);
  1792. fg = mlx5_create_flow_group(ft_prio->anchor.ft, flow_group_in);
  1793. if (IS_ERR(fg)) {
  1794. err = PTR_ERR(fg);
  1795. goto out;
  1796. }
  1797. ft_prio->anchor.fg_drop = fg;
  1798. out:
  1799. kvfree(flow_group_in);
  1800. return err;
  1801. }
  1802. static void
  1803. steering_anchor_destroy_fg_drop(struct mlx5_ib_flow_prio *ft_prio)
  1804. {
  1805. if (ft_prio->anchor.fg_drop) {
  1806. mlx5_destroy_flow_group(ft_prio->anchor.fg_drop);
  1807. ft_prio->anchor.fg_drop = NULL;
  1808. }
  1809. }
  1810. static int
  1811. steering_anchor_create_fg_goto_table(struct mlx5_ib_flow_prio *ft_prio)
  1812. {
  1813. int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
  1814. struct mlx5_flow_group *fg;
  1815. void *flow_group_in;
  1816. int err = 0;
  1817. if (ft_prio->anchor.fg_goto_table)
  1818. return 0;
  1819. flow_group_in = kvzalloc(inlen, GFP_KERNEL);
  1820. if (!flow_group_in)
  1821. return -ENOMEM;
  1822. fg = mlx5_create_flow_group(ft_prio->anchor.ft, flow_group_in);
  1823. if (IS_ERR(fg)) {
  1824. err = PTR_ERR(fg);
  1825. goto out;
  1826. }
  1827. ft_prio->anchor.fg_goto_table = fg;
  1828. out:
  1829. kvfree(flow_group_in);
  1830. return err;
  1831. }
  1832. static void
  1833. steering_anchor_destroy_fg_goto_table(struct mlx5_ib_flow_prio *ft_prio)
  1834. {
  1835. if (ft_prio->anchor.fg_goto_table) {
  1836. mlx5_destroy_flow_group(ft_prio->anchor.fg_goto_table);
  1837. ft_prio->anchor.fg_goto_table = NULL;
  1838. }
  1839. }
  1840. static int
  1841. steering_anchor_create_rule_drop(struct mlx5_ib_flow_prio *ft_prio)
  1842. {
  1843. struct mlx5_flow_act flow_act = {};
  1844. struct mlx5_flow_handle *handle;
  1845. if (ft_prio->anchor.rule_drop)
  1846. return 0;
  1847. flow_act.fg = ft_prio->anchor.fg_drop;
  1848. flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP;
  1849. handle = mlx5_add_flow_rules(ft_prio->anchor.ft, NULL, &flow_act,
  1850. NULL, 0);
  1851. if (IS_ERR(handle))
  1852. return PTR_ERR(handle);
  1853. ft_prio->anchor.rule_drop = handle;
  1854. return 0;
  1855. }
  1856. static void steering_anchor_destroy_rule_drop(struct mlx5_ib_flow_prio *ft_prio)
  1857. {
  1858. if (ft_prio->anchor.rule_drop) {
  1859. mlx5_del_flow_rules(ft_prio->anchor.rule_drop);
  1860. ft_prio->anchor.rule_drop = NULL;
  1861. }
  1862. }
  1863. static int
  1864. steering_anchor_create_rule_goto_table(struct mlx5_ib_flow_prio *ft_prio)
  1865. {
  1866. struct mlx5_flow_destination dest = {};
  1867. struct mlx5_flow_act flow_act = {};
  1868. struct mlx5_flow_handle *handle;
  1869. if (ft_prio->anchor.rule_goto_table)
  1870. return 0;
  1871. flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
  1872. flow_act.flags |= FLOW_ACT_IGNORE_FLOW_LEVEL;
  1873. flow_act.fg = ft_prio->anchor.fg_goto_table;
  1874. dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
  1875. dest.ft = ft_prio->flow_table;
  1876. handle = mlx5_add_flow_rules(ft_prio->anchor.ft, NULL, &flow_act,
  1877. &dest, 1);
  1878. if (IS_ERR(handle))
  1879. return PTR_ERR(handle);
  1880. ft_prio->anchor.rule_goto_table = handle;
  1881. return 0;
  1882. }
  1883. static void
  1884. steering_anchor_destroy_rule_goto_table(struct mlx5_ib_flow_prio *ft_prio)
  1885. {
  1886. if (ft_prio->anchor.rule_goto_table) {
  1887. mlx5_del_flow_rules(ft_prio->anchor.rule_goto_table);
  1888. ft_prio->anchor.rule_goto_table = NULL;
  1889. }
  1890. }
  1891. static int steering_anchor_create_res(struct mlx5_ib_dev *dev,
  1892. struct mlx5_ib_flow_prio *ft_prio,
  1893. enum mlx5_flow_namespace_type ns_type)
  1894. {
  1895. int err;
  1896. err = steering_anchor_create_ft(dev, ft_prio, ns_type);
  1897. if (err)
  1898. return err;
  1899. err = steering_anchor_create_fg_drop(ft_prio);
  1900. if (err)
  1901. goto destroy_ft;
  1902. err = steering_anchor_create_fg_goto_table(ft_prio);
  1903. if (err)
  1904. goto destroy_fg_drop;
  1905. err = steering_anchor_create_rule_drop(ft_prio);
  1906. if (err)
  1907. goto destroy_fg_goto_table;
  1908. err = steering_anchor_create_rule_goto_table(ft_prio);
  1909. if (err)
  1910. goto destroy_rule_drop;
  1911. return 0;
  1912. destroy_rule_drop:
  1913. steering_anchor_destroy_rule_drop(ft_prio);
  1914. destroy_fg_goto_table:
  1915. steering_anchor_destroy_fg_goto_table(ft_prio);
  1916. destroy_fg_drop:
  1917. steering_anchor_destroy_fg_drop(ft_prio);
  1918. destroy_ft:
  1919. steering_anchor_destroy_ft(ft_prio);
  1920. return err;
  1921. }
  1922. static void mlx5_steering_anchor_destroy_res(struct mlx5_ib_flow_prio *ft_prio)
  1923. {
  1924. steering_anchor_destroy_rule_goto_table(ft_prio);
  1925. steering_anchor_destroy_rule_drop(ft_prio);
  1926. steering_anchor_destroy_fg_goto_table(ft_prio);
  1927. steering_anchor_destroy_fg_drop(ft_prio);
  1928. steering_anchor_destroy_ft(ft_prio);
  1929. }
  1930. static int steering_anchor_cleanup(struct ib_uobject *uobject,
  1931. enum rdma_remove_reason why,
  1932. struct uverbs_attr_bundle *attrs)
  1933. {
  1934. struct mlx5_ib_steering_anchor *obj = uobject->object;
  1935. if (atomic_read(&obj->usecnt))
  1936. return -EBUSY;
  1937. mutex_lock(&obj->dev->flow_db->lock);
  1938. if (!--obj->ft_prio->anchor.rule_goto_table_ref)
  1939. steering_anchor_destroy_rule_goto_table(obj->ft_prio);
  1940. put_flow_table(obj->dev, obj->ft_prio, true);
  1941. mutex_unlock(&obj->dev->flow_db->lock);
  1942. kfree(obj);
  1943. return 0;
  1944. }
  1945. static void fs_cleanup_anchor(struct mlx5_ib_flow_prio *prio,
  1946. int count)
  1947. {
  1948. while (count--)
  1949. mlx5_steering_anchor_destroy_res(&prio[count]);
  1950. }
  1951. void mlx5_ib_fs_cleanup_anchor(struct mlx5_ib_dev *dev)
  1952. {
  1953. fs_cleanup_anchor(dev->flow_db->prios, MLX5_IB_NUM_FLOW_FT);
  1954. fs_cleanup_anchor(dev->flow_db->egress_prios, MLX5_IB_NUM_FLOW_FT);
  1955. fs_cleanup_anchor(dev->flow_db->sniffer, MLX5_IB_NUM_SNIFFER_FTS);
  1956. fs_cleanup_anchor(dev->flow_db->egress, MLX5_IB_NUM_EGRESS_FTS);
  1957. fs_cleanup_anchor(dev->flow_db->fdb, MLX5_IB_NUM_FDB_FTS);
  1958. fs_cleanup_anchor(dev->flow_db->rdma_rx, MLX5_IB_NUM_FLOW_FT);
  1959. fs_cleanup_anchor(dev->flow_db->rdma_tx, MLX5_IB_NUM_FLOW_FT);
  1960. }
  1961. static int mlx5_ib_matcher_ns(struct uverbs_attr_bundle *attrs,
  1962. struct mlx5_ib_flow_matcher *obj)
  1963. {
  1964. enum mlx5_ib_uapi_flow_table_type ft_type =
  1965. MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_RX;
  1966. u32 flags;
  1967. int err;
  1968. /* New users should use MLX5_IB_ATTR_FLOW_MATCHER_FT_TYPE and older
  1969. * users should switch to it. We leave this to not break userspace
  1970. */
  1971. if (uverbs_attr_is_valid(attrs, MLX5_IB_ATTR_FLOW_MATCHER_FT_TYPE) &&
  1972. uverbs_attr_is_valid(attrs, MLX5_IB_ATTR_FLOW_MATCHER_FLOW_FLAGS))
  1973. return -EINVAL;
  1974. if (uverbs_attr_is_valid(attrs, MLX5_IB_ATTR_FLOW_MATCHER_FT_TYPE)) {
  1975. err = uverbs_get_const(&ft_type, attrs,
  1976. MLX5_IB_ATTR_FLOW_MATCHER_FT_TYPE);
  1977. if (err)
  1978. return err;
  1979. err = mlx5_ib_ft_type_to_namespace(ft_type, &obj->ns_type);
  1980. if (err)
  1981. return err;
  1982. return 0;
  1983. }
  1984. if (uverbs_attr_is_valid(attrs, MLX5_IB_ATTR_FLOW_MATCHER_FLOW_FLAGS)) {
  1985. err = uverbs_get_flags32(&flags, attrs,
  1986. MLX5_IB_ATTR_FLOW_MATCHER_FLOW_FLAGS,
  1987. IB_FLOW_ATTR_FLAGS_EGRESS);
  1988. if (err)
  1989. return err;
  1990. if (flags)
  1991. return mlx5_ib_ft_type_to_namespace(
  1992. MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_TX,
  1993. &obj->ns_type);
  1994. }
  1995. obj->ns_type = MLX5_FLOW_NAMESPACE_BYPASS;
  1996. return 0;
  1997. }
  1998. static int UVERBS_HANDLER(MLX5_IB_METHOD_FLOW_MATCHER_CREATE)(
  1999. struct uverbs_attr_bundle *attrs)
  2000. {
  2001. struct ib_uobject *uobj = uverbs_attr_get_uobject(
  2002. attrs, MLX5_IB_ATTR_FLOW_MATCHER_CREATE_HANDLE);
  2003. struct mlx5_ib_dev *dev = mlx5_udata_to_mdev(&attrs->driver_udata);
  2004. struct mlx5_ib_flow_matcher *obj;
  2005. int err;
  2006. obj = kzalloc(sizeof(struct mlx5_ib_flow_matcher), GFP_KERNEL);
  2007. if (!obj)
  2008. return -ENOMEM;
  2009. obj->mask_len = uverbs_attr_get_len(
  2010. attrs, MLX5_IB_ATTR_FLOW_MATCHER_MATCH_MASK);
  2011. err = uverbs_copy_from(&obj->matcher_mask,
  2012. attrs,
  2013. MLX5_IB_ATTR_FLOW_MATCHER_MATCH_MASK);
  2014. if (err)
  2015. goto end;
  2016. obj->flow_type = uverbs_attr_get_enum_id(
  2017. attrs, MLX5_IB_ATTR_FLOW_MATCHER_FLOW_TYPE);
  2018. if (obj->flow_type == MLX5_IB_FLOW_TYPE_NORMAL) {
  2019. err = uverbs_copy_from(&obj->priority,
  2020. attrs,
  2021. MLX5_IB_ATTR_FLOW_MATCHER_FLOW_TYPE);
  2022. if (err)
  2023. goto end;
  2024. }
  2025. err = uverbs_copy_from(&obj->match_criteria_enable,
  2026. attrs,
  2027. MLX5_IB_ATTR_FLOW_MATCHER_MATCH_CRITERIA);
  2028. if (err)
  2029. goto end;
  2030. err = mlx5_ib_matcher_ns(attrs, obj);
  2031. if (err)
  2032. goto end;
  2033. if (obj->ns_type == MLX5_FLOW_NAMESPACE_FDB_BYPASS &&
  2034. mlx5_eswitch_mode(dev->mdev) != MLX5_ESWITCH_OFFLOADS) {
  2035. err = -EINVAL;
  2036. goto end;
  2037. }
  2038. uobj->object = obj;
  2039. obj->mdev = dev->mdev;
  2040. atomic_set(&obj->usecnt, 0);
  2041. return 0;
  2042. end:
  2043. kfree(obj);
  2044. return err;
  2045. }
  2046. static int UVERBS_HANDLER(MLX5_IB_METHOD_STEERING_ANCHOR_CREATE)(
  2047. struct uverbs_attr_bundle *attrs)
  2048. {
  2049. struct ib_uobject *uobj = uverbs_attr_get_uobject(
  2050. attrs, MLX5_IB_ATTR_STEERING_ANCHOR_CREATE_HANDLE);
  2051. struct mlx5_ib_dev *dev = mlx5_udata_to_mdev(&attrs->driver_udata);
  2052. enum mlx5_ib_uapi_flow_table_type ib_uapi_ft_type;
  2053. enum mlx5_flow_namespace_type ns_type;
  2054. struct mlx5_ib_steering_anchor *obj;
  2055. struct mlx5_ib_flow_prio *ft_prio;
  2056. u16 priority;
  2057. u32 ft_id;
  2058. int err;
  2059. if (!capable(CAP_NET_RAW))
  2060. return -EPERM;
  2061. err = uverbs_get_const(&ib_uapi_ft_type, attrs,
  2062. MLX5_IB_ATTR_STEERING_ANCHOR_FT_TYPE);
  2063. if (err)
  2064. return err;
  2065. err = mlx5_ib_ft_type_to_namespace(ib_uapi_ft_type, &ns_type);
  2066. if (err)
  2067. return err;
  2068. err = uverbs_copy_from(&priority, attrs,
  2069. MLX5_IB_ATTR_STEERING_ANCHOR_PRIORITY);
  2070. if (err)
  2071. return err;
  2072. obj = kzalloc(sizeof(*obj), GFP_KERNEL);
  2073. if (!obj)
  2074. return -ENOMEM;
  2075. mutex_lock(&dev->flow_db->lock);
  2076. ft_prio = _get_flow_table(dev, priority, ns_type, 0);
  2077. if (IS_ERR(ft_prio)) {
  2078. err = PTR_ERR(ft_prio);
  2079. goto free_obj;
  2080. }
  2081. ft_prio->refcount++;
  2082. if (!ft_prio->anchor.rule_goto_table_ref) {
  2083. err = steering_anchor_create_res(dev, ft_prio, ns_type);
  2084. if (err)
  2085. goto put_flow_table;
  2086. }
  2087. ft_prio->anchor.rule_goto_table_ref++;
  2088. ft_id = mlx5_flow_table_id(ft_prio->anchor.ft);
  2089. err = uverbs_copy_to(attrs, MLX5_IB_ATTR_STEERING_ANCHOR_FT_ID,
  2090. &ft_id, sizeof(ft_id));
  2091. if (err)
  2092. goto destroy_res;
  2093. mutex_unlock(&dev->flow_db->lock);
  2094. uobj->object = obj;
  2095. obj->dev = dev;
  2096. obj->ft_prio = ft_prio;
  2097. atomic_set(&obj->usecnt, 0);
  2098. return 0;
  2099. destroy_res:
  2100. --ft_prio->anchor.rule_goto_table_ref;
  2101. mlx5_steering_anchor_destroy_res(ft_prio);
  2102. put_flow_table:
  2103. put_flow_table(dev, ft_prio, true);
  2104. free_obj:
  2105. mutex_unlock(&dev->flow_db->lock);
  2106. kfree(obj);
  2107. return err;
  2108. }
  2109. static struct ib_flow_action *
  2110. mlx5_ib_create_modify_header(struct mlx5_ib_dev *dev,
  2111. enum mlx5_ib_uapi_flow_table_type ft_type,
  2112. u8 num_actions, void *in)
  2113. {
  2114. enum mlx5_flow_namespace_type namespace;
  2115. struct mlx5_ib_flow_action *maction;
  2116. int ret;
  2117. ret = mlx5_ib_ft_type_to_namespace(ft_type, &namespace);
  2118. if (ret)
  2119. return ERR_PTR(-EINVAL);
  2120. maction = kzalloc(sizeof(*maction), GFP_KERNEL);
  2121. if (!maction)
  2122. return ERR_PTR(-ENOMEM);
  2123. maction->flow_action_raw.modify_hdr =
  2124. mlx5_modify_header_alloc(dev->mdev, namespace, num_actions, in);
  2125. if (IS_ERR(maction->flow_action_raw.modify_hdr)) {
  2126. ret = PTR_ERR(maction->flow_action_raw.modify_hdr);
  2127. kfree(maction);
  2128. return ERR_PTR(ret);
  2129. }
  2130. maction->flow_action_raw.sub_type =
  2131. MLX5_IB_FLOW_ACTION_MODIFY_HEADER;
  2132. maction->flow_action_raw.dev = dev;
  2133. return &maction->ib_action;
  2134. }
  2135. static bool mlx5_ib_modify_header_supported(struct mlx5_ib_dev *dev)
  2136. {
  2137. return MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev,
  2138. max_modify_header_actions) ||
  2139. MLX5_CAP_FLOWTABLE_NIC_TX(dev->mdev,
  2140. max_modify_header_actions) ||
  2141. MLX5_CAP_FLOWTABLE_RDMA_TX(dev->mdev,
  2142. max_modify_header_actions);
  2143. }
  2144. static int UVERBS_HANDLER(MLX5_IB_METHOD_FLOW_ACTION_CREATE_MODIFY_HEADER)(
  2145. struct uverbs_attr_bundle *attrs)
  2146. {
  2147. struct ib_uobject *uobj = uverbs_attr_get_uobject(
  2148. attrs, MLX5_IB_ATTR_CREATE_MODIFY_HEADER_HANDLE);
  2149. struct mlx5_ib_dev *mdev = mlx5_udata_to_mdev(&attrs->driver_udata);
  2150. enum mlx5_ib_uapi_flow_table_type ft_type;
  2151. struct ib_flow_action *action;
  2152. int num_actions;
  2153. void *in;
  2154. int ret;
  2155. if (!mlx5_ib_modify_header_supported(mdev))
  2156. return -EOPNOTSUPP;
  2157. in = uverbs_attr_get_alloced_ptr(attrs,
  2158. MLX5_IB_ATTR_CREATE_MODIFY_HEADER_ACTIONS_PRM);
  2159. num_actions = uverbs_attr_ptr_get_array_size(
  2160. attrs, MLX5_IB_ATTR_CREATE_MODIFY_HEADER_ACTIONS_PRM,
  2161. MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto));
  2162. if (num_actions < 0)
  2163. return num_actions;
  2164. ret = uverbs_get_const(&ft_type, attrs,
  2165. MLX5_IB_ATTR_CREATE_MODIFY_HEADER_FT_TYPE);
  2166. if (ret)
  2167. return ret;
  2168. action = mlx5_ib_create_modify_header(mdev, ft_type, num_actions, in);
  2169. if (IS_ERR(action))
  2170. return PTR_ERR(action);
  2171. uverbs_flow_action_fill_action(action, uobj, &mdev->ib_dev,
  2172. IB_FLOW_ACTION_UNSPECIFIED);
  2173. return 0;
  2174. }
  2175. static bool mlx5_ib_flow_action_packet_reformat_valid(struct mlx5_ib_dev *ibdev,
  2176. u8 packet_reformat_type,
  2177. u8 ft_type)
  2178. {
  2179. switch (packet_reformat_type) {
  2180. case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL:
  2181. if (ft_type == MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_TX)
  2182. return MLX5_CAP_FLOWTABLE(ibdev->mdev,
  2183. encap_general_header);
  2184. break;
  2185. case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL:
  2186. if (ft_type == MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_TX)
  2187. return MLX5_CAP_FLOWTABLE_NIC_TX(ibdev->mdev,
  2188. reformat_l2_to_l3_tunnel);
  2189. break;
  2190. case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_TO_L2:
  2191. if (ft_type == MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_RX)
  2192. return MLX5_CAP_FLOWTABLE_NIC_RX(ibdev->mdev,
  2193. reformat_l3_tunnel_to_l2);
  2194. break;
  2195. case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2:
  2196. if (ft_type == MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_RX)
  2197. return MLX5_CAP_FLOWTABLE_NIC_RX(ibdev->mdev, decap);
  2198. break;
  2199. default:
  2200. break;
  2201. }
  2202. return false;
  2203. }
  2204. static int mlx5_ib_dv_to_prm_packet_reforamt_type(u8 dv_prt, u8 *prm_prt)
  2205. {
  2206. switch (dv_prt) {
  2207. case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL:
  2208. *prm_prt = MLX5_REFORMAT_TYPE_L2_TO_L2_TUNNEL;
  2209. break;
  2210. case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_TO_L2:
  2211. *prm_prt = MLX5_REFORMAT_TYPE_L3_TUNNEL_TO_L2;
  2212. break;
  2213. case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL:
  2214. *prm_prt = MLX5_REFORMAT_TYPE_L2_TO_L3_TUNNEL;
  2215. break;
  2216. default:
  2217. return -EINVAL;
  2218. }
  2219. return 0;
  2220. }
  2221. static int mlx5_ib_flow_action_create_packet_reformat_ctx(
  2222. struct mlx5_ib_dev *dev,
  2223. struct mlx5_ib_flow_action *maction,
  2224. u8 ft_type, u8 dv_prt,
  2225. void *in, size_t len)
  2226. {
  2227. struct mlx5_pkt_reformat_params reformat_params;
  2228. enum mlx5_flow_namespace_type namespace;
  2229. u8 prm_prt;
  2230. int ret;
  2231. ret = mlx5_ib_ft_type_to_namespace(ft_type, &namespace);
  2232. if (ret)
  2233. return ret;
  2234. ret = mlx5_ib_dv_to_prm_packet_reforamt_type(dv_prt, &prm_prt);
  2235. if (ret)
  2236. return ret;
  2237. memset(&reformat_params, 0, sizeof(reformat_params));
  2238. reformat_params.type = prm_prt;
  2239. reformat_params.size = len;
  2240. reformat_params.data = in;
  2241. maction->flow_action_raw.pkt_reformat =
  2242. mlx5_packet_reformat_alloc(dev->mdev, &reformat_params,
  2243. namespace);
  2244. if (IS_ERR(maction->flow_action_raw.pkt_reformat)) {
  2245. ret = PTR_ERR(maction->flow_action_raw.pkt_reformat);
  2246. return ret;
  2247. }
  2248. maction->flow_action_raw.sub_type =
  2249. MLX5_IB_FLOW_ACTION_PACKET_REFORMAT;
  2250. maction->flow_action_raw.dev = dev;
  2251. return 0;
  2252. }
  2253. static int UVERBS_HANDLER(MLX5_IB_METHOD_FLOW_ACTION_CREATE_PACKET_REFORMAT)(
  2254. struct uverbs_attr_bundle *attrs)
  2255. {
  2256. struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs,
  2257. MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_HANDLE);
  2258. struct mlx5_ib_dev *mdev = mlx5_udata_to_mdev(&attrs->driver_udata);
  2259. enum mlx5_ib_uapi_flow_action_packet_reformat_type dv_prt;
  2260. enum mlx5_ib_uapi_flow_table_type ft_type;
  2261. struct mlx5_ib_flow_action *maction;
  2262. int ret;
  2263. ret = uverbs_get_const(&ft_type, attrs,
  2264. MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_FT_TYPE);
  2265. if (ret)
  2266. return ret;
  2267. ret = uverbs_get_const(&dv_prt, attrs,
  2268. MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_TYPE);
  2269. if (ret)
  2270. return ret;
  2271. if (!mlx5_ib_flow_action_packet_reformat_valid(mdev, dv_prt, ft_type))
  2272. return -EOPNOTSUPP;
  2273. maction = kzalloc(sizeof(*maction), GFP_KERNEL);
  2274. if (!maction)
  2275. return -ENOMEM;
  2276. if (dv_prt ==
  2277. MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2) {
  2278. maction->flow_action_raw.sub_type =
  2279. MLX5_IB_FLOW_ACTION_DECAP;
  2280. maction->flow_action_raw.dev = mdev;
  2281. } else {
  2282. void *in;
  2283. int len;
  2284. in = uverbs_attr_get_alloced_ptr(attrs,
  2285. MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_DATA_BUF);
  2286. if (IS_ERR(in)) {
  2287. ret = PTR_ERR(in);
  2288. goto free_maction;
  2289. }
  2290. len = uverbs_attr_get_len(attrs,
  2291. MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_DATA_BUF);
  2292. ret = mlx5_ib_flow_action_create_packet_reformat_ctx(mdev,
  2293. maction, ft_type, dv_prt, in, len);
  2294. if (ret)
  2295. goto free_maction;
  2296. }
  2297. uverbs_flow_action_fill_action(&maction->ib_action, uobj, &mdev->ib_dev,
  2298. IB_FLOW_ACTION_UNSPECIFIED);
  2299. return 0;
  2300. free_maction:
  2301. kfree(maction);
  2302. return ret;
  2303. }
  2304. DECLARE_UVERBS_NAMED_METHOD(
  2305. MLX5_IB_METHOD_CREATE_FLOW,
  2306. UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_HANDLE,
  2307. UVERBS_OBJECT_FLOW,
  2308. UVERBS_ACCESS_NEW,
  2309. UA_MANDATORY),
  2310. UVERBS_ATTR_PTR_IN(
  2311. MLX5_IB_ATTR_CREATE_FLOW_MATCH_VALUE,
  2312. UVERBS_ATTR_SIZE(1, sizeof(struct mlx5_ib_match_params)),
  2313. UA_MANDATORY,
  2314. UA_ALLOC_AND_COPY),
  2315. UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_MATCHER,
  2316. MLX5_IB_OBJECT_FLOW_MATCHER,
  2317. UVERBS_ACCESS_READ,
  2318. UA_MANDATORY),
  2319. UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_DEST_QP,
  2320. UVERBS_OBJECT_QP,
  2321. UVERBS_ACCESS_READ),
  2322. UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_DEST_DEVX,
  2323. MLX5_IB_OBJECT_DEVX_OBJ,
  2324. UVERBS_ACCESS_READ),
  2325. UVERBS_ATTR_IDRS_ARR(MLX5_IB_ATTR_CREATE_FLOW_ARR_FLOW_ACTIONS,
  2326. UVERBS_OBJECT_FLOW_ACTION,
  2327. UVERBS_ACCESS_READ, 1,
  2328. MLX5_IB_CREATE_FLOW_MAX_FLOW_ACTIONS,
  2329. UA_OPTIONAL),
  2330. UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_CREATE_FLOW_TAG,
  2331. UVERBS_ATTR_TYPE(u32),
  2332. UA_OPTIONAL),
  2333. UVERBS_ATTR_IDRS_ARR(MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX,
  2334. MLX5_IB_OBJECT_DEVX_OBJ,
  2335. UVERBS_ACCESS_READ, 1, 1,
  2336. UA_OPTIONAL),
  2337. UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX_OFFSET,
  2338. UVERBS_ATTR_MIN_SIZE(sizeof(u32)),
  2339. UA_OPTIONAL,
  2340. UA_ALLOC_AND_COPY),
  2341. UVERBS_ATTR_FLAGS_IN(MLX5_IB_ATTR_CREATE_FLOW_FLAGS,
  2342. enum mlx5_ib_create_flow_flags,
  2343. UA_OPTIONAL));
  2344. DECLARE_UVERBS_NAMED_METHOD_DESTROY(
  2345. MLX5_IB_METHOD_DESTROY_FLOW,
  2346. UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_HANDLE,
  2347. UVERBS_OBJECT_FLOW,
  2348. UVERBS_ACCESS_DESTROY,
  2349. UA_MANDATORY));
  2350. ADD_UVERBS_METHODS(mlx5_ib_fs,
  2351. UVERBS_OBJECT_FLOW,
  2352. &UVERBS_METHOD(MLX5_IB_METHOD_CREATE_FLOW),
  2353. &UVERBS_METHOD(MLX5_IB_METHOD_DESTROY_FLOW));
  2354. DECLARE_UVERBS_NAMED_METHOD(
  2355. MLX5_IB_METHOD_FLOW_ACTION_CREATE_MODIFY_HEADER,
  2356. UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_MODIFY_HEADER_HANDLE,
  2357. UVERBS_OBJECT_FLOW_ACTION,
  2358. UVERBS_ACCESS_NEW,
  2359. UA_MANDATORY),
  2360. UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_CREATE_MODIFY_HEADER_ACTIONS_PRM,
  2361. UVERBS_ATTR_MIN_SIZE(MLX5_UN_SZ_BYTES(
  2362. set_add_copy_action_in_auto)),
  2363. UA_MANDATORY,
  2364. UA_ALLOC_AND_COPY),
  2365. UVERBS_ATTR_CONST_IN(MLX5_IB_ATTR_CREATE_MODIFY_HEADER_FT_TYPE,
  2366. enum mlx5_ib_uapi_flow_table_type,
  2367. UA_MANDATORY));
  2368. DECLARE_UVERBS_NAMED_METHOD(
  2369. MLX5_IB_METHOD_FLOW_ACTION_CREATE_PACKET_REFORMAT,
  2370. UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_HANDLE,
  2371. UVERBS_OBJECT_FLOW_ACTION,
  2372. UVERBS_ACCESS_NEW,
  2373. UA_MANDATORY),
  2374. UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_DATA_BUF,
  2375. UVERBS_ATTR_MIN_SIZE(1),
  2376. UA_ALLOC_AND_COPY,
  2377. UA_OPTIONAL),
  2378. UVERBS_ATTR_CONST_IN(MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_TYPE,
  2379. enum mlx5_ib_uapi_flow_action_packet_reformat_type,
  2380. UA_MANDATORY),
  2381. UVERBS_ATTR_CONST_IN(MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_FT_TYPE,
  2382. enum mlx5_ib_uapi_flow_table_type,
  2383. UA_MANDATORY));
  2384. ADD_UVERBS_METHODS(
  2385. mlx5_ib_flow_actions,
  2386. UVERBS_OBJECT_FLOW_ACTION,
  2387. &UVERBS_METHOD(MLX5_IB_METHOD_FLOW_ACTION_CREATE_MODIFY_HEADER),
  2388. &UVERBS_METHOD(MLX5_IB_METHOD_FLOW_ACTION_CREATE_PACKET_REFORMAT));
  2389. DECLARE_UVERBS_NAMED_METHOD(
  2390. MLX5_IB_METHOD_FLOW_MATCHER_CREATE,
  2391. UVERBS_ATTR_IDR(MLX5_IB_ATTR_FLOW_MATCHER_CREATE_HANDLE,
  2392. MLX5_IB_OBJECT_FLOW_MATCHER,
  2393. UVERBS_ACCESS_NEW,
  2394. UA_MANDATORY),
  2395. UVERBS_ATTR_PTR_IN(
  2396. MLX5_IB_ATTR_FLOW_MATCHER_MATCH_MASK,
  2397. UVERBS_ATTR_SIZE(1, sizeof(struct mlx5_ib_match_params)),
  2398. UA_MANDATORY),
  2399. UVERBS_ATTR_ENUM_IN(MLX5_IB_ATTR_FLOW_MATCHER_FLOW_TYPE,
  2400. mlx5_ib_flow_type,
  2401. UA_MANDATORY),
  2402. UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_FLOW_MATCHER_MATCH_CRITERIA,
  2403. UVERBS_ATTR_TYPE(u8),
  2404. UA_MANDATORY),
  2405. UVERBS_ATTR_FLAGS_IN(MLX5_IB_ATTR_FLOW_MATCHER_FLOW_FLAGS,
  2406. enum ib_flow_flags,
  2407. UA_OPTIONAL),
  2408. UVERBS_ATTR_CONST_IN(MLX5_IB_ATTR_FLOW_MATCHER_FT_TYPE,
  2409. enum mlx5_ib_uapi_flow_table_type,
  2410. UA_OPTIONAL));
  2411. DECLARE_UVERBS_NAMED_METHOD_DESTROY(
  2412. MLX5_IB_METHOD_FLOW_MATCHER_DESTROY,
  2413. UVERBS_ATTR_IDR(MLX5_IB_ATTR_FLOW_MATCHER_DESTROY_HANDLE,
  2414. MLX5_IB_OBJECT_FLOW_MATCHER,
  2415. UVERBS_ACCESS_DESTROY,
  2416. UA_MANDATORY));
  2417. DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_FLOW_MATCHER,
  2418. UVERBS_TYPE_ALLOC_IDR(flow_matcher_cleanup),
  2419. &UVERBS_METHOD(MLX5_IB_METHOD_FLOW_MATCHER_CREATE),
  2420. &UVERBS_METHOD(MLX5_IB_METHOD_FLOW_MATCHER_DESTROY));
  2421. DECLARE_UVERBS_NAMED_METHOD(
  2422. MLX5_IB_METHOD_STEERING_ANCHOR_CREATE,
  2423. UVERBS_ATTR_IDR(MLX5_IB_ATTR_STEERING_ANCHOR_CREATE_HANDLE,
  2424. MLX5_IB_OBJECT_STEERING_ANCHOR,
  2425. UVERBS_ACCESS_NEW,
  2426. UA_MANDATORY),
  2427. UVERBS_ATTR_CONST_IN(MLX5_IB_ATTR_STEERING_ANCHOR_FT_TYPE,
  2428. enum mlx5_ib_uapi_flow_table_type,
  2429. UA_MANDATORY),
  2430. UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_STEERING_ANCHOR_PRIORITY,
  2431. UVERBS_ATTR_TYPE(u16),
  2432. UA_MANDATORY),
  2433. UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_STEERING_ANCHOR_FT_ID,
  2434. UVERBS_ATTR_TYPE(u32),
  2435. UA_MANDATORY));
  2436. DECLARE_UVERBS_NAMED_METHOD_DESTROY(
  2437. MLX5_IB_METHOD_STEERING_ANCHOR_DESTROY,
  2438. UVERBS_ATTR_IDR(MLX5_IB_ATTR_STEERING_ANCHOR_DESTROY_HANDLE,
  2439. MLX5_IB_OBJECT_STEERING_ANCHOR,
  2440. UVERBS_ACCESS_DESTROY,
  2441. UA_MANDATORY));
  2442. DECLARE_UVERBS_NAMED_OBJECT(
  2443. MLX5_IB_OBJECT_STEERING_ANCHOR,
  2444. UVERBS_TYPE_ALLOC_IDR(steering_anchor_cleanup),
  2445. &UVERBS_METHOD(MLX5_IB_METHOD_STEERING_ANCHOR_CREATE),
  2446. &UVERBS_METHOD(MLX5_IB_METHOD_STEERING_ANCHOR_DESTROY));
  2447. const struct uapi_definition mlx5_ib_flow_defs[] = {
  2448. UAPI_DEF_CHAIN_OBJ_TREE_NAMED(
  2449. MLX5_IB_OBJECT_FLOW_MATCHER),
  2450. UAPI_DEF_CHAIN_OBJ_TREE(
  2451. UVERBS_OBJECT_FLOW,
  2452. &mlx5_ib_fs),
  2453. UAPI_DEF_CHAIN_OBJ_TREE(UVERBS_OBJECT_FLOW_ACTION,
  2454. &mlx5_ib_flow_actions),
  2455. UAPI_DEF_CHAIN_OBJ_TREE_NAMED(
  2456. MLX5_IB_OBJECT_STEERING_ANCHOR,
  2457. UAPI_DEF_IS_OBJ_SUPPORTED(mlx5_ib_shared_ft_allowed)),
  2458. {},
  2459. };
  2460. static const struct ib_device_ops flow_ops = {
  2461. .create_flow = mlx5_ib_create_flow,
  2462. .destroy_flow = mlx5_ib_destroy_flow,
  2463. .destroy_flow_action = mlx5_ib_destroy_flow_action,
  2464. };
  2465. int mlx5_ib_fs_init(struct mlx5_ib_dev *dev)
  2466. {
  2467. dev->flow_db = kzalloc(sizeof(*dev->flow_db), GFP_KERNEL);
  2468. if (!dev->flow_db)
  2469. return -ENOMEM;
  2470. mutex_init(&dev->flow_db->lock);
  2471. ib_set_device_ops(&dev->ib_dev, &flow_ops);
  2472. return 0;
  2473. }