ocelot_flower.c 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012
  1. // SPDX-License-Identifier: (GPL-2.0 OR MIT)
  2. /* Microsemi Ocelot Switch driver
  3. * Copyright (c) 2019 Microsemi Corporation
  4. */
  5. #include <net/pkt_cls.h>
  6. #include <net/tc_act/tc_gact.h>
  7. #include <soc/mscc/ocelot_vcap.h>
  8. #include "ocelot_police.h"
  9. #include "ocelot_vcap.h"
  10. /* Arbitrarily chosen constants for encoding the VCAP block and lookup number
  11. * into the chain number. This is UAPI.
  12. */
  13. #define VCAP_BLOCK 10000
  14. #define VCAP_LOOKUP 1000
  15. #define VCAP_IS1_NUM_LOOKUPS 3
  16. #define VCAP_IS2_NUM_LOOKUPS 2
  17. #define VCAP_IS2_NUM_PAG 256
  18. #define VCAP_IS1_CHAIN(lookup) \
  19. (1 * VCAP_BLOCK + (lookup) * VCAP_LOOKUP)
  20. #define VCAP_IS2_CHAIN(lookup, pag) \
  21. (2 * VCAP_BLOCK + (lookup) * VCAP_LOOKUP + (pag))
  22. /* PSFP chain and block ID */
  23. #define PSFP_BLOCK_ID OCELOT_NUM_VCAP_BLOCKS
  24. #define OCELOT_PSFP_CHAIN (3 * VCAP_BLOCK)
  25. static int ocelot_chain_to_block(int chain, bool ingress)
  26. {
  27. int lookup, pag;
  28. if (!ingress) {
  29. if (chain == 0)
  30. return VCAP_ES0;
  31. return -EOPNOTSUPP;
  32. }
  33. /* Backwards compatibility with older, single-chain tc-flower
  34. * offload support in Ocelot
  35. */
  36. if (chain == 0)
  37. return VCAP_IS2;
  38. for (lookup = 0; lookup < VCAP_IS1_NUM_LOOKUPS; lookup++)
  39. if (chain == VCAP_IS1_CHAIN(lookup))
  40. return VCAP_IS1;
  41. for (lookup = 0; lookup < VCAP_IS2_NUM_LOOKUPS; lookup++)
  42. for (pag = 0; pag < VCAP_IS2_NUM_PAG; pag++)
  43. if (chain == VCAP_IS2_CHAIN(lookup, pag))
  44. return VCAP_IS2;
  45. if (chain == OCELOT_PSFP_CHAIN)
  46. return PSFP_BLOCK_ID;
  47. return -EOPNOTSUPP;
  48. }
  49. /* Caller must ensure this is a valid IS1 or IS2 chain first,
  50. * by calling ocelot_chain_to_block.
  51. */
  52. static int ocelot_chain_to_lookup(int chain)
  53. {
  54. /* Backwards compatibility with older, single-chain tc-flower
  55. * offload support in Ocelot
  56. */
  57. if (chain == 0)
  58. return 0;
  59. return (chain / VCAP_LOOKUP) % 10;
  60. }
  61. /* Caller must ensure this is a valid IS2 chain first,
  62. * by calling ocelot_chain_to_block.
  63. */
  64. static int ocelot_chain_to_pag(int chain)
  65. {
  66. int lookup;
  67. /* Backwards compatibility with older, single-chain tc-flower
  68. * offload support in Ocelot
  69. */
  70. if (chain == 0)
  71. return 0;
  72. lookup = ocelot_chain_to_lookup(chain);
  73. /* calculate PAG value as chain index relative to the first PAG */
  74. return chain - VCAP_IS2_CHAIN(lookup, 0);
  75. }
  76. static bool ocelot_is_goto_target_valid(int goto_target, int chain,
  77. bool ingress)
  78. {
  79. int pag;
  80. /* Can't offload GOTO in VCAP ES0 */
  81. if (!ingress)
  82. return (goto_target < 0);
  83. /* Non-optional GOTOs */
  84. if (chain == 0)
  85. /* VCAP IS1 can be skipped, either partially or completely */
  86. return (goto_target == VCAP_IS1_CHAIN(0) ||
  87. goto_target == VCAP_IS1_CHAIN(1) ||
  88. goto_target == VCAP_IS1_CHAIN(2) ||
  89. goto_target == VCAP_IS2_CHAIN(0, 0) ||
  90. goto_target == VCAP_IS2_CHAIN(1, 0) ||
  91. goto_target == OCELOT_PSFP_CHAIN);
  92. if (chain == VCAP_IS1_CHAIN(0))
  93. return (goto_target == VCAP_IS1_CHAIN(1));
  94. if (chain == VCAP_IS1_CHAIN(1))
  95. return (goto_target == VCAP_IS1_CHAIN(2));
  96. /* Lookup 2 of VCAP IS1 can really support non-optional GOTOs,
  97. * using a Policy Association Group (PAG) value, which is an 8-bit
  98. * value encoding a VCAP IS2 target chain.
  99. */
  100. if (chain == VCAP_IS1_CHAIN(2)) {
  101. for (pag = 0; pag < VCAP_IS2_NUM_PAG; pag++)
  102. if (goto_target == VCAP_IS2_CHAIN(0, pag))
  103. return true;
  104. return false;
  105. }
  106. /* Non-optional GOTO from VCAP IS2 lookup 0 to lookup 1.
  107. * We cannot change the PAG at this point.
  108. */
  109. for (pag = 0; pag < VCAP_IS2_NUM_PAG; pag++)
  110. if (chain == VCAP_IS2_CHAIN(0, pag))
  111. return (goto_target == VCAP_IS2_CHAIN(1, pag));
  112. /* VCAP IS2 lookup 1 can goto to PSFP block if hardware support */
  113. for (pag = 0; pag < VCAP_IS2_NUM_PAG; pag++)
  114. if (chain == VCAP_IS2_CHAIN(1, pag))
  115. return (goto_target == OCELOT_PSFP_CHAIN);
  116. return false;
  117. }
  118. static struct ocelot_vcap_filter *
  119. ocelot_find_vcap_filter_that_points_at(struct ocelot *ocelot, int chain)
  120. {
  121. struct ocelot_vcap_filter *filter;
  122. struct ocelot_vcap_block *block;
  123. int block_id;
  124. block_id = ocelot_chain_to_block(chain, true);
  125. if (block_id < 0)
  126. return NULL;
  127. if (block_id == VCAP_IS2) {
  128. block = &ocelot->block[VCAP_IS1];
  129. list_for_each_entry(filter, &block->rules, list)
  130. if (filter->type == OCELOT_VCAP_FILTER_PAG &&
  131. filter->goto_target == chain)
  132. return filter;
  133. }
  134. list_for_each_entry(filter, &ocelot->dummy_rules, list)
  135. if (filter->goto_target == chain)
  136. return filter;
  137. return NULL;
  138. }
  139. static int
  140. ocelot_flower_parse_ingress_vlan_modify(struct ocelot *ocelot, int port,
  141. struct ocelot_vcap_filter *filter,
  142. const struct flow_action_entry *a,
  143. struct netlink_ext_ack *extack)
  144. {
  145. struct ocelot_port *ocelot_port = ocelot->ports[port];
  146. if (filter->goto_target != -1) {
  147. NL_SET_ERR_MSG_MOD(extack,
  148. "Last action must be GOTO");
  149. return -EOPNOTSUPP;
  150. }
  151. if (!ocelot_port->vlan_aware) {
  152. NL_SET_ERR_MSG_MOD(extack,
  153. "Can only modify VLAN under VLAN aware bridge");
  154. return -EOPNOTSUPP;
  155. }
  156. filter->action.vid_replace_ena = true;
  157. filter->action.pcp_dei_ena = true;
  158. filter->action.vid = a->vlan.vid;
  159. filter->action.pcp = a->vlan.prio;
  160. filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
  161. return 0;
  162. }
  163. static int
  164. ocelot_flower_parse_egress_vlan_modify(struct ocelot_vcap_filter *filter,
  165. const struct flow_action_entry *a,
  166. struct netlink_ext_ack *extack)
  167. {
  168. enum ocelot_tag_tpid_sel tpid;
  169. switch (ntohs(a->vlan.proto)) {
  170. case ETH_P_8021Q:
  171. tpid = OCELOT_TAG_TPID_SEL_8021Q;
  172. break;
  173. case ETH_P_8021AD:
  174. tpid = OCELOT_TAG_TPID_SEL_8021AD;
  175. break;
  176. default:
  177. NL_SET_ERR_MSG_MOD(extack,
  178. "Cannot modify custom TPID");
  179. return -EOPNOTSUPP;
  180. }
  181. filter->action.tag_a_tpid_sel = tpid;
  182. filter->action.push_outer_tag = OCELOT_ES0_TAG;
  183. filter->action.tag_a_vid_sel = OCELOT_ES0_VID_PLUS_CLASSIFIED_VID;
  184. filter->action.vid_a_val = a->vlan.vid;
  185. filter->action.pcp_a_val = a->vlan.prio;
  186. filter->action.tag_a_pcp_sel = OCELOT_ES0_PCP;
  187. filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
  188. return 0;
  189. }
  190. static int ocelot_flower_parse_action(struct ocelot *ocelot, int port,
  191. bool ingress, struct flow_cls_offload *f,
  192. struct ocelot_vcap_filter *filter)
  193. {
  194. const struct flow_action *action = &f->rule->action;
  195. struct netlink_ext_ack *extack = f->common.extack;
  196. bool allow_missing_goto_target = false;
  197. const struct flow_action_entry *a;
  198. enum ocelot_tag_tpid_sel tpid;
  199. int i, chain, egress_port;
  200. u32 pol_ix, pol_max;
  201. u64 rate;
  202. int err;
  203. if (!flow_action_basic_hw_stats_check(&f->rule->action,
  204. f->common.extack))
  205. return -EOPNOTSUPP;
  206. chain = f->common.chain_index;
  207. filter->block_id = ocelot_chain_to_block(chain, ingress);
  208. if (filter->block_id < 0) {
  209. NL_SET_ERR_MSG_MOD(extack, "Cannot offload to this chain");
  210. return -EOPNOTSUPP;
  211. }
  212. if (filter->block_id == VCAP_IS1 || filter->block_id == VCAP_IS2)
  213. filter->lookup = ocelot_chain_to_lookup(chain);
  214. if (filter->block_id == VCAP_IS2)
  215. filter->pag = ocelot_chain_to_pag(chain);
  216. filter->goto_target = -1;
  217. filter->type = OCELOT_VCAP_FILTER_DUMMY;
  218. flow_action_for_each(i, a, action) {
  219. switch (a->id) {
  220. case FLOW_ACTION_DROP:
  221. if (filter->block_id != VCAP_IS2) {
  222. NL_SET_ERR_MSG_MOD(extack,
  223. "Drop action can only be offloaded to VCAP IS2");
  224. return -EOPNOTSUPP;
  225. }
  226. if (filter->goto_target != -1) {
  227. NL_SET_ERR_MSG_MOD(extack,
  228. "Last action must be GOTO");
  229. return -EOPNOTSUPP;
  230. }
  231. filter->action.mask_mode = OCELOT_MASK_MODE_PERMIT_DENY;
  232. filter->action.port_mask = 0;
  233. filter->action.police_ena = true;
  234. filter->action.pol_ix = OCELOT_POLICER_DISCARD;
  235. filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
  236. break;
  237. case FLOW_ACTION_ACCEPT:
  238. if (filter->block_id != VCAP_ES0 &&
  239. filter->block_id != VCAP_IS1 &&
  240. filter->block_id != VCAP_IS2) {
  241. NL_SET_ERR_MSG_MOD(extack,
  242. "Accept action can only be offloaded to VCAP chains");
  243. return -EOPNOTSUPP;
  244. }
  245. if (filter->block_id != VCAP_ES0 &&
  246. filter->goto_target != -1) {
  247. NL_SET_ERR_MSG_MOD(extack,
  248. "Last action must be GOTO");
  249. return -EOPNOTSUPP;
  250. }
  251. filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
  252. break;
  253. case FLOW_ACTION_TRAP:
  254. if (filter->block_id != VCAP_IS2 ||
  255. filter->lookup != 0) {
  256. NL_SET_ERR_MSG_MOD(extack,
  257. "Trap action can only be offloaded to VCAP IS2 lookup 0");
  258. return -EOPNOTSUPP;
  259. }
  260. if (filter->goto_target != -1) {
  261. NL_SET_ERR_MSG_MOD(extack,
  262. "Last action must be GOTO");
  263. return -EOPNOTSUPP;
  264. }
  265. filter->action.mask_mode = OCELOT_MASK_MODE_PERMIT_DENY;
  266. filter->action.port_mask = 0;
  267. filter->action.cpu_copy_ena = true;
  268. filter->action.cpu_qu_num = 0;
  269. filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
  270. filter->is_trap = true;
  271. break;
  272. case FLOW_ACTION_POLICE:
  273. if (filter->block_id == PSFP_BLOCK_ID) {
  274. filter->type = OCELOT_PSFP_FILTER_OFFLOAD;
  275. break;
  276. }
  277. if (filter->block_id != VCAP_IS2 ||
  278. filter->lookup != 0) {
  279. NL_SET_ERR_MSG_MOD(extack,
  280. "Police action can only be offloaded to VCAP IS2 lookup 0 or PSFP");
  281. return -EOPNOTSUPP;
  282. }
  283. if (filter->goto_target != -1) {
  284. NL_SET_ERR_MSG_MOD(extack,
  285. "Last action must be GOTO");
  286. return -EOPNOTSUPP;
  287. }
  288. err = ocelot_policer_validate(action, a, extack);
  289. if (err)
  290. return err;
  291. filter->action.police_ena = true;
  292. pol_ix = a->hw_index + ocelot->vcap_pol.base;
  293. pol_max = ocelot->vcap_pol.max;
  294. if (ocelot->vcap_pol.max2 && pol_ix > pol_max) {
  295. pol_ix += ocelot->vcap_pol.base2 - pol_max - 1;
  296. pol_max = ocelot->vcap_pol.max2;
  297. }
  298. if (pol_ix >= pol_max)
  299. return -EINVAL;
  300. filter->action.pol_ix = pol_ix;
  301. rate = a->police.rate_bytes_ps;
  302. filter->action.pol.rate = div_u64(rate, 1000) * 8;
  303. filter->action.pol.burst = a->police.burst;
  304. filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
  305. break;
  306. case FLOW_ACTION_REDIRECT:
  307. if (filter->block_id != VCAP_IS2) {
  308. NL_SET_ERR_MSG_MOD(extack,
  309. "Redirect action can only be offloaded to VCAP IS2");
  310. return -EOPNOTSUPP;
  311. }
  312. if (filter->goto_target != -1) {
  313. NL_SET_ERR_MSG_MOD(extack,
  314. "Last action must be GOTO");
  315. return -EOPNOTSUPP;
  316. }
  317. egress_port = ocelot->ops->netdev_to_port(a->dev);
  318. if (egress_port < 0) {
  319. NL_SET_ERR_MSG_MOD(extack,
  320. "Destination not an ocelot port");
  321. return -EOPNOTSUPP;
  322. }
  323. filter->action.mask_mode = OCELOT_MASK_MODE_REDIRECT;
  324. filter->action.port_mask = BIT(egress_port);
  325. filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
  326. break;
  327. case FLOW_ACTION_MIRRED:
  328. if (filter->block_id != VCAP_IS2) {
  329. NL_SET_ERR_MSG_MOD(extack,
  330. "Mirror action can only be offloaded to VCAP IS2");
  331. return -EOPNOTSUPP;
  332. }
  333. if (filter->goto_target != -1) {
  334. NL_SET_ERR_MSG_MOD(extack,
  335. "Last action must be GOTO");
  336. return -EOPNOTSUPP;
  337. }
  338. egress_port = ocelot->ops->netdev_to_port(a->dev);
  339. if (egress_port < 0) {
  340. NL_SET_ERR_MSG_MOD(extack,
  341. "Destination not an ocelot port");
  342. return -EOPNOTSUPP;
  343. }
  344. filter->egress_port.value = egress_port;
  345. filter->action.mirror_ena = true;
  346. filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
  347. break;
  348. case FLOW_ACTION_VLAN_POP:
  349. if (filter->block_id != VCAP_IS1) {
  350. NL_SET_ERR_MSG_MOD(extack,
  351. "VLAN pop action can only be offloaded to VCAP IS1");
  352. return -EOPNOTSUPP;
  353. }
  354. if (filter->goto_target != -1) {
  355. NL_SET_ERR_MSG_MOD(extack,
  356. "Last action must be GOTO");
  357. return -EOPNOTSUPP;
  358. }
  359. filter->action.vlan_pop_cnt_ena = true;
  360. filter->action.vlan_pop_cnt++;
  361. if (filter->action.vlan_pop_cnt > 2) {
  362. NL_SET_ERR_MSG_MOD(extack,
  363. "Cannot pop more than 2 VLAN headers");
  364. return -EOPNOTSUPP;
  365. }
  366. filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
  367. break;
  368. case FLOW_ACTION_VLAN_MANGLE:
  369. if (filter->block_id == VCAP_IS1) {
  370. err = ocelot_flower_parse_ingress_vlan_modify(ocelot, port,
  371. filter, a,
  372. extack);
  373. } else if (filter->block_id == VCAP_ES0) {
  374. err = ocelot_flower_parse_egress_vlan_modify(filter, a,
  375. extack);
  376. } else {
  377. NL_SET_ERR_MSG_MOD(extack,
  378. "VLAN modify action can only be offloaded to VCAP IS1 or ES0");
  379. err = -EOPNOTSUPP;
  380. }
  381. if (err)
  382. return err;
  383. break;
  384. case FLOW_ACTION_PRIORITY:
  385. if (filter->block_id != VCAP_IS1) {
  386. NL_SET_ERR_MSG_MOD(extack,
  387. "Priority action can only be offloaded to VCAP IS1");
  388. return -EOPNOTSUPP;
  389. }
  390. if (filter->goto_target != -1) {
  391. NL_SET_ERR_MSG_MOD(extack,
  392. "Last action must be GOTO");
  393. return -EOPNOTSUPP;
  394. }
  395. filter->action.qos_ena = true;
  396. filter->action.qos_val = a->priority;
  397. filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
  398. break;
  399. case FLOW_ACTION_GOTO:
  400. filter->goto_target = a->chain_index;
  401. if (filter->block_id == VCAP_IS1 && filter->lookup == 2) {
  402. int pag = ocelot_chain_to_pag(filter->goto_target);
  403. filter->action.pag_override_mask = 0xff;
  404. filter->action.pag_val = pag;
  405. filter->type = OCELOT_VCAP_FILTER_PAG;
  406. }
  407. break;
  408. case FLOW_ACTION_VLAN_PUSH:
  409. if (filter->block_id != VCAP_ES0) {
  410. NL_SET_ERR_MSG_MOD(extack,
  411. "VLAN push action can only be offloaded to VCAP ES0");
  412. return -EOPNOTSUPP;
  413. }
  414. switch (ntohs(a->vlan.proto)) {
  415. case ETH_P_8021Q:
  416. tpid = OCELOT_TAG_TPID_SEL_8021Q;
  417. break;
  418. case ETH_P_8021AD:
  419. tpid = OCELOT_TAG_TPID_SEL_8021AD;
  420. break;
  421. default:
  422. NL_SET_ERR_MSG_MOD(extack,
  423. "Cannot push custom TPID");
  424. return -EOPNOTSUPP;
  425. }
  426. filter->action.tag_a_tpid_sel = tpid;
  427. filter->action.push_outer_tag = OCELOT_ES0_TAG;
  428. filter->action.tag_a_vid_sel = OCELOT_ES0_VID;
  429. filter->action.vid_a_val = a->vlan.vid;
  430. filter->action.pcp_a_val = a->vlan.prio;
  431. filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
  432. break;
  433. case FLOW_ACTION_GATE:
  434. if (filter->block_id != PSFP_BLOCK_ID) {
  435. NL_SET_ERR_MSG_MOD(extack,
  436. "Gate action can only be offloaded to PSFP chain");
  437. return -EOPNOTSUPP;
  438. }
  439. filter->type = OCELOT_PSFP_FILTER_OFFLOAD;
  440. break;
  441. default:
  442. NL_SET_ERR_MSG_MOD(extack, "Cannot offload action");
  443. return -EOPNOTSUPP;
  444. }
  445. }
  446. if (filter->goto_target == -1) {
  447. if ((filter->block_id == VCAP_IS2 && filter->lookup == 1) ||
  448. chain == 0 || filter->block_id == PSFP_BLOCK_ID) {
  449. allow_missing_goto_target = true;
  450. } else {
  451. NL_SET_ERR_MSG_MOD(extack, "Missing GOTO action");
  452. return -EOPNOTSUPP;
  453. }
  454. }
  455. if (!ocelot_is_goto_target_valid(filter->goto_target, chain, ingress) &&
  456. !allow_missing_goto_target) {
  457. NL_SET_ERR_MSG_MOD(extack, "Cannot offload this GOTO target");
  458. return -EOPNOTSUPP;
  459. }
  460. return 0;
  461. }
  462. static int ocelot_flower_parse_indev(struct ocelot *ocelot, int port,
  463. struct flow_cls_offload *f,
  464. struct ocelot_vcap_filter *filter)
  465. {
  466. struct flow_rule *rule = flow_cls_offload_flow_rule(f);
  467. const struct vcap_props *vcap = &ocelot->vcap[VCAP_ES0];
  468. int key_length = vcap->keys[VCAP_ES0_IGR_PORT].length;
  469. struct netlink_ext_ack *extack = f->common.extack;
  470. struct net_device *dev, *indev;
  471. struct flow_match_meta match;
  472. int ingress_port;
  473. flow_rule_match_meta(rule, &match);
  474. if (!match.mask->ingress_ifindex)
  475. return 0;
  476. if (match.mask->ingress_ifindex != 0xFFFFFFFF) {
  477. NL_SET_ERR_MSG_MOD(extack, "Unsupported ingress ifindex mask");
  478. return -EOPNOTSUPP;
  479. }
  480. dev = ocelot->ops->port_to_netdev(ocelot, port);
  481. if (!dev)
  482. return -EINVAL;
  483. indev = __dev_get_by_index(dev_net(dev), match.key->ingress_ifindex);
  484. if (!indev) {
  485. NL_SET_ERR_MSG_MOD(extack,
  486. "Can't find the ingress port to match on");
  487. return -ENOENT;
  488. }
  489. ingress_port = ocelot->ops->netdev_to_port(indev);
  490. if (ingress_port < 0) {
  491. NL_SET_ERR_MSG_MOD(extack,
  492. "Can only offload an ocelot ingress port");
  493. return -EOPNOTSUPP;
  494. }
  495. if (ingress_port == port) {
  496. NL_SET_ERR_MSG_MOD(extack,
  497. "Ingress port is equal to the egress port");
  498. return -EINVAL;
  499. }
  500. filter->ingress_port.value = ingress_port;
  501. filter->ingress_port.mask = GENMASK(key_length - 1, 0);
  502. return 0;
  503. }
  504. static int
  505. ocelot_flower_parse_key(struct ocelot *ocelot, int port, bool ingress,
  506. struct flow_cls_offload *f,
  507. struct ocelot_vcap_filter *filter)
  508. {
  509. struct flow_rule *rule = flow_cls_offload_flow_rule(f);
  510. struct flow_dissector *dissector = rule->match.dissector;
  511. struct netlink_ext_ack *extack = f->common.extack;
  512. u16 proto = ntohs(f->common.protocol);
  513. bool match_protocol = true;
  514. int ret;
  515. if (dissector->used_keys &
  516. ~(BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL) |
  517. BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) |
  518. BIT_ULL(FLOW_DISSECTOR_KEY_META) |
  519. BIT_ULL(FLOW_DISSECTOR_KEY_PORTS) |
  520. BIT_ULL(FLOW_DISSECTOR_KEY_VLAN) |
  521. BIT_ULL(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
  522. BIT_ULL(FLOW_DISSECTOR_KEY_IPV6_ADDRS) |
  523. BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS))) {
  524. return -EOPNOTSUPP;
  525. }
  526. if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_META)) {
  527. struct flow_match_meta match;
  528. flow_rule_match_meta(rule, &match);
  529. if (match.mask->l2_miss) {
  530. NL_SET_ERR_MSG_MOD(extack, "Can't match on \"l2_miss\"");
  531. return -EOPNOTSUPP;
  532. }
  533. }
  534. /* For VCAP ES0 (egress rewriter) we can match on the ingress port */
  535. if (!ingress) {
  536. ret = ocelot_flower_parse_indev(ocelot, port, f, filter);
  537. if (ret)
  538. return ret;
  539. }
  540. if (flow_rule_match_has_control_flags(rule, extack))
  541. return -EOPNOTSUPP;
  542. if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {
  543. struct flow_match_vlan match;
  544. flow_rule_match_vlan(rule, &match);
  545. filter->key_type = OCELOT_VCAP_KEY_ANY;
  546. filter->vlan.vid.value = match.key->vlan_id;
  547. filter->vlan.vid.mask = match.mask->vlan_id;
  548. filter->vlan.pcp.value[0] = match.key->vlan_priority;
  549. filter->vlan.pcp.mask[0] = match.mask->vlan_priority;
  550. match_protocol = false;
  551. }
  552. if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
  553. struct flow_match_eth_addrs match;
  554. if (filter->block_id == VCAP_ES0) {
  555. NL_SET_ERR_MSG_MOD(extack,
  556. "VCAP ES0 cannot match on MAC address");
  557. return -EOPNOTSUPP;
  558. }
  559. /* The hw support mac matches only for MAC_ETYPE key,
  560. * therefore if other matches(port, tcp flags, etc) are added
  561. * then just bail out
  562. */
  563. if ((dissector->used_keys &
  564. (BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
  565. BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) |
  566. BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL))) !=
  567. (BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
  568. BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) |
  569. BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL)))
  570. return -EOPNOTSUPP;
  571. flow_rule_match_eth_addrs(rule, &match);
  572. if (filter->block_id == VCAP_IS1 &&
  573. !is_zero_ether_addr(match.mask->dst)) {
  574. NL_SET_ERR_MSG_MOD(extack,
  575. "Key type S1_NORMAL cannot match on destination MAC");
  576. return -EOPNOTSUPP;
  577. }
  578. filter->key_type = OCELOT_VCAP_KEY_ETYPE;
  579. ether_addr_copy(filter->key.etype.dmac.value,
  580. match.key->dst);
  581. ether_addr_copy(filter->key.etype.smac.value,
  582. match.key->src);
  583. ether_addr_copy(filter->key.etype.dmac.mask,
  584. match.mask->dst);
  585. ether_addr_copy(filter->key.etype.smac.mask,
  586. match.mask->src);
  587. goto finished_key_parsing;
  588. }
  589. if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
  590. struct flow_match_basic match;
  591. flow_rule_match_basic(rule, &match);
  592. if (ntohs(match.key->n_proto) == ETH_P_IP) {
  593. if (filter->block_id == VCAP_ES0) {
  594. NL_SET_ERR_MSG_MOD(extack,
  595. "VCAP ES0 cannot match on IP protocol");
  596. return -EOPNOTSUPP;
  597. }
  598. filter->key_type = OCELOT_VCAP_KEY_IPV4;
  599. filter->key.ipv4.proto.value[0] =
  600. match.key->ip_proto;
  601. filter->key.ipv4.proto.mask[0] =
  602. match.mask->ip_proto;
  603. match_protocol = false;
  604. }
  605. if (ntohs(match.key->n_proto) == ETH_P_IPV6) {
  606. if (filter->block_id == VCAP_ES0) {
  607. NL_SET_ERR_MSG_MOD(extack,
  608. "VCAP ES0 cannot match on IP protocol");
  609. return -EOPNOTSUPP;
  610. }
  611. filter->key_type = OCELOT_VCAP_KEY_IPV6;
  612. filter->key.ipv6.proto.value[0] =
  613. match.key->ip_proto;
  614. filter->key.ipv6.proto.mask[0] =
  615. match.mask->ip_proto;
  616. match_protocol = false;
  617. }
  618. }
  619. if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS) &&
  620. proto == ETH_P_IP) {
  621. struct flow_match_ipv4_addrs match;
  622. u8 *tmp;
  623. if (filter->block_id == VCAP_ES0) {
  624. NL_SET_ERR_MSG_MOD(extack,
  625. "VCAP ES0 cannot match on IP address");
  626. return -EOPNOTSUPP;
  627. }
  628. flow_rule_match_ipv4_addrs(rule, &match);
  629. if (filter->block_id == VCAP_IS1 && *(u32 *)&match.mask->dst) {
  630. NL_SET_ERR_MSG_MOD(extack,
  631. "Key type S1_NORMAL cannot match on destination IP");
  632. return -EOPNOTSUPP;
  633. }
  634. tmp = &filter->key.ipv4.sip.value.addr[0];
  635. memcpy(tmp, &match.key->src, 4);
  636. tmp = &filter->key.ipv4.sip.mask.addr[0];
  637. memcpy(tmp, &match.mask->src, 4);
  638. tmp = &filter->key.ipv4.dip.value.addr[0];
  639. memcpy(tmp, &match.key->dst, 4);
  640. tmp = &filter->key.ipv4.dip.mask.addr[0];
  641. memcpy(tmp, &match.mask->dst, 4);
  642. match_protocol = false;
  643. }
  644. if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS) &&
  645. proto == ETH_P_IPV6) {
  646. return -EOPNOTSUPP;
  647. }
  648. if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) {
  649. struct flow_match_ports match;
  650. if (filter->block_id == VCAP_ES0) {
  651. NL_SET_ERR_MSG_MOD(extack,
  652. "VCAP ES0 cannot match on L4 ports");
  653. return -EOPNOTSUPP;
  654. }
  655. flow_rule_match_ports(rule, &match);
  656. filter->key.ipv4.sport.value = ntohs(match.key->src);
  657. filter->key.ipv4.sport.mask = ntohs(match.mask->src);
  658. filter->key.ipv4.dport.value = ntohs(match.key->dst);
  659. filter->key.ipv4.dport.mask = ntohs(match.mask->dst);
  660. match_protocol = false;
  661. }
  662. finished_key_parsing:
  663. if (match_protocol && proto != ETH_P_ALL) {
  664. if (filter->block_id == VCAP_ES0) {
  665. NL_SET_ERR_MSG_MOD(extack,
  666. "VCAP ES0 cannot match on L2 proto");
  667. return -EOPNOTSUPP;
  668. }
  669. /* TODO: support SNAP, LLC etc */
  670. if (proto < ETH_P_802_3_MIN)
  671. return -EOPNOTSUPP;
  672. filter->key_type = OCELOT_VCAP_KEY_ETYPE;
  673. *(__be16 *)filter->key.etype.etype.value = htons(proto);
  674. *(__be16 *)filter->key.etype.etype.mask = htons(0xffff);
  675. }
  676. /* else, a filter of type OCELOT_VCAP_KEY_ANY is implicitly added */
  677. return 0;
  678. }
  679. static int ocelot_flower_parse(struct ocelot *ocelot, int port, bool ingress,
  680. struct flow_cls_offload *f,
  681. struct ocelot_vcap_filter *filter)
  682. {
  683. int ret;
  684. filter->prio = f->common.prio;
  685. filter->id.cookie = f->cookie;
  686. filter->id.tc_offload = true;
  687. ret = ocelot_flower_parse_action(ocelot, port, ingress, f, filter);
  688. if (ret)
  689. return ret;
  690. /* PSFP filter need to parse key by stream identification function. */
  691. if (filter->type == OCELOT_PSFP_FILTER_OFFLOAD)
  692. return 0;
  693. return ocelot_flower_parse_key(ocelot, port, ingress, f, filter);
  694. }
  695. static struct ocelot_vcap_filter
  696. *ocelot_vcap_filter_create(struct ocelot *ocelot, int port, bool ingress,
  697. struct flow_cls_offload *f)
  698. {
  699. struct ocelot_vcap_filter *filter;
  700. filter = kzalloc(sizeof(*filter), GFP_KERNEL);
  701. if (!filter)
  702. return NULL;
  703. if (ingress) {
  704. filter->ingress_port_mask = BIT(port);
  705. } else {
  706. const struct vcap_props *vcap = &ocelot->vcap[VCAP_ES0];
  707. int key_length = vcap->keys[VCAP_ES0_EGR_PORT].length;
  708. filter->egress_port.value = port;
  709. filter->egress_port.mask = GENMASK(key_length - 1, 0);
  710. }
  711. return filter;
  712. }
  713. static int ocelot_vcap_dummy_filter_add(struct ocelot *ocelot,
  714. struct ocelot_vcap_filter *filter)
  715. {
  716. list_add(&filter->list, &ocelot->dummy_rules);
  717. return 0;
  718. }
  719. static int ocelot_vcap_dummy_filter_del(struct ocelot *ocelot,
  720. struct ocelot_vcap_filter *filter)
  721. {
  722. list_del(&filter->list);
  723. kfree(filter);
  724. return 0;
  725. }
  726. /* If we have an egress VLAN modification rule, we need to actually write the
  727. * delta between the input VLAN (from the key) and the output VLAN (from the
  728. * action), but the action was parsed first. So we need to patch the delta into
  729. * the action here.
  730. */
  731. static int
  732. ocelot_flower_patch_es0_vlan_modify(struct ocelot_vcap_filter *filter,
  733. struct netlink_ext_ack *extack)
  734. {
  735. if (filter->block_id != VCAP_ES0 ||
  736. filter->action.tag_a_vid_sel != OCELOT_ES0_VID_PLUS_CLASSIFIED_VID)
  737. return 0;
  738. if (filter->vlan.vid.mask != VLAN_VID_MASK) {
  739. NL_SET_ERR_MSG_MOD(extack,
  740. "VCAP ES0 VLAN rewriting needs a full VLAN in the key");
  741. return -EOPNOTSUPP;
  742. }
  743. filter->action.vid_a_val -= filter->vlan.vid.value;
  744. filter->action.vid_a_val &= VLAN_VID_MASK;
  745. return 0;
  746. }
  747. int ocelot_cls_flower_replace(struct ocelot *ocelot, int port,
  748. struct flow_cls_offload *f, bool ingress)
  749. {
  750. struct netlink_ext_ack *extack = f->common.extack;
  751. struct ocelot_vcap_filter *filter;
  752. int chain = f->common.chain_index;
  753. int block_id, ret;
  754. if (chain && !ocelot_find_vcap_filter_that_points_at(ocelot, chain)) {
  755. NL_SET_ERR_MSG_MOD(extack, "No default GOTO action points to this chain");
  756. return -EOPNOTSUPP;
  757. }
  758. block_id = ocelot_chain_to_block(chain, ingress);
  759. if (block_id < 0) {
  760. NL_SET_ERR_MSG_MOD(extack, "Cannot offload to this chain");
  761. return -EOPNOTSUPP;
  762. }
  763. filter = ocelot_vcap_block_find_filter_by_id(&ocelot->block[block_id],
  764. f->cookie, true);
  765. if (filter) {
  766. /* Filter already exists on other ports */
  767. if (!ingress) {
  768. NL_SET_ERR_MSG_MOD(extack, "VCAP ES0 does not support shared filters");
  769. return -EOPNOTSUPP;
  770. }
  771. filter->ingress_port_mask |= BIT(port);
  772. return ocelot_vcap_filter_replace(ocelot, filter);
  773. }
  774. /* Filter didn't exist, create it now */
  775. filter = ocelot_vcap_filter_create(ocelot, port, ingress, f);
  776. if (!filter)
  777. return -ENOMEM;
  778. ret = ocelot_flower_parse(ocelot, port, ingress, f, filter);
  779. if (ret) {
  780. kfree(filter);
  781. return ret;
  782. }
  783. ret = ocelot_flower_patch_es0_vlan_modify(filter, extack);
  784. if (ret) {
  785. kfree(filter);
  786. return ret;
  787. }
  788. /* The non-optional GOTOs for the TCAM skeleton don't need
  789. * to be actually offloaded.
  790. */
  791. if (filter->type == OCELOT_VCAP_FILTER_DUMMY)
  792. return ocelot_vcap_dummy_filter_add(ocelot, filter);
  793. if (filter->type == OCELOT_PSFP_FILTER_OFFLOAD) {
  794. kfree(filter);
  795. if (ocelot->ops->psfp_filter_add)
  796. return ocelot->ops->psfp_filter_add(ocelot, port, f);
  797. NL_SET_ERR_MSG_MOD(extack, "PSFP chain is not supported in HW");
  798. return -EOPNOTSUPP;
  799. }
  800. return ocelot_vcap_filter_add(ocelot, filter, f->common.extack);
  801. }
  802. EXPORT_SYMBOL_GPL(ocelot_cls_flower_replace);
  803. int ocelot_cls_flower_destroy(struct ocelot *ocelot, int port,
  804. struct flow_cls_offload *f, bool ingress)
  805. {
  806. struct ocelot_vcap_filter *filter;
  807. struct ocelot_vcap_block *block;
  808. int block_id;
  809. block_id = ocelot_chain_to_block(f->common.chain_index, ingress);
  810. if (block_id < 0)
  811. return 0;
  812. if (block_id == PSFP_BLOCK_ID) {
  813. if (ocelot->ops->psfp_filter_del)
  814. return ocelot->ops->psfp_filter_del(ocelot, f);
  815. return -EOPNOTSUPP;
  816. }
  817. block = &ocelot->block[block_id];
  818. filter = ocelot_vcap_block_find_filter_by_id(block, f->cookie, true);
  819. if (!filter)
  820. return 0;
  821. if (filter->type == OCELOT_VCAP_FILTER_DUMMY)
  822. return ocelot_vcap_dummy_filter_del(ocelot, filter);
  823. if (ingress) {
  824. filter->ingress_port_mask &= ~BIT(port);
  825. if (filter->ingress_port_mask)
  826. return ocelot_vcap_filter_replace(ocelot, filter);
  827. }
  828. return ocelot_vcap_filter_del(ocelot, filter);
  829. }
  830. EXPORT_SYMBOL_GPL(ocelot_cls_flower_destroy);
  831. int ocelot_cls_flower_stats(struct ocelot *ocelot, int port,
  832. struct flow_cls_offload *f, bool ingress)
  833. {
  834. struct ocelot_vcap_filter *filter;
  835. struct ocelot_vcap_block *block;
  836. struct flow_stats stats = {0};
  837. int block_id, ret;
  838. block_id = ocelot_chain_to_block(f->common.chain_index, ingress);
  839. if (block_id < 0)
  840. return 0;
  841. if (block_id == PSFP_BLOCK_ID) {
  842. if (ocelot->ops->psfp_stats_get) {
  843. ret = ocelot->ops->psfp_stats_get(ocelot, f, &stats);
  844. if (ret)
  845. return ret;
  846. goto stats_update;
  847. }
  848. return -EOPNOTSUPP;
  849. }
  850. block = &ocelot->block[block_id];
  851. filter = ocelot_vcap_block_find_filter_by_id(block, f->cookie, true);
  852. if (!filter || filter->type == OCELOT_VCAP_FILTER_DUMMY)
  853. return 0;
  854. ret = ocelot_vcap_filter_stats_update(ocelot, filter);
  855. if (ret)
  856. return ret;
  857. stats.pkts = filter->stats.pkts;
  858. stats_update:
  859. flow_stats_update(&f->stats, 0x0, stats.pkts, stats.drops, 0x0,
  860. FLOW_ACTION_HW_STATS_IMMEDIATE);
  861. return 0;
  862. }
  863. EXPORT_SYMBOL_GPL(ocelot_cls_flower_stats);