trap.c 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
  4. * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com>
  5. */
  6. #include <trace/events/devlink.h>
  7. #include "devl_internal.h"
  8. struct devlink_stats {
  9. u64_stats_t rx_bytes;
  10. u64_stats_t rx_packets;
  11. struct u64_stats_sync syncp;
  12. };
  13. /**
  14. * struct devlink_trap_policer_item - Packet trap policer attributes.
  15. * @policer: Immutable packet trap policer attributes.
  16. * @rate: Rate in packets / sec.
  17. * @burst: Burst size in packets.
  18. * @list: trap_policer_list member.
  19. *
  20. * Describes packet trap policer attributes. Created by devlink during trap
  21. * policer registration.
  22. */
  23. struct devlink_trap_policer_item {
  24. const struct devlink_trap_policer *policer;
  25. u64 rate;
  26. u64 burst;
  27. struct list_head list;
  28. };
  29. /**
  30. * struct devlink_trap_group_item - Packet trap group attributes.
  31. * @group: Immutable packet trap group attributes.
  32. * @policer_item: Associated policer item. Can be NULL.
  33. * @list: trap_group_list member.
  34. * @stats: Trap group statistics.
  35. *
  36. * Describes packet trap group attributes. Created by devlink during trap
  37. * group registration.
  38. */
  39. struct devlink_trap_group_item {
  40. const struct devlink_trap_group *group;
  41. struct devlink_trap_policer_item *policer_item;
  42. struct list_head list;
  43. struct devlink_stats __percpu *stats;
  44. };
  45. /**
  46. * struct devlink_trap_item - Packet trap attributes.
  47. * @trap: Immutable packet trap attributes.
  48. * @group_item: Associated group item.
  49. * @list: trap_list member.
  50. * @action: Trap action.
  51. * @stats: Trap statistics.
  52. * @priv: Driver private information.
  53. *
  54. * Describes both mutable and immutable packet trap attributes. Created by
  55. * devlink during trap registration and used for all trap related operations.
  56. */
  57. struct devlink_trap_item {
  58. const struct devlink_trap *trap;
  59. struct devlink_trap_group_item *group_item;
  60. struct list_head list;
  61. enum devlink_trap_action action;
  62. struct devlink_stats __percpu *stats;
  63. void *priv;
  64. };
  65. static struct devlink_trap_policer_item *
  66. devlink_trap_policer_item_lookup(struct devlink *devlink, u32 id)
  67. {
  68. struct devlink_trap_policer_item *policer_item;
  69. list_for_each_entry(policer_item, &devlink->trap_policer_list, list) {
  70. if (policer_item->policer->id == id)
  71. return policer_item;
  72. }
  73. return NULL;
  74. }
  75. static struct devlink_trap_item *
  76. devlink_trap_item_lookup(struct devlink *devlink, const char *name)
  77. {
  78. struct devlink_trap_item *trap_item;
  79. list_for_each_entry(trap_item, &devlink->trap_list, list) {
  80. if (!strcmp(trap_item->trap->name, name))
  81. return trap_item;
  82. }
  83. return NULL;
  84. }
  85. static struct devlink_trap_item *
  86. devlink_trap_item_get_from_info(struct devlink *devlink,
  87. struct genl_info *info)
  88. {
  89. struct nlattr *attr;
  90. if (!info->attrs[DEVLINK_ATTR_TRAP_NAME])
  91. return NULL;
  92. attr = info->attrs[DEVLINK_ATTR_TRAP_NAME];
  93. return devlink_trap_item_lookup(devlink, nla_data(attr));
  94. }
  95. static int
  96. devlink_trap_action_get_from_info(struct genl_info *info,
  97. enum devlink_trap_action *p_trap_action)
  98. {
  99. u8 val;
  100. val = nla_get_u8(info->attrs[DEVLINK_ATTR_TRAP_ACTION]);
  101. switch (val) {
  102. case DEVLINK_TRAP_ACTION_DROP:
  103. case DEVLINK_TRAP_ACTION_TRAP:
  104. case DEVLINK_TRAP_ACTION_MIRROR:
  105. *p_trap_action = val;
  106. break;
  107. default:
  108. return -EINVAL;
  109. }
  110. return 0;
  111. }
  112. static int devlink_trap_metadata_put(struct sk_buff *msg,
  113. const struct devlink_trap *trap)
  114. {
  115. struct nlattr *attr;
  116. attr = nla_nest_start(msg, DEVLINK_ATTR_TRAP_METADATA);
  117. if (!attr)
  118. return -EMSGSIZE;
  119. if ((trap->metadata_cap & DEVLINK_TRAP_METADATA_TYPE_F_IN_PORT) &&
  120. nla_put_flag(msg, DEVLINK_ATTR_TRAP_METADATA_TYPE_IN_PORT))
  121. goto nla_put_failure;
  122. if ((trap->metadata_cap & DEVLINK_TRAP_METADATA_TYPE_F_FA_COOKIE) &&
  123. nla_put_flag(msg, DEVLINK_ATTR_TRAP_METADATA_TYPE_FA_COOKIE))
  124. goto nla_put_failure;
  125. nla_nest_end(msg, attr);
  126. return 0;
  127. nla_put_failure:
  128. nla_nest_cancel(msg, attr);
  129. return -EMSGSIZE;
  130. }
  131. static void devlink_trap_stats_read(struct devlink_stats __percpu *trap_stats,
  132. struct devlink_stats *stats)
  133. {
  134. int i;
  135. memset(stats, 0, sizeof(*stats));
  136. for_each_possible_cpu(i) {
  137. struct devlink_stats *cpu_stats;
  138. u64 rx_packets, rx_bytes;
  139. unsigned int start;
  140. cpu_stats = per_cpu_ptr(trap_stats, i);
  141. do {
  142. start = u64_stats_fetch_begin(&cpu_stats->syncp);
  143. rx_packets = u64_stats_read(&cpu_stats->rx_packets);
  144. rx_bytes = u64_stats_read(&cpu_stats->rx_bytes);
  145. } while (u64_stats_fetch_retry(&cpu_stats->syncp, start));
  146. u64_stats_add(&stats->rx_packets, rx_packets);
  147. u64_stats_add(&stats->rx_bytes, rx_bytes);
  148. }
  149. }
  150. static int
  151. devlink_trap_group_stats_put(struct sk_buff *msg,
  152. struct devlink_stats __percpu *trap_stats)
  153. {
  154. struct devlink_stats stats;
  155. struct nlattr *attr;
  156. devlink_trap_stats_read(trap_stats, &stats);
  157. attr = nla_nest_start(msg, DEVLINK_ATTR_STATS);
  158. if (!attr)
  159. return -EMSGSIZE;
  160. if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_PACKETS,
  161. u64_stats_read(&stats.rx_packets),
  162. DEVLINK_ATTR_PAD))
  163. goto nla_put_failure;
  164. if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_BYTES,
  165. u64_stats_read(&stats.rx_bytes),
  166. DEVLINK_ATTR_PAD))
  167. goto nla_put_failure;
  168. nla_nest_end(msg, attr);
  169. return 0;
  170. nla_put_failure:
  171. nla_nest_cancel(msg, attr);
  172. return -EMSGSIZE;
  173. }
  174. static int devlink_trap_stats_put(struct sk_buff *msg, struct devlink *devlink,
  175. const struct devlink_trap_item *trap_item)
  176. {
  177. struct devlink_stats stats;
  178. struct nlattr *attr;
  179. u64 drops = 0;
  180. int err;
  181. if (devlink->ops->trap_drop_counter_get) {
  182. err = devlink->ops->trap_drop_counter_get(devlink,
  183. trap_item->trap,
  184. &drops);
  185. if (err)
  186. return err;
  187. }
  188. devlink_trap_stats_read(trap_item->stats, &stats);
  189. attr = nla_nest_start(msg, DEVLINK_ATTR_STATS);
  190. if (!attr)
  191. return -EMSGSIZE;
  192. if (devlink->ops->trap_drop_counter_get &&
  193. nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_DROPPED, drops,
  194. DEVLINK_ATTR_PAD))
  195. goto nla_put_failure;
  196. if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_PACKETS,
  197. u64_stats_read(&stats.rx_packets),
  198. DEVLINK_ATTR_PAD))
  199. goto nla_put_failure;
  200. if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_BYTES,
  201. u64_stats_read(&stats.rx_bytes),
  202. DEVLINK_ATTR_PAD))
  203. goto nla_put_failure;
  204. nla_nest_end(msg, attr);
  205. return 0;
  206. nla_put_failure:
  207. nla_nest_cancel(msg, attr);
  208. return -EMSGSIZE;
  209. }
  210. static int devlink_nl_trap_fill(struct sk_buff *msg, struct devlink *devlink,
  211. const struct devlink_trap_item *trap_item,
  212. enum devlink_command cmd, u32 portid, u32 seq,
  213. int flags)
  214. {
  215. struct devlink_trap_group_item *group_item = trap_item->group_item;
  216. void *hdr;
  217. int err;
  218. hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
  219. if (!hdr)
  220. return -EMSGSIZE;
  221. if (devlink_nl_put_handle(msg, devlink))
  222. goto nla_put_failure;
  223. if (nla_put_string(msg, DEVLINK_ATTR_TRAP_GROUP_NAME,
  224. group_item->group->name))
  225. goto nla_put_failure;
  226. if (nla_put_string(msg, DEVLINK_ATTR_TRAP_NAME, trap_item->trap->name))
  227. goto nla_put_failure;
  228. if (nla_put_u8(msg, DEVLINK_ATTR_TRAP_TYPE, trap_item->trap->type))
  229. goto nla_put_failure;
  230. if (trap_item->trap->generic &&
  231. nla_put_flag(msg, DEVLINK_ATTR_TRAP_GENERIC))
  232. goto nla_put_failure;
  233. if (nla_put_u8(msg, DEVLINK_ATTR_TRAP_ACTION, trap_item->action))
  234. goto nla_put_failure;
  235. err = devlink_trap_metadata_put(msg, trap_item->trap);
  236. if (err)
  237. goto nla_put_failure;
  238. err = devlink_trap_stats_put(msg, devlink, trap_item);
  239. if (err)
  240. goto nla_put_failure;
  241. genlmsg_end(msg, hdr);
  242. return 0;
  243. nla_put_failure:
  244. genlmsg_cancel(msg, hdr);
  245. return -EMSGSIZE;
  246. }
  247. int devlink_nl_trap_get_doit(struct sk_buff *skb, struct genl_info *info)
  248. {
  249. struct netlink_ext_ack *extack = info->extack;
  250. struct devlink *devlink = info->user_ptr[0];
  251. struct devlink_trap_item *trap_item;
  252. struct sk_buff *msg;
  253. int err;
  254. if (list_empty(&devlink->trap_list))
  255. return -EOPNOTSUPP;
  256. trap_item = devlink_trap_item_get_from_info(devlink, info);
  257. if (!trap_item) {
  258. NL_SET_ERR_MSG(extack, "Device did not register this trap");
  259. return -ENOENT;
  260. }
  261. msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
  262. if (!msg)
  263. return -ENOMEM;
  264. err = devlink_nl_trap_fill(msg, devlink, trap_item,
  265. DEVLINK_CMD_TRAP_NEW, info->snd_portid,
  266. info->snd_seq, 0);
  267. if (err)
  268. goto err_trap_fill;
  269. return genlmsg_reply(msg, info);
  270. err_trap_fill:
  271. nlmsg_free(msg);
  272. return err;
  273. }
  274. static int devlink_nl_trap_get_dump_one(struct sk_buff *msg,
  275. struct devlink *devlink,
  276. struct netlink_callback *cb, int flags)
  277. {
  278. struct devlink_nl_dump_state *state = devlink_dump_state(cb);
  279. struct devlink_trap_item *trap_item;
  280. int idx = 0;
  281. int err = 0;
  282. list_for_each_entry(trap_item, &devlink->trap_list, list) {
  283. if (idx < state->idx) {
  284. idx++;
  285. continue;
  286. }
  287. err = devlink_nl_trap_fill(msg, devlink, trap_item,
  288. DEVLINK_CMD_TRAP_NEW,
  289. NETLINK_CB(cb->skb).portid,
  290. cb->nlh->nlmsg_seq, flags);
  291. if (err) {
  292. state->idx = idx;
  293. break;
  294. }
  295. idx++;
  296. }
  297. return err;
  298. }
  299. int devlink_nl_trap_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
  300. {
  301. return devlink_nl_dumpit(skb, cb, devlink_nl_trap_get_dump_one);
  302. }
  303. static int __devlink_trap_action_set(struct devlink *devlink,
  304. struct devlink_trap_item *trap_item,
  305. enum devlink_trap_action trap_action,
  306. struct netlink_ext_ack *extack)
  307. {
  308. int err;
  309. if (trap_item->action != trap_action &&
  310. trap_item->trap->type != DEVLINK_TRAP_TYPE_DROP) {
  311. NL_SET_ERR_MSG(extack, "Cannot change action of non-drop traps. Skipping");
  312. return 0;
  313. }
  314. err = devlink->ops->trap_action_set(devlink, trap_item->trap,
  315. trap_action, extack);
  316. if (err)
  317. return err;
  318. trap_item->action = trap_action;
  319. return 0;
  320. }
  321. static int devlink_trap_action_set(struct devlink *devlink,
  322. struct devlink_trap_item *trap_item,
  323. struct genl_info *info)
  324. {
  325. enum devlink_trap_action trap_action;
  326. int err;
  327. if (!info->attrs[DEVLINK_ATTR_TRAP_ACTION])
  328. return 0;
  329. err = devlink_trap_action_get_from_info(info, &trap_action);
  330. if (err) {
  331. NL_SET_ERR_MSG(info->extack, "Invalid trap action");
  332. return -EINVAL;
  333. }
  334. return __devlink_trap_action_set(devlink, trap_item, trap_action,
  335. info->extack);
  336. }
  337. int devlink_nl_trap_set_doit(struct sk_buff *skb, struct genl_info *info)
  338. {
  339. struct netlink_ext_ack *extack = info->extack;
  340. struct devlink *devlink = info->user_ptr[0];
  341. struct devlink_trap_item *trap_item;
  342. if (list_empty(&devlink->trap_list))
  343. return -EOPNOTSUPP;
  344. trap_item = devlink_trap_item_get_from_info(devlink, info);
  345. if (!trap_item) {
  346. NL_SET_ERR_MSG(extack, "Device did not register this trap");
  347. return -ENOENT;
  348. }
  349. return devlink_trap_action_set(devlink, trap_item, info);
  350. }
  351. static struct devlink_trap_group_item *
  352. devlink_trap_group_item_lookup(struct devlink *devlink, const char *name)
  353. {
  354. struct devlink_trap_group_item *group_item;
  355. list_for_each_entry(group_item, &devlink->trap_group_list, list) {
  356. if (!strcmp(group_item->group->name, name))
  357. return group_item;
  358. }
  359. return NULL;
  360. }
  361. static struct devlink_trap_group_item *
  362. devlink_trap_group_item_lookup_by_id(struct devlink *devlink, u16 id)
  363. {
  364. struct devlink_trap_group_item *group_item;
  365. list_for_each_entry(group_item, &devlink->trap_group_list, list) {
  366. if (group_item->group->id == id)
  367. return group_item;
  368. }
  369. return NULL;
  370. }
  371. static struct devlink_trap_group_item *
  372. devlink_trap_group_item_get_from_info(struct devlink *devlink,
  373. struct genl_info *info)
  374. {
  375. char *name;
  376. if (!info->attrs[DEVLINK_ATTR_TRAP_GROUP_NAME])
  377. return NULL;
  378. name = nla_data(info->attrs[DEVLINK_ATTR_TRAP_GROUP_NAME]);
  379. return devlink_trap_group_item_lookup(devlink, name);
  380. }
  381. static int
  382. devlink_nl_trap_group_fill(struct sk_buff *msg, struct devlink *devlink,
  383. const struct devlink_trap_group_item *group_item,
  384. enum devlink_command cmd, u32 portid, u32 seq,
  385. int flags)
  386. {
  387. void *hdr;
  388. int err;
  389. hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
  390. if (!hdr)
  391. return -EMSGSIZE;
  392. if (devlink_nl_put_handle(msg, devlink))
  393. goto nla_put_failure;
  394. if (nla_put_string(msg, DEVLINK_ATTR_TRAP_GROUP_NAME,
  395. group_item->group->name))
  396. goto nla_put_failure;
  397. if (group_item->group->generic &&
  398. nla_put_flag(msg, DEVLINK_ATTR_TRAP_GENERIC))
  399. goto nla_put_failure;
  400. if (group_item->policer_item &&
  401. nla_put_u32(msg, DEVLINK_ATTR_TRAP_POLICER_ID,
  402. group_item->policer_item->policer->id))
  403. goto nla_put_failure;
  404. err = devlink_trap_group_stats_put(msg, group_item->stats);
  405. if (err)
  406. goto nla_put_failure;
  407. genlmsg_end(msg, hdr);
  408. return 0;
  409. nla_put_failure:
  410. genlmsg_cancel(msg, hdr);
  411. return -EMSGSIZE;
  412. }
  413. int devlink_nl_trap_group_get_doit(struct sk_buff *skb, struct genl_info *info)
  414. {
  415. struct netlink_ext_ack *extack = info->extack;
  416. struct devlink *devlink = info->user_ptr[0];
  417. struct devlink_trap_group_item *group_item;
  418. struct sk_buff *msg;
  419. int err;
  420. if (list_empty(&devlink->trap_group_list))
  421. return -EOPNOTSUPP;
  422. group_item = devlink_trap_group_item_get_from_info(devlink, info);
  423. if (!group_item) {
  424. NL_SET_ERR_MSG(extack, "Device did not register this trap group");
  425. return -ENOENT;
  426. }
  427. msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
  428. if (!msg)
  429. return -ENOMEM;
  430. err = devlink_nl_trap_group_fill(msg, devlink, group_item,
  431. DEVLINK_CMD_TRAP_GROUP_NEW,
  432. info->snd_portid, info->snd_seq, 0);
  433. if (err)
  434. goto err_trap_group_fill;
  435. return genlmsg_reply(msg, info);
  436. err_trap_group_fill:
  437. nlmsg_free(msg);
  438. return err;
  439. }
  440. static int devlink_nl_trap_group_get_dump_one(struct sk_buff *msg,
  441. struct devlink *devlink,
  442. struct netlink_callback *cb,
  443. int flags)
  444. {
  445. struct devlink_nl_dump_state *state = devlink_dump_state(cb);
  446. struct devlink_trap_group_item *group_item;
  447. int idx = 0;
  448. int err = 0;
  449. list_for_each_entry(group_item, &devlink->trap_group_list, list) {
  450. if (idx < state->idx) {
  451. idx++;
  452. continue;
  453. }
  454. err = devlink_nl_trap_group_fill(msg, devlink, group_item,
  455. DEVLINK_CMD_TRAP_GROUP_NEW,
  456. NETLINK_CB(cb->skb).portid,
  457. cb->nlh->nlmsg_seq, flags);
  458. if (err) {
  459. state->idx = idx;
  460. break;
  461. }
  462. idx++;
  463. }
  464. return err;
  465. }
  466. int devlink_nl_trap_group_get_dumpit(struct sk_buff *skb,
  467. struct netlink_callback *cb)
  468. {
  469. return devlink_nl_dumpit(skb, cb, devlink_nl_trap_group_get_dump_one);
  470. }
  471. static int
  472. __devlink_trap_group_action_set(struct devlink *devlink,
  473. struct devlink_trap_group_item *group_item,
  474. enum devlink_trap_action trap_action,
  475. struct netlink_ext_ack *extack)
  476. {
  477. const char *group_name = group_item->group->name;
  478. struct devlink_trap_item *trap_item;
  479. int err;
  480. if (devlink->ops->trap_group_action_set) {
  481. err = devlink->ops->trap_group_action_set(devlink, group_item->group,
  482. trap_action, extack);
  483. if (err)
  484. return err;
  485. list_for_each_entry(trap_item, &devlink->trap_list, list) {
  486. if (strcmp(trap_item->group_item->group->name, group_name))
  487. continue;
  488. if (trap_item->action != trap_action &&
  489. trap_item->trap->type != DEVLINK_TRAP_TYPE_DROP)
  490. continue;
  491. trap_item->action = trap_action;
  492. }
  493. return 0;
  494. }
  495. list_for_each_entry(trap_item, &devlink->trap_list, list) {
  496. if (strcmp(trap_item->group_item->group->name, group_name))
  497. continue;
  498. err = __devlink_trap_action_set(devlink, trap_item,
  499. trap_action, extack);
  500. if (err)
  501. return err;
  502. }
  503. return 0;
  504. }
  505. static int
  506. devlink_trap_group_action_set(struct devlink *devlink,
  507. struct devlink_trap_group_item *group_item,
  508. struct genl_info *info, bool *p_modified)
  509. {
  510. enum devlink_trap_action trap_action;
  511. int err;
  512. if (!info->attrs[DEVLINK_ATTR_TRAP_ACTION])
  513. return 0;
  514. err = devlink_trap_action_get_from_info(info, &trap_action);
  515. if (err) {
  516. NL_SET_ERR_MSG(info->extack, "Invalid trap action");
  517. return -EINVAL;
  518. }
  519. err = __devlink_trap_group_action_set(devlink, group_item, trap_action,
  520. info->extack);
  521. if (err)
  522. return err;
  523. *p_modified = true;
  524. return 0;
  525. }
  526. static int devlink_trap_group_set(struct devlink *devlink,
  527. struct devlink_trap_group_item *group_item,
  528. struct genl_info *info)
  529. {
  530. struct devlink_trap_policer_item *policer_item;
  531. struct netlink_ext_ack *extack = info->extack;
  532. const struct devlink_trap_policer *policer;
  533. struct nlattr **attrs = info->attrs;
  534. u32 policer_id;
  535. int err;
  536. if (!attrs[DEVLINK_ATTR_TRAP_POLICER_ID])
  537. return 0;
  538. if (!devlink->ops->trap_group_set)
  539. return -EOPNOTSUPP;
  540. policer_id = nla_get_u32(attrs[DEVLINK_ATTR_TRAP_POLICER_ID]);
  541. policer_item = devlink_trap_policer_item_lookup(devlink, policer_id);
  542. if (policer_id && !policer_item) {
  543. NL_SET_ERR_MSG(extack, "Device did not register this trap policer");
  544. return -ENOENT;
  545. }
  546. policer = policer_item ? policer_item->policer : NULL;
  547. err = devlink->ops->trap_group_set(devlink, group_item->group, policer,
  548. extack);
  549. if (err)
  550. return err;
  551. group_item->policer_item = policer_item;
  552. return 0;
  553. }
  554. int devlink_nl_trap_group_set_doit(struct sk_buff *skb, struct genl_info *info)
  555. {
  556. struct netlink_ext_ack *extack = info->extack;
  557. struct devlink *devlink = info->user_ptr[0];
  558. struct devlink_trap_group_item *group_item;
  559. bool modified = false;
  560. int err;
  561. if (list_empty(&devlink->trap_group_list))
  562. return -EOPNOTSUPP;
  563. group_item = devlink_trap_group_item_get_from_info(devlink, info);
  564. if (!group_item) {
  565. NL_SET_ERR_MSG(extack, "Device did not register this trap group");
  566. return -ENOENT;
  567. }
  568. err = devlink_trap_group_action_set(devlink, group_item, info,
  569. &modified);
  570. if (err)
  571. return err;
  572. err = devlink_trap_group_set(devlink, group_item, info);
  573. if (err)
  574. goto err_trap_group_set;
  575. return 0;
  576. err_trap_group_set:
  577. if (modified)
  578. NL_SET_ERR_MSG(extack, "Trap group set failed, but some changes were committed already");
  579. return err;
  580. }
  581. static struct devlink_trap_policer_item *
  582. devlink_trap_policer_item_get_from_info(struct devlink *devlink,
  583. struct genl_info *info)
  584. {
  585. u32 id;
  586. if (!info->attrs[DEVLINK_ATTR_TRAP_POLICER_ID])
  587. return NULL;
  588. id = nla_get_u32(info->attrs[DEVLINK_ATTR_TRAP_POLICER_ID]);
  589. return devlink_trap_policer_item_lookup(devlink, id);
  590. }
  591. static int
  592. devlink_trap_policer_stats_put(struct sk_buff *msg, struct devlink *devlink,
  593. const struct devlink_trap_policer *policer)
  594. {
  595. struct nlattr *attr;
  596. u64 drops;
  597. int err;
  598. if (!devlink->ops->trap_policer_counter_get)
  599. return 0;
  600. err = devlink->ops->trap_policer_counter_get(devlink, policer, &drops);
  601. if (err)
  602. return err;
  603. attr = nla_nest_start(msg, DEVLINK_ATTR_STATS);
  604. if (!attr)
  605. return -EMSGSIZE;
  606. if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_DROPPED, drops,
  607. DEVLINK_ATTR_PAD))
  608. goto nla_put_failure;
  609. nla_nest_end(msg, attr);
  610. return 0;
  611. nla_put_failure:
  612. nla_nest_cancel(msg, attr);
  613. return -EMSGSIZE;
  614. }
  615. static int
  616. devlink_nl_trap_policer_fill(struct sk_buff *msg, struct devlink *devlink,
  617. const struct devlink_trap_policer_item *policer_item,
  618. enum devlink_command cmd, u32 portid, u32 seq,
  619. int flags)
  620. {
  621. void *hdr;
  622. int err;
  623. hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
  624. if (!hdr)
  625. return -EMSGSIZE;
  626. if (devlink_nl_put_handle(msg, devlink))
  627. goto nla_put_failure;
  628. if (nla_put_u32(msg, DEVLINK_ATTR_TRAP_POLICER_ID,
  629. policer_item->policer->id))
  630. goto nla_put_failure;
  631. if (nla_put_u64_64bit(msg, DEVLINK_ATTR_TRAP_POLICER_RATE,
  632. policer_item->rate, DEVLINK_ATTR_PAD))
  633. goto nla_put_failure;
  634. if (nla_put_u64_64bit(msg, DEVLINK_ATTR_TRAP_POLICER_BURST,
  635. policer_item->burst, DEVLINK_ATTR_PAD))
  636. goto nla_put_failure;
  637. err = devlink_trap_policer_stats_put(msg, devlink,
  638. policer_item->policer);
  639. if (err)
  640. goto nla_put_failure;
  641. genlmsg_end(msg, hdr);
  642. return 0;
  643. nla_put_failure:
  644. genlmsg_cancel(msg, hdr);
  645. return -EMSGSIZE;
  646. }
  647. int devlink_nl_trap_policer_get_doit(struct sk_buff *skb,
  648. struct genl_info *info)
  649. {
  650. struct devlink_trap_policer_item *policer_item;
  651. struct netlink_ext_ack *extack = info->extack;
  652. struct devlink *devlink = info->user_ptr[0];
  653. struct sk_buff *msg;
  654. int err;
  655. if (list_empty(&devlink->trap_policer_list))
  656. return -EOPNOTSUPP;
  657. policer_item = devlink_trap_policer_item_get_from_info(devlink, info);
  658. if (!policer_item) {
  659. NL_SET_ERR_MSG(extack, "Device did not register this trap policer");
  660. return -ENOENT;
  661. }
  662. msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
  663. if (!msg)
  664. return -ENOMEM;
  665. err = devlink_nl_trap_policer_fill(msg, devlink, policer_item,
  666. DEVLINK_CMD_TRAP_POLICER_NEW,
  667. info->snd_portid, info->snd_seq, 0);
  668. if (err)
  669. goto err_trap_policer_fill;
  670. return genlmsg_reply(msg, info);
  671. err_trap_policer_fill:
  672. nlmsg_free(msg);
  673. return err;
  674. }
  675. static int devlink_nl_trap_policer_get_dump_one(struct sk_buff *msg,
  676. struct devlink *devlink,
  677. struct netlink_callback *cb,
  678. int flags)
  679. {
  680. struct devlink_nl_dump_state *state = devlink_dump_state(cb);
  681. struct devlink_trap_policer_item *policer_item;
  682. int idx = 0;
  683. int err = 0;
  684. list_for_each_entry(policer_item, &devlink->trap_policer_list, list) {
  685. if (idx < state->idx) {
  686. idx++;
  687. continue;
  688. }
  689. err = devlink_nl_trap_policer_fill(msg, devlink, policer_item,
  690. DEVLINK_CMD_TRAP_POLICER_NEW,
  691. NETLINK_CB(cb->skb).portid,
  692. cb->nlh->nlmsg_seq, flags);
  693. if (err) {
  694. state->idx = idx;
  695. break;
  696. }
  697. idx++;
  698. }
  699. return err;
  700. }
  701. int devlink_nl_trap_policer_get_dumpit(struct sk_buff *skb,
  702. struct netlink_callback *cb)
  703. {
  704. return devlink_nl_dumpit(skb, cb, devlink_nl_trap_policer_get_dump_one);
  705. }
  706. static int
  707. devlink_trap_policer_set(struct devlink *devlink,
  708. struct devlink_trap_policer_item *policer_item,
  709. struct genl_info *info)
  710. {
  711. struct netlink_ext_ack *extack = info->extack;
  712. struct nlattr **attrs = info->attrs;
  713. u64 rate, burst;
  714. int err;
  715. rate = policer_item->rate;
  716. burst = policer_item->burst;
  717. if (attrs[DEVLINK_ATTR_TRAP_POLICER_RATE])
  718. rate = nla_get_u64(attrs[DEVLINK_ATTR_TRAP_POLICER_RATE]);
  719. if (attrs[DEVLINK_ATTR_TRAP_POLICER_BURST])
  720. burst = nla_get_u64(attrs[DEVLINK_ATTR_TRAP_POLICER_BURST]);
  721. if (rate < policer_item->policer->min_rate) {
  722. NL_SET_ERR_MSG(extack, "Policer rate lower than limit");
  723. return -EINVAL;
  724. }
  725. if (rate > policer_item->policer->max_rate) {
  726. NL_SET_ERR_MSG(extack, "Policer rate higher than limit");
  727. return -EINVAL;
  728. }
  729. if (burst < policer_item->policer->min_burst) {
  730. NL_SET_ERR_MSG(extack, "Policer burst size lower than limit");
  731. return -EINVAL;
  732. }
  733. if (burst > policer_item->policer->max_burst) {
  734. NL_SET_ERR_MSG(extack, "Policer burst size higher than limit");
  735. return -EINVAL;
  736. }
  737. err = devlink->ops->trap_policer_set(devlink, policer_item->policer,
  738. rate, burst, info->extack);
  739. if (err)
  740. return err;
  741. policer_item->rate = rate;
  742. policer_item->burst = burst;
  743. return 0;
  744. }
  745. int devlink_nl_trap_policer_set_doit(struct sk_buff *skb,
  746. struct genl_info *info)
  747. {
  748. struct devlink_trap_policer_item *policer_item;
  749. struct netlink_ext_ack *extack = info->extack;
  750. struct devlink *devlink = info->user_ptr[0];
  751. if (list_empty(&devlink->trap_policer_list))
  752. return -EOPNOTSUPP;
  753. if (!devlink->ops->trap_policer_set)
  754. return -EOPNOTSUPP;
  755. policer_item = devlink_trap_policer_item_get_from_info(devlink, info);
  756. if (!policer_item) {
  757. NL_SET_ERR_MSG(extack, "Device did not register this trap policer");
  758. return -ENOENT;
  759. }
  760. return devlink_trap_policer_set(devlink, policer_item, info);
  761. }
  762. #define DEVLINK_TRAP(_id, _type) \
  763. { \
  764. .type = DEVLINK_TRAP_TYPE_##_type, \
  765. .id = DEVLINK_TRAP_GENERIC_ID_##_id, \
  766. .name = DEVLINK_TRAP_GENERIC_NAME_##_id, \
  767. }
  768. static const struct devlink_trap devlink_trap_generic[] = {
  769. DEVLINK_TRAP(SMAC_MC, DROP),
  770. DEVLINK_TRAP(VLAN_TAG_MISMATCH, DROP),
  771. DEVLINK_TRAP(INGRESS_VLAN_FILTER, DROP),
  772. DEVLINK_TRAP(INGRESS_STP_FILTER, DROP),
  773. DEVLINK_TRAP(EMPTY_TX_LIST, DROP),
  774. DEVLINK_TRAP(PORT_LOOPBACK_FILTER, DROP),
  775. DEVLINK_TRAP(BLACKHOLE_ROUTE, DROP),
  776. DEVLINK_TRAP(TTL_ERROR, EXCEPTION),
  777. DEVLINK_TRAP(TAIL_DROP, DROP),
  778. DEVLINK_TRAP(NON_IP_PACKET, DROP),
  779. DEVLINK_TRAP(UC_DIP_MC_DMAC, DROP),
  780. DEVLINK_TRAP(DIP_LB, DROP),
  781. DEVLINK_TRAP(SIP_MC, DROP),
  782. DEVLINK_TRAP(SIP_LB, DROP),
  783. DEVLINK_TRAP(CORRUPTED_IP_HDR, DROP),
  784. DEVLINK_TRAP(IPV4_SIP_BC, DROP),
  785. DEVLINK_TRAP(IPV6_MC_DIP_RESERVED_SCOPE, DROP),
  786. DEVLINK_TRAP(IPV6_MC_DIP_INTERFACE_LOCAL_SCOPE, DROP),
  787. DEVLINK_TRAP(MTU_ERROR, EXCEPTION),
  788. DEVLINK_TRAP(UNRESOLVED_NEIGH, EXCEPTION),
  789. DEVLINK_TRAP(RPF, EXCEPTION),
  790. DEVLINK_TRAP(REJECT_ROUTE, EXCEPTION),
  791. DEVLINK_TRAP(IPV4_LPM_UNICAST_MISS, EXCEPTION),
  792. DEVLINK_TRAP(IPV6_LPM_UNICAST_MISS, EXCEPTION),
  793. DEVLINK_TRAP(NON_ROUTABLE, DROP),
  794. DEVLINK_TRAP(DECAP_ERROR, EXCEPTION),
  795. DEVLINK_TRAP(OVERLAY_SMAC_MC, DROP),
  796. DEVLINK_TRAP(INGRESS_FLOW_ACTION_DROP, DROP),
  797. DEVLINK_TRAP(EGRESS_FLOW_ACTION_DROP, DROP),
  798. DEVLINK_TRAP(STP, CONTROL),
  799. DEVLINK_TRAP(LACP, CONTROL),
  800. DEVLINK_TRAP(LLDP, CONTROL),
  801. DEVLINK_TRAP(IGMP_QUERY, CONTROL),
  802. DEVLINK_TRAP(IGMP_V1_REPORT, CONTROL),
  803. DEVLINK_TRAP(IGMP_V2_REPORT, CONTROL),
  804. DEVLINK_TRAP(IGMP_V3_REPORT, CONTROL),
  805. DEVLINK_TRAP(IGMP_V2_LEAVE, CONTROL),
  806. DEVLINK_TRAP(MLD_QUERY, CONTROL),
  807. DEVLINK_TRAP(MLD_V1_REPORT, CONTROL),
  808. DEVLINK_TRAP(MLD_V2_REPORT, CONTROL),
  809. DEVLINK_TRAP(MLD_V1_DONE, CONTROL),
  810. DEVLINK_TRAP(IPV4_DHCP, CONTROL),
  811. DEVLINK_TRAP(IPV6_DHCP, CONTROL),
  812. DEVLINK_TRAP(ARP_REQUEST, CONTROL),
  813. DEVLINK_TRAP(ARP_RESPONSE, CONTROL),
  814. DEVLINK_TRAP(ARP_OVERLAY, CONTROL),
  815. DEVLINK_TRAP(IPV6_NEIGH_SOLICIT, CONTROL),
  816. DEVLINK_TRAP(IPV6_NEIGH_ADVERT, CONTROL),
  817. DEVLINK_TRAP(IPV4_BFD, CONTROL),
  818. DEVLINK_TRAP(IPV6_BFD, CONTROL),
  819. DEVLINK_TRAP(IPV4_OSPF, CONTROL),
  820. DEVLINK_TRAP(IPV6_OSPF, CONTROL),
  821. DEVLINK_TRAP(IPV4_BGP, CONTROL),
  822. DEVLINK_TRAP(IPV6_BGP, CONTROL),
  823. DEVLINK_TRAP(IPV4_VRRP, CONTROL),
  824. DEVLINK_TRAP(IPV6_VRRP, CONTROL),
  825. DEVLINK_TRAP(IPV4_PIM, CONTROL),
  826. DEVLINK_TRAP(IPV6_PIM, CONTROL),
  827. DEVLINK_TRAP(UC_LB, CONTROL),
  828. DEVLINK_TRAP(LOCAL_ROUTE, CONTROL),
  829. DEVLINK_TRAP(EXTERNAL_ROUTE, CONTROL),
  830. DEVLINK_TRAP(IPV6_UC_DIP_LINK_LOCAL_SCOPE, CONTROL),
  831. DEVLINK_TRAP(IPV6_DIP_ALL_NODES, CONTROL),
  832. DEVLINK_TRAP(IPV6_DIP_ALL_ROUTERS, CONTROL),
  833. DEVLINK_TRAP(IPV6_ROUTER_SOLICIT, CONTROL),
  834. DEVLINK_TRAP(IPV6_ROUTER_ADVERT, CONTROL),
  835. DEVLINK_TRAP(IPV6_REDIRECT, CONTROL),
  836. DEVLINK_TRAP(IPV4_ROUTER_ALERT, CONTROL),
  837. DEVLINK_TRAP(IPV6_ROUTER_ALERT, CONTROL),
  838. DEVLINK_TRAP(PTP_EVENT, CONTROL),
  839. DEVLINK_TRAP(PTP_GENERAL, CONTROL),
  840. DEVLINK_TRAP(FLOW_ACTION_SAMPLE, CONTROL),
  841. DEVLINK_TRAP(FLOW_ACTION_TRAP, CONTROL),
  842. DEVLINK_TRAP(EARLY_DROP, DROP),
  843. DEVLINK_TRAP(VXLAN_PARSING, DROP),
  844. DEVLINK_TRAP(LLC_SNAP_PARSING, DROP),
  845. DEVLINK_TRAP(VLAN_PARSING, DROP),
  846. DEVLINK_TRAP(PPPOE_PPP_PARSING, DROP),
  847. DEVLINK_TRAP(MPLS_PARSING, DROP),
  848. DEVLINK_TRAP(ARP_PARSING, DROP),
  849. DEVLINK_TRAP(IP_1_PARSING, DROP),
  850. DEVLINK_TRAP(IP_N_PARSING, DROP),
  851. DEVLINK_TRAP(GRE_PARSING, DROP),
  852. DEVLINK_TRAP(UDP_PARSING, DROP),
  853. DEVLINK_TRAP(TCP_PARSING, DROP),
  854. DEVLINK_TRAP(IPSEC_PARSING, DROP),
  855. DEVLINK_TRAP(SCTP_PARSING, DROP),
  856. DEVLINK_TRAP(DCCP_PARSING, DROP),
  857. DEVLINK_TRAP(GTP_PARSING, DROP),
  858. DEVLINK_TRAP(ESP_PARSING, DROP),
  859. DEVLINK_TRAP(BLACKHOLE_NEXTHOP, DROP),
  860. DEVLINK_TRAP(DMAC_FILTER, DROP),
  861. DEVLINK_TRAP(EAPOL, CONTROL),
  862. DEVLINK_TRAP(LOCKED_PORT, DROP),
  863. };
  864. #define DEVLINK_TRAP_GROUP(_id) \
  865. { \
  866. .id = DEVLINK_TRAP_GROUP_GENERIC_ID_##_id, \
  867. .name = DEVLINK_TRAP_GROUP_GENERIC_NAME_##_id, \
  868. }
  869. static const struct devlink_trap_group devlink_trap_group_generic[] = {
  870. DEVLINK_TRAP_GROUP(L2_DROPS),
  871. DEVLINK_TRAP_GROUP(L3_DROPS),
  872. DEVLINK_TRAP_GROUP(L3_EXCEPTIONS),
  873. DEVLINK_TRAP_GROUP(BUFFER_DROPS),
  874. DEVLINK_TRAP_GROUP(TUNNEL_DROPS),
  875. DEVLINK_TRAP_GROUP(ACL_DROPS),
  876. DEVLINK_TRAP_GROUP(STP),
  877. DEVLINK_TRAP_GROUP(LACP),
  878. DEVLINK_TRAP_GROUP(LLDP),
  879. DEVLINK_TRAP_GROUP(MC_SNOOPING),
  880. DEVLINK_TRAP_GROUP(DHCP),
  881. DEVLINK_TRAP_GROUP(NEIGH_DISCOVERY),
  882. DEVLINK_TRAP_GROUP(BFD),
  883. DEVLINK_TRAP_GROUP(OSPF),
  884. DEVLINK_TRAP_GROUP(BGP),
  885. DEVLINK_TRAP_GROUP(VRRP),
  886. DEVLINK_TRAP_GROUP(PIM),
  887. DEVLINK_TRAP_GROUP(UC_LB),
  888. DEVLINK_TRAP_GROUP(LOCAL_DELIVERY),
  889. DEVLINK_TRAP_GROUP(EXTERNAL_DELIVERY),
  890. DEVLINK_TRAP_GROUP(IPV6),
  891. DEVLINK_TRAP_GROUP(PTP_EVENT),
  892. DEVLINK_TRAP_GROUP(PTP_GENERAL),
  893. DEVLINK_TRAP_GROUP(ACL_SAMPLE),
  894. DEVLINK_TRAP_GROUP(ACL_TRAP),
  895. DEVLINK_TRAP_GROUP(PARSER_ERROR_DROPS),
  896. DEVLINK_TRAP_GROUP(EAPOL),
  897. };
  898. static int devlink_trap_generic_verify(const struct devlink_trap *trap)
  899. {
  900. if (trap->id > DEVLINK_TRAP_GENERIC_ID_MAX)
  901. return -EINVAL;
  902. if (strcmp(trap->name, devlink_trap_generic[trap->id].name))
  903. return -EINVAL;
  904. if (trap->type != devlink_trap_generic[trap->id].type)
  905. return -EINVAL;
  906. return 0;
  907. }
  908. static int devlink_trap_driver_verify(const struct devlink_trap *trap)
  909. {
  910. int i;
  911. if (trap->id <= DEVLINK_TRAP_GENERIC_ID_MAX)
  912. return -EINVAL;
  913. for (i = 0; i < ARRAY_SIZE(devlink_trap_generic); i++) {
  914. if (!strcmp(trap->name, devlink_trap_generic[i].name))
  915. return -EEXIST;
  916. }
  917. return 0;
  918. }
  919. static int devlink_trap_verify(const struct devlink_trap *trap)
  920. {
  921. if (!trap || !trap->name)
  922. return -EINVAL;
  923. if (trap->generic)
  924. return devlink_trap_generic_verify(trap);
  925. else
  926. return devlink_trap_driver_verify(trap);
  927. }
  928. static int
  929. devlink_trap_group_generic_verify(const struct devlink_trap_group *group)
  930. {
  931. if (group->id > DEVLINK_TRAP_GROUP_GENERIC_ID_MAX)
  932. return -EINVAL;
  933. if (strcmp(group->name, devlink_trap_group_generic[group->id].name))
  934. return -EINVAL;
  935. return 0;
  936. }
  937. static int
  938. devlink_trap_group_driver_verify(const struct devlink_trap_group *group)
  939. {
  940. int i;
  941. if (group->id <= DEVLINK_TRAP_GROUP_GENERIC_ID_MAX)
  942. return -EINVAL;
  943. for (i = 0; i < ARRAY_SIZE(devlink_trap_group_generic); i++) {
  944. if (!strcmp(group->name, devlink_trap_group_generic[i].name))
  945. return -EEXIST;
  946. }
  947. return 0;
  948. }
  949. static int devlink_trap_group_verify(const struct devlink_trap_group *group)
  950. {
  951. if (group->generic)
  952. return devlink_trap_group_generic_verify(group);
  953. else
  954. return devlink_trap_group_driver_verify(group);
  955. }
  956. static void
  957. devlink_trap_group_notify(struct devlink *devlink,
  958. const struct devlink_trap_group_item *group_item,
  959. enum devlink_command cmd)
  960. {
  961. struct sk_buff *msg;
  962. int err;
  963. WARN_ON_ONCE(cmd != DEVLINK_CMD_TRAP_GROUP_NEW &&
  964. cmd != DEVLINK_CMD_TRAP_GROUP_DEL);
  965. if (!devl_is_registered(devlink) || !devlink_nl_notify_need(devlink))
  966. return;
  967. msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
  968. if (!msg)
  969. return;
  970. err = devlink_nl_trap_group_fill(msg, devlink, group_item, cmd, 0, 0,
  971. 0);
  972. if (err) {
  973. nlmsg_free(msg);
  974. return;
  975. }
  976. devlink_nl_notify_send(devlink, msg);
  977. }
  978. void devlink_trap_groups_notify_register(struct devlink *devlink)
  979. {
  980. struct devlink_trap_group_item *group_item;
  981. list_for_each_entry(group_item, &devlink->trap_group_list, list)
  982. devlink_trap_group_notify(devlink, group_item,
  983. DEVLINK_CMD_TRAP_GROUP_NEW);
  984. }
  985. void devlink_trap_groups_notify_unregister(struct devlink *devlink)
  986. {
  987. struct devlink_trap_group_item *group_item;
  988. list_for_each_entry_reverse(group_item, &devlink->trap_group_list, list)
  989. devlink_trap_group_notify(devlink, group_item,
  990. DEVLINK_CMD_TRAP_GROUP_DEL);
  991. }
  992. static int
  993. devlink_trap_item_group_link(struct devlink *devlink,
  994. struct devlink_trap_item *trap_item)
  995. {
  996. u16 group_id = trap_item->trap->init_group_id;
  997. struct devlink_trap_group_item *group_item;
  998. group_item = devlink_trap_group_item_lookup_by_id(devlink, group_id);
  999. if (WARN_ON_ONCE(!group_item))
  1000. return -EINVAL;
  1001. trap_item->group_item = group_item;
  1002. return 0;
  1003. }
  1004. static void devlink_trap_notify(struct devlink *devlink,
  1005. const struct devlink_trap_item *trap_item,
  1006. enum devlink_command cmd)
  1007. {
  1008. struct sk_buff *msg;
  1009. int err;
  1010. WARN_ON_ONCE(cmd != DEVLINK_CMD_TRAP_NEW &&
  1011. cmd != DEVLINK_CMD_TRAP_DEL);
  1012. if (!devl_is_registered(devlink) || !devlink_nl_notify_need(devlink))
  1013. return;
  1014. msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
  1015. if (!msg)
  1016. return;
  1017. err = devlink_nl_trap_fill(msg, devlink, trap_item, cmd, 0, 0, 0);
  1018. if (err) {
  1019. nlmsg_free(msg);
  1020. return;
  1021. }
  1022. devlink_nl_notify_send(devlink, msg);
  1023. }
  1024. void devlink_traps_notify_register(struct devlink *devlink)
  1025. {
  1026. struct devlink_trap_item *trap_item;
  1027. list_for_each_entry(trap_item, &devlink->trap_list, list)
  1028. devlink_trap_notify(devlink, trap_item, DEVLINK_CMD_TRAP_NEW);
  1029. }
  1030. void devlink_traps_notify_unregister(struct devlink *devlink)
  1031. {
  1032. struct devlink_trap_item *trap_item;
  1033. list_for_each_entry_reverse(trap_item, &devlink->trap_list, list)
  1034. devlink_trap_notify(devlink, trap_item, DEVLINK_CMD_TRAP_DEL);
  1035. }
  1036. static int
  1037. devlink_trap_register(struct devlink *devlink,
  1038. const struct devlink_trap *trap, void *priv)
  1039. {
  1040. struct devlink_trap_item *trap_item;
  1041. int err;
  1042. if (devlink_trap_item_lookup(devlink, trap->name))
  1043. return -EEXIST;
  1044. trap_item = kzalloc(sizeof(*trap_item), GFP_KERNEL);
  1045. if (!trap_item)
  1046. return -ENOMEM;
  1047. trap_item->stats = netdev_alloc_pcpu_stats(struct devlink_stats);
  1048. if (!trap_item->stats) {
  1049. err = -ENOMEM;
  1050. goto err_stats_alloc;
  1051. }
  1052. trap_item->trap = trap;
  1053. trap_item->action = trap->init_action;
  1054. trap_item->priv = priv;
  1055. err = devlink_trap_item_group_link(devlink, trap_item);
  1056. if (err)
  1057. goto err_group_link;
  1058. err = devlink->ops->trap_init(devlink, trap, trap_item);
  1059. if (err)
  1060. goto err_trap_init;
  1061. list_add_tail(&trap_item->list, &devlink->trap_list);
  1062. devlink_trap_notify(devlink, trap_item, DEVLINK_CMD_TRAP_NEW);
  1063. return 0;
  1064. err_trap_init:
  1065. err_group_link:
  1066. free_percpu(trap_item->stats);
  1067. err_stats_alloc:
  1068. kfree(trap_item);
  1069. return err;
  1070. }
  1071. static void devlink_trap_unregister(struct devlink *devlink,
  1072. const struct devlink_trap *trap)
  1073. {
  1074. struct devlink_trap_item *trap_item;
  1075. trap_item = devlink_trap_item_lookup(devlink, trap->name);
  1076. if (WARN_ON_ONCE(!trap_item))
  1077. return;
  1078. devlink_trap_notify(devlink, trap_item, DEVLINK_CMD_TRAP_DEL);
  1079. list_del(&trap_item->list);
  1080. if (devlink->ops->trap_fini)
  1081. devlink->ops->trap_fini(devlink, trap, trap_item);
  1082. free_percpu(trap_item->stats);
  1083. kfree(trap_item);
  1084. }
  1085. static void devlink_trap_disable(struct devlink *devlink,
  1086. const struct devlink_trap *trap)
  1087. {
  1088. struct devlink_trap_item *trap_item;
  1089. trap_item = devlink_trap_item_lookup(devlink, trap->name);
  1090. if (WARN_ON_ONCE(!trap_item))
  1091. return;
  1092. devlink->ops->trap_action_set(devlink, trap, DEVLINK_TRAP_ACTION_DROP,
  1093. NULL);
  1094. trap_item->action = DEVLINK_TRAP_ACTION_DROP;
  1095. }
  1096. /**
  1097. * devl_traps_register - Register packet traps with devlink.
  1098. * @devlink: devlink.
  1099. * @traps: Packet traps.
  1100. * @traps_count: Count of provided packet traps.
  1101. * @priv: Driver private information.
  1102. *
  1103. * Return: Non-zero value on failure.
  1104. */
  1105. int devl_traps_register(struct devlink *devlink,
  1106. const struct devlink_trap *traps,
  1107. size_t traps_count, void *priv)
  1108. {
  1109. int i, err;
  1110. if (!devlink->ops->trap_init || !devlink->ops->trap_action_set)
  1111. return -EINVAL;
  1112. devl_assert_locked(devlink);
  1113. for (i = 0; i < traps_count; i++) {
  1114. const struct devlink_trap *trap = &traps[i];
  1115. err = devlink_trap_verify(trap);
  1116. if (err)
  1117. goto err_trap_verify;
  1118. err = devlink_trap_register(devlink, trap, priv);
  1119. if (err)
  1120. goto err_trap_register;
  1121. }
  1122. return 0;
  1123. err_trap_register:
  1124. err_trap_verify:
  1125. for (i--; i >= 0; i--)
  1126. devlink_trap_unregister(devlink, &traps[i]);
  1127. return err;
  1128. }
  1129. EXPORT_SYMBOL_GPL(devl_traps_register);
  1130. /**
  1131. * devlink_traps_register - Register packet traps with devlink.
  1132. * @devlink: devlink.
  1133. * @traps: Packet traps.
  1134. * @traps_count: Count of provided packet traps.
  1135. * @priv: Driver private information.
  1136. *
  1137. * Context: Takes and release devlink->lock <mutex>.
  1138. *
  1139. * Return: Non-zero value on failure.
  1140. */
  1141. int devlink_traps_register(struct devlink *devlink,
  1142. const struct devlink_trap *traps,
  1143. size_t traps_count, void *priv)
  1144. {
  1145. int err;
  1146. devl_lock(devlink);
  1147. err = devl_traps_register(devlink, traps, traps_count, priv);
  1148. devl_unlock(devlink);
  1149. return err;
  1150. }
  1151. EXPORT_SYMBOL_GPL(devlink_traps_register);
  1152. /**
  1153. * devl_traps_unregister - Unregister packet traps from devlink.
  1154. * @devlink: devlink.
  1155. * @traps: Packet traps.
  1156. * @traps_count: Count of provided packet traps.
  1157. */
  1158. void devl_traps_unregister(struct devlink *devlink,
  1159. const struct devlink_trap *traps,
  1160. size_t traps_count)
  1161. {
  1162. int i;
  1163. devl_assert_locked(devlink);
  1164. /* Make sure we do not have any packets in-flight while unregistering
  1165. * traps by disabling all of them and waiting for a grace period.
  1166. */
  1167. for (i = traps_count - 1; i >= 0; i--)
  1168. devlink_trap_disable(devlink, &traps[i]);
  1169. synchronize_rcu();
  1170. for (i = traps_count - 1; i >= 0; i--)
  1171. devlink_trap_unregister(devlink, &traps[i]);
  1172. }
  1173. EXPORT_SYMBOL_GPL(devl_traps_unregister);
  1174. /**
  1175. * devlink_traps_unregister - Unregister packet traps from devlink.
  1176. * @devlink: devlink.
  1177. * @traps: Packet traps.
  1178. * @traps_count: Count of provided packet traps.
  1179. *
  1180. * Context: Takes and release devlink->lock <mutex>.
  1181. */
  1182. void devlink_traps_unregister(struct devlink *devlink,
  1183. const struct devlink_trap *traps,
  1184. size_t traps_count)
  1185. {
  1186. devl_lock(devlink);
  1187. devl_traps_unregister(devlink, traps, traps_count);
  1188. devl_unlock(devlink);
  1189. }
  1190. EXPORT_SYMBOL_GPL(devlink_traps_unregister);
  1191. static void
  1192. devlink_trap_stats_update(struct devlink_stats __percpu *trap_stats,
  1193. size_t skb_len)
  1194. {
  1195. struct devlink_stats *stats;
  1196. stats = this_cpu_ptr(trap_stats);
  1197. u64_stats_update_begin(&stats->syncp);
  1198. u64_stats_add(&stats->rx_bytes, skb_len);
  1199. u64_stats_inc(&stats->rx_packets);
  1200. u64_stats_update_end(&stats->syncp);
  1201. }
  1202. static void
  1203. devlink_trap_report_metadata_set(struct devlink_trap_metadata *metadata,
  1204. const struct devlink_trap_item *trap_item,
  1205. struct devlink_port *in_devlink_port,
  1206. const struct flow_action_cookie *fa_cookie)
  1207. {
  1208. metadata->trap_name = trap_item->trap->name;
  1209. metadata->trap_group_name = trap_item->group_item->group->name;
  1210. metadata->fa_cookie = fa_cookie;
  1211. metadata->trap_type = trap_item->trap->type;
  1212. spin_lock(&in_devlink_port->type_lock);
  1213. if (in_devlink_port->type == DEVLINK_PORT_TYPE_ETH)
  1214. metadata->input_dev = in_devlink_port->type_eth.netdev;
  1215. spin_unlock(&in_devlink_port->type_lock);
  1216. }
  1217. /**
  1218. * devlink_trap_report - Report trapped packet to drop monitor.
  1219. * @devlink: devlink.
  1220. * @skb: Trapped packet.
  1221. * @trap_ctx: Trap context.
  1222. * @in_devlink_port: Input devlink port.
  1223. * @fa_cookie: Flow action cookie. Could be NULL.
  1224. */
  1225. void devlink_trap_report(struct devlink *devlink, struct sk_buff *skb,
  1226. void *trap_ctx, struct devlink_port *in_devlink_port,
  1227. const struct flow_action_cookie *fa_cookie)
  1228. {
  1229. struct devlink_trap_item *trap_item = trap_ctx;
  1230. devlink_trap_stats_update(trap_item->stats, skb->len);
  1231. devlink_trap_stats_update(trap_item->group_item->stats, skb->len);
  1232. if (tracepoint_enabled(devlink_trap_report)) {
  1233. struct devlink_trap_metadata metadata = {};
  1234. devlink_trap_report_metadata_set(&metadata, trap_item,
  1235. in_devlink_port, fa_cookie);
  1236. trace_devlink_trap_report(devlink, skb, &metadata);
  1237. }
  1238. }
  1239. EXPORT_SYMBOL_GPL(devlink_trap_report);
  1240. /**
  1241. * devlink_trap_ctx_priv - Trap context to driver private information.
  1242. * @trap_ctx: Trap context.
  1243. *
  1244. * Return: Driver private information passed during registration.
  1245. */
  1246. void *devlink_trap_ctx_priv(void *trap_ctx)
  1247. {
  1248. struct devlink_trap_item *trap_item = trap_ctx;
  1249. return trap_item->priv;
  1250. }
  1251. EXPORT_SYMBOL_GPL(devlink_trap_ctx_priv);
  1252. static int
  1253. devlink_trap_group_item_policer_link(struct devlink *devlink,
  1254. struct devlink_trap_group_item *group_item)
  1255. {
  1256. u32 policer_id = group_item->group->init_policer_id;
  1257. struct devlink_trap_policer_item *policer_item;
  1258. if (policer_id == 0)
  1259. return 0;
  1260. policer_item = devlink_trap_policer_item_lookup(devlink, policer_id);
  1261. if (WARN_ON_ONCE(!policer_item))
  1262. return -EINVAL;
  1263. group_item->policer_item = policer_item;
  1264. return 0;
  1265. }
  1266. static int
  1267. devlink_trap_group_register(struct devlink *devlink,
  1268. const struct devlink_trap_group *group)
  1269. {
  1270. struct devlink_trap_group_item *group_item;
  1271. int err;
  1272. if (devlink_trap_group_item_lookup(devlink, group->name))
  1273. return -EEXIST;
  1274. group_item = kzalloc(sizeof(*group_item), GFP_KERNEL);
  1275. if (!group_item)
  1276. return -ENOMEM;
  1277. group_item->stats = netdev_alloc_pcpu_stats(struct devlink_stats);
  1278. if (!group_item->stats) {
  1279. err = -ENOMEM;
  1280. goto err_stats_alloc;
  1281. }
  1282. group_item->group = group;
  1283. err = devlink_trap_group_item_policer_link(devlink, group_item);
  1284. if (err)
  1285. goto err_policer_link;
  1286. if (devlink->ops->trap_group_init) {
  1287. err = devlink->ops->trap_group_init(devlink, group);
  1288. if (err)
  1289. goto err_group_init;
  1290. }
  1291. list_add_tail(&group_item->list, &devlink->trap_group_list);
  1292. devlink_trap_group_notify(devlink, group_item,
  1293. DEVLINK_CMD_TRAP_GROUP_NEW);
  1294. return 0;
  1295. err_group_init:
  1296. err_policer_link:
  1297. free_percpu(group_item->stats);
  1298. err_stats_alloc:
  1299. kfree(group_item);
  1300. return err;
  1301. }
  1302. static void
  1303. devlink_trap_group_unregister(struct devlink *devlink,
  1304. const struct devlink_trap_group *group)
  1305. {
  1306. struct devlink_trap_group_item *group_item;
  1307. group_item = devlink_trap_group_item_lookup(devlink, group->name);
  1308. if (WARN_ON_ONCE(!group_item))
  1309. return;
  1310. devlink_trap_group_notify(devlink, group_item,
  1311. DEVLINK_CMD_TRAP_GROUP_DEL);
  1312. list_del(&group_item->list);
  1313. free_percpu(group_item->stats);
  1314. kfree(group_item);
  1315. }
  1316. /**
  1317. * devl_trap_groups_register - Register packet trap groups with devlink.
  1318. * @devlink: devlink.
  1319. * @groups: Packet trap groups.
  1320. * @groups_count: Count of provided packet trap groups.
  1321. *
  1322. * Return: Non-zero value on failure.
  1323. */
  1324. int devl_trap_groups_register(struct devlink *devlink,
  1325. const struct devlink_trap_group *groups,
  1326. size_t groups_count)
  1327. {
  1328. int i, err;
  1329. devl_assert_locked(devlink);
  1330. for (i = 0; i < groups_count; i++) {
  1331. const struct devlink_trap_group *group = &groups[i];
  1332. err = devlink_trap_group_verify(group);
  1333. if (err)
  1334. goto err_trap_group_verify;
  1335. err = devlink_trap_group_register(devlink, group);
  1336. if (err)
  1337. goto err_trap_group_register;
  1338. }
  1339. return 0;
  1340. err_trap_group_register:
  1341. err_trap_group_verify:
  1342. for (i--; i >= 0; i--)
  1343. devlink_trap_group_unregister(devlink, &groups[i]);
  1344. return err;
  1345. }
  1346. EXPORT_SYMBOL_GPL(devl_trap_groups_register);
  1347. /**
  1348. * devlink_trap_groups_register - Register packet trap groups with devlink.
  1349. * @devlink: devlink.
  1350. * @groups: Packet trap groups.
  1351. * @groups_count: Count of provided packet trap groups.
  1352. *
  1353. * Context: Takes and release devlink->lock <mutex>.
  1354. *
  1355. * Return: Non-zero value on failure.
  1356. */
  1357. int devlink_trap_groups_register(struct devlink *devlink,
  1358. const struct devlink_trap_group *groups,
  1359. size_t groups_count)
  1360. {
  1361. int err;
  1362. devl_lock(devlink);
  1363. err = devl_trap_groups_register(devlink, groups, groups_count);
  1364. devl_unlock(devlink);
  1365. return err;
  1366. }
  1367. EXPORT_SYMBOL_GPL(devlink_trap_groups_register);
  1368. /**
  1369. * devl_trap_groups_unregister - Unregister packet trap groups from devlink.
  1370. * @devlink: devlink.
  1371. * @groups: Packet trap groups.
  1372. * @groups_count: Count of provided packet trap groups.
  1373. */
  1374. void devl_trap_groups_unregister(struct devlink *devlink,
  1375. const struct devlink_trap_group *groups,
  1376. size_t groups_count)
  1377. {
  1378. int i;
  1379. devl_assert_locked(devlink);
  1380. for (i = groups_count - 1; i >= 0; i--)
  1381. devlink_trap_group_unregister(devlink, &groups[i]);
  1382. }
  1383. EXPORT_SYMBOL_GPL(devl_trap_groups_unregister);
  1384. /**
  1385. * devlink_trap_groups_unregister - Unregister packet trap groups from devlink.
  1386. * @devlink: devlink.
  1387. * @groups: Packet trap groups.
  1388. * @groups_count: Count of provided packet trap groups.
  1389. *
  1390. * Context: Takes and release devlink->lock <mutex>.
  1391. */
  1392. void devlink_trap_groups_unregister(struct devlink *devlink,
  1393. const struct devlink_trap_group *groups,
  1394. size_t groups_count)
  1395. {
  1396. devl_lock(devlink);
  1397. devl_trap_groups_unregister(devlink, groups, groups_count);
  1398. devl_unlock(devlink);
  1399. }
  1400. EXPORT_SYMBOL_GPL(devlink_trap_groups_unregister);
  1401. static void
  1402. devlink_trap_policer_notify(struct devlink *devlink,
  1403. const struct devlink_trap_policer_item *policer_item,
  1404. enum devlink_command cmd)
  1405. {
  1406. struct sk_buff *msg;
  1407. int err;
  1408. WARN_ON_ONCE(cmd != DEVLINK_CMD_TRAP_POLICER_NEW &&
  1409. cmd != DEVLINK_CMD_TRAP_POLICER_DEL);
  1410. if (!devl_is_registered(devlink) || !devlink_nl_notify_need(devlink))
  1411. return;
  1412. msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
  1413. if (!msg)
  1414. return;
  1415. err = devlink_nl_trap_policer_fill(msg, devlink, policer_item, cmd, 0,
  1416. 0, 0);
  1417. if (err) {
  1418. nlmsg_free(msg);
  1419. return;
  1420. }
  1421. devlink_nl_notify_send(devlink, msg);
  1422. }
  1423. void devlink_trap_policers_notify_register(struct devlink *devlink)
  1424. {
  1425. struct devlink_trap_policer_item *policer_item;
  1426. list_for_each_entry(policer_item, &devlink->trap_policer_list, list)
  1427. devlink_trap_policer_notify(devlink, policer_item,
  1428. DEVLINK_CMD_TRAP_POLICER_NEW);
  1429. }
  1430. void devlink_trap_policers_notify_unregister(struct devlink *devlink)
  1431. {
  1432. struct devlink_trap_policer_item *policer_item;
  1433. list_for_each_entry_reverse(policer_item, &devlink->trap_policer_list,
  1434. list)
  1435. devlink_trap_policer_notify(devlink, policer_item,
  1436. DEVLINK_CMD_TRAP_POLICER_DEL);
  1437. }
  1438. static int
  1439. devlink_trap_policer_register(struct devlink *devlink,
  1440. const struct devlink_trap_policer *policer)
  1441. {
  1442. struct devlink_trap_policer_item *policer_item;
  1443. int err;
  1444. if (devlink_trap_policer_item_lookup(devlink, policer->id))
  1445. return -EEXIST;
  1446. policer_item = kzalloc(sizeof(*policer_item), GFP_KERNEL);
  1447. if (!policer_item)
  1448. return -ENOMEM;
  1449. policer_item->policer = policer;
  1450. policer_item->rate = policer->init_rate;
  1451. policer_item->burst = policer->init_burst;
  1452. if (devlink->ops->trap_policer_init) {
  1453. err = devlink->ops->trap_policer_init(devlink, policer);
  1454. if (err)
  1455. goto err_policer_init;
  1456. }
  1457. list_add_tail(&policer_item->list, &devlink->trap_policer_list);
  1458. devlink_trap_policer_notify(devlink, policer_item,
  1459. DEVLINK_CMD_TRAP_POLICER_NEW);
  1460. return 0;
  1461. err_policer_init:
  1462. kfree(policer_item);
  1463. return err;
  1464. }
  1465. static void
  1466. devlink_trap_policer_unregister(struct devlink *devlink,
  1467. const struct devlink_trap_policer *policer)
  1468. {
  1469. struct devlink_trap_policer_item *policer_item;
  1470. policer_item = devlink_trap_policer_item_lookup(devlink, policer->id);
  1471. if (WARN_ON_ONCE(!policer_item))
  1472. return;
  1473. devlink_trap_policer_notify(devlink, policer_item,
  1474. DEVLINK_CMD_TRAP_POLICER_DEL);
  1475. list_del(&policer_item->list);
  1476. if (devlink->ops->trap_policer_fini)
  1477. devlink->ops->trap_policer_fini(devlink, policer);
  1478. kfree(policer_item);
  1479. }
  1480. /**
  1481. * devl_trap_policers_register - Register packet trap policers with devlink.
  1482. * @devlink: devlink.
  1483. * @policers: Packet trap policers.
  1484. * @policers_count: Count of provided packet trap policers.
  1485. *
  1486. * Return: Non-zero value on failure.
  1487. */
  1488. int
  1489. devl_trap_policers_register(struct devlink *devlink,
  1490. const struct devlink_trap_policer *policers,
  1491. size_t policers_count)
  1492. {
  1493. int i, err;
  1494. devl_assert_locked(devlink);
  1495. for (i = 0; i < policers_count; i++) {
  1496. const struct devlink_trap_policer *policer = &policers[i];
  1497. if (WARN_ON(policer->id == 0 ||
  1498. policer->max_rate < policer->min_rate ||
  1499. policer->max_burst < policer->min_burst)) {
  1500. err = -EINVAL;
  1501. goto err_trap_policer_verify;
  1502. }
  1503. err = devlink_trap_policer_register(devlink, policer);
  1504. if (err)
  1505. goto err_trap_policer_register;
  1506. }
  1507. return 0;
  1508. err_trap_policer_register:
  1509. err_trap_policer_verify:
  1510. for (i--; i >= 0; i--)
  1511. devlink_trap_policer_unregister(devlink, &policers[i]);
  1512. return err;
  1513. }
  1514. EXPORT_SYMBOL_GPL(devl_trap_policers_register);
  1515. /**
  1516. * devl_trap_policers_unregister - Unregister packet trap policers from devlink.
  1517. * @devlink: devlink.
  1518. * @policers: Packet trap policers.
  1519. * @policers_count: Count of provided packet trap policers.
  1520. */
  1521. void
  1522. devl_trap_policers_unregister(struct devlink *devlink,
  1523. const struct devlink_trap_policer *policers,
  1524. size_t policers_count)
  1525. {
  1526. int i;
  1527. devl_assert_locked(devlink);
  1528. for (i = policers_count - 1; i >= 0; i--)
  1529. devlink_trap_policer_unregister(devlink, &policers[i]);
  1530. }
  1531. EXPORT_SYMBOL_GPL(devl_trap_policers_unregister);