ocelot_flower.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005
  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(FLOW_DISSECTOR_KEY_CONTROL) |
  517. BIT(FLOW_DISSECTOR_KEY_BASIC) |
  518. BIT(FLOW_DISSECTOR_KEY_META) |
  519. BIT(FLOW_DISSECTOR_KEY_PORTS) |
  520. BIT(FLOW_DISSECTOR_KEY_VLAN) |
  521. BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
  522. BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) |
  523. BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS))) {
  524. return -EOPNOTSUPP;
  525. }
  526. /* For VCAP ES0 (egress rewriter) we can match on the ingress port */
  527. if (!ingress) {
  528. ret = ocelot_flower_parse_indev(ocelot, port, f, filter);
  529. if (ret)
  530. return ret;
  531. }
  532. if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) {
  533. struct flow_match_control match;
  534. flow_rule_match_control(rule, &match);
  535. }
  536. if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {
  537. struct flow_match_vlan match;
  538. flow_rule_match_vlan(rule, &match);
  539. filter->key_type = OCELOT_VCAP_KEY_ANY;
  540. filter->vlan.vid.value = match.key->vlan_id;
  541. filter->vlan.vid.mask = match.mask->vlan_id;
  542. filter->vlan.pcp.value[0] = match.key->vlan_priority;
  543. filter->vlan.pcp.mask[0] = match.mask->vlan_priority;
  544. match_protocol = false;
  545. }
  546. if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
  547. struct flow_match_eth_addrs match;
  548. if (filter->block_id == VCAP_ES0) {
  549. NL_SET_ERR_MSG_MOD(extack,
  550. "VCAP ES0 cannot match on MAC address");
  551. return -EOPNOTSUPP;
  552. }
  553. /* The hw support mac matches only for MAC_ETYPE key,
  554. * therefore if other matches(port, tcp flags, etc) are added
  555. * then just bail out
  556. */
  557. if ((dissector->used_keys &
  558. (BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
  559. BIT(FLOW_DISSECTOR_KEY_BASIC) |
  560. BIT(FLOW_DISSECTOR_KEY_CONTROL))) !=
  561. (BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
  562. BIT(FLOW_DISSECTOR_KEY_BASIC) |
  563. BIT(FLOW_DISSECTOR_KEY_CONTROL)))
  564. return -EOPNOTSUPP;
  565. flow_rule_match_eth_addrs(rule, &match);
  566. if (filter->block_id == VCAP_IS1 &&
  567. !is_zero_ether_addr(match.mask->dst)) {
  568. NL_SET_ERR_MSG_MOD(extack,
  569. "Key type S1_NORMAL cannot match on destination MAC");
  570. return -EOPNOTSUPP;
  571. }
  572. filter->key_type = OCELOT_VCAP_KEY_ETYPE;
  573. ether_addr_copy(filter->key.etype.dmac.value,
  574. match.key->dst);
  575. ether_addr_copy(filter->key.etype.smac.value,
  576. match.key->src);
  577. ether_addr_copy(filter->key.etype.dmac.mask,
  578. match.mask->dst);
  579. ether_addr_copy(filter->key.etype.smac.mask,
  580. match.mask->src);
  581. goto finished_key_parsing;
  582. }
  583. if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
  584. struct flow_match_basic match;
  585. flow_rule_match_basic(rule, &match);
  586. if (ntohs(match.key->n_proto) == ETH_P_IP) {
  587. if (filter->block_id == VCAP_ES0) {
  588. NL_SET_ERR_MSG_MOD(extack,
  589. "VCAP ES0 cannot match on IP protocol");
  590. return -EOPNOTSUPP;
  591. }
  592. filter->key_type = OCELOT_VCAP_KEY_IPV4;
  593. filter->key.ipv4.proto.value[0] =
  594. match.key->ip_proto;
  595. filter->key.ipv4.proto.mask[0] =
  596. match.mask->ip_proto;
  597. match_protocol = false;
  598. }
  599. if (ntohs(match.key->n_proto) == ETH_P_IPV6) {
  600. if (filter->block_id == VCAP_ES0) {
  601. NL_SET_ERR_MSG_MOD(extack,
  602. "VCAP ES0 cannot match on IP protocol");
  603. return -EOPNOTSUPP;
  604. }
  605. filter->key_type = OCELOT_VCAP_KEY_IPV6;
  606. filter->key.ipv6.proto.value[0] =
  607. match.key->ip_proto;
  608. filter->key.ipv6.proto.mask[0] =
  609. match.mask->ip_proto;
  610. match_protocol = false;
  611. }
  612. }
  613. if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS) &&
  614. proto == ETH_P_IP) {
  615. struct flow_match_ipv4_addrs match;
  616. u8 *tmp;
  617. if (filter->block_id == VCAP_ES0) {
  618. NL_SET_ERR_MSG_MOD(extack,
  619. "VCAP ES0 cannot match on IP address");
  620. return -EOPNOTSUPP;
  621. }
  622. flow_rule_match_ipv4_addrs(rule, &match);
  623. if (filter->block_id == VCAP_IS1 && *(u32 *)&match.mask->dst) {
  624. NL_SET_ERR_MSG_MOD(extack,
  625. "Key type S1_NORMAL cannot match on destination IP");
  626. return -EOPNOTSUPP;
  627. }
  628. tmp = &filter->key.ipv4.sip.value.addr[0];
  629. memcpy(tmp, &match.key->src, 4);
  630. tmp = &filter->key.ipv4.sip.mask.addr[0];
  631. memcpy(tmp, &match.mask->src, 4);
  632. tmp = &filter->key.ipv4.dip.value.addr[0];
  633. memcpy(tmp, &match.key->dst, 4);
  634. tmp = &filter->key.ipv4.dip.mask.addr[0];
  635. memcpy(tmp, &match.mask->dst, 4);
  636. match_protocol = false;
  637. }
  638. if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS) &&
  639. proto == ETH_P_IPV6) {
  640. return -EOPNOTSUPP;
  641. }
  642. if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) {
  643. struct flow_match_ports match;
  644. if (filter->block_id == VCAP_ES0) {
  645. NL_SET_ERR_MSG_MOD(extack,
  646. "VCAP ES0 cannot match on L4 ports");
  647. return -EOPNOTSUPP;
  648. }
  649. flow_rule_match_ports(rule, &match);
  650. filter->key.ipv4.sport.value = ntohs(match.key->src);
  651. filter->key.ipv4.sport.mask = ntohs(match.mask->src);
  652. filter->key.ipv4.dport.value = ntohs(match.key->dst);
  653. filter->key.ipv4.dport.mask = ntohs(match.mask->dst);
  654. match_protocol = false;
  655. }
  656. finished_key_parsing:
  657. if (match_protocol && proto != ETH_P_ALL) {
  658. if (filter->block_id == VCAP_ES0) {
  659. NL_SET_ERR_MSG_MOD(extack,
  660. "VCAP ES0 cannot match on L2 proto");
  661. return -EOPNOTSUPP;
  662. }
  663. /* TODO: support SNAP, LLC etc */
  664. if (proto < ETH_P_802_3_MIN)
  665. return -EOPNOTSUPP;
  666. filter->key_type = OCELOT_VCAP_KEY_ETYPE;
  667. *(__be16 *)filter->key.etype.etype.value = htons(proto);
  668. *(__be16 *)filter->key.etype.etype.mask = htons(0xffff);
  669. }
  670. /* else, a filter of type OCELOT_VCAP_KEY_ANY is implicitly added */
  671. return 0;
  672. }
  673. static int ocelot_flower_parse(struct ocelot *ocelot, int port, bool ingress,
  674. struct flow_cls_offload *f,
  675. struct ocelot_vcap_filter *filter)
  676. {
  677. int ret;
  678. filter->prio = f->common.prio;
  679. filter->id.cookie = f->cookie;
  680. filter->id.tc_offload = true;
  681. ret = ocelot_flower_parse_action(ocelot, port, ingress, f, filter);
  682. if (ret)
  683. return ret;
  684. /* PSFP filter need to parse key by stream identification function. */
  685. if (filter->type == OCELOT_PSFP_FILTER_OFFLOAD)
  686. return 0;
  687. return ocelot_flower_parse_key(ocelot, port, ingress, f, filter);
  688. }
  689. static struct ocelot_vcap_filter
  690. *ocelot_vcap_filter_create(struct ocelot *ocelot, int port, bool ingress,
  691. struct flow_cls_offload *f)
  692. {
  693. struct ocelot_vcap_filter *filter;
  694. filter = kzalloc(sizeof(*filter), GFP_KERNEL);
  695. if (!filter)
  696. return NULL;
  697. if (ingress) {
  698. filter->ingress_port_mask = BIT(port);
  699. } else {
  700. const struct vcap_props *vcap = &ocelot->vcap[VCAP_ES0];
  701. int key_length = vcap->keys[VCAP_ES0_EGR_PORT].length;
  702. filter->egress_port.value = port;
  703. filter->egress_port.mask = GENMASK(key_length - 1, 0);
  704. }
  705. return filter;
  706. }
  707. static int ocelot_vcap_dummy_filter_add(struct ocelot *ocelot,
  708. struct ocelot_vcap_filter *filter)
  709. {
  710. list_add(&filter->list, &ocelot->dummy_rules);
  711. return 0;
  712. }
  713. static int ocelot_vcap_dummy_filter_del(struct ocelot *ocelot,
  714. struct ocelot_vcap_filter *filter)
  715. {
  716. list_del(&filter->list);
  717. kfree(filter);
  718. return 0;
  719. }
  720. /* If we have an egress VLAN modification rule, we need to actually write the
  721. * delta between the input VLAN (from the key) and the output VLAN (from the
  722. * action), but the action was parsed first. So we need to patch the delta into
  723. * the action here.
  724. */
  725. static int
  726. ocelot_flower_patch_es0_vlan_modify(struct ocelot_vcap_filter *filter,
  727. struct netlink_ext_ack *extack)
  728. {
  729. if (filter->block_id != VCAP_ES0 ||
  730. filter->action.tag_a_vid_sel != OCELOT_ES0_VID_PLUS_CLASSIFIED_VID)
  731. return 0;
  732. if (filter->vlan.vid.mask != VLAN_VID_MASK) {
  733. NL_SET_ERR_MSG_MOD(extack,
  734. "VCAP ES0 VLAN rewriting needs a full VLAN in the key");
  735. return -EOPNOTSUPP;
  736. }
  737. filter->action.vid_a_val -= filter->vlan.vid.value;
  738. filter->action.vid_a_val &= VLAN_VID_MASK;
  739. return 0;
  740. }
  741. int ocelot_cls_flower_replace(struct ocelot *ocelot, int port,
  742. struct flow_cls_offload *f, bool ingress)
  743. {
  744. struct netlink_ext_ack *extack = f->common.extack;
  745. struct ocelot_vcap_filter *filter;
  746. int chain = f->common.chain_index;
  747. int block_id, ret;
  748. if (chain && !ocelot_find_vcap_filter_that_points_at(ocelot, chain)) {
  749. NL_SET_ERR_MSG_MOD(extack, "No default GOTO action points to this chain");
  750. return -EOPNOTSUPP;
  751. }
  752. block_id = ocelot_chain_to_block(chain, ingress);
  753. if (block_id < 0) {
  754. NL_SET_ERR_MSG_MOD(extack, "Cannot offload to this chain");
  755. return -EOPNOTSUPP;
  756. }
  757. filter = ocelot_vcap_block_find_filter_by_id(&ocelot->block[block_id],
  758. f->cookie, true);
  759. if (filter) {
  760. /* Filter already exists on other ports */
  761. if (!ingress) {
  762. NL_SET_ERR_MSG_MOD(extack, "VCAP ES0 does not support shared filters");
  763. return -EOPNOTSUPP;
  764. }
  765. filter->ingress_port_mask |= BIT(port);
  766. return ocelot_vcap_filter_replace(ocelot, filter);
  767. }
  768. /* Filter didn't exist, create it now */
  769. filter = ocelot_vcap_filter_create(ocelot, port, ingress, f);
  770. if (!filter)
  771. return -ENOMEM;
  772. ret = ocelot_flower_parse(ocelot, port, ingress, f, filter);
  773. if (ret) {
  774. kfree(filter);
  775. return ret;
  776. }
  777. ret = ocelot_flower_patch_es0_vlan_modify(filter, extack);
  778. if (ret) {
  779. kfree(filter);
  780. return ret;
  781. }
  782. /* The non-optional GOTOs for the TCAM skeleton don't need
  783. * to be actually offloaded.
  784. */
  785. if (filter->type == OCELOT_VCAP_FILTER_DUMMY)
  786. return ocelot_vcap_dummy_filter_add(ocelot, filter);
  787. if (filter->type == OCELOT_PSFP_FILTER_OFFLOAD) {
  788. kfree(filter);
  789. if (ocelot->ops->psfp_filter_add)
  790. return ocelot->ops->psfp_filter_add(ocelot, port, f);
  791. NL_SET_ERR_MSG_MOD(extack, "PSFP chain is not supported in HW");
  792. return -EOPNOTSUPP;
  793. }
  794. return ocelot_vcap_filter_add(ocelot, filter, f->common.extack);
  795. }
  796. EXPORT_SYMBOL_GPL(ocelot_cls_flower_replace);
  797. int ocelot_cls_flower_destroy(struct ocelot *ocelot, int port,
  798. struct flow_cls_offload *f, bool ingress)
  799. {
  800. struct ocelot_vcap_filter *filter;
  801. struct ocelot_vcap_block *block;
  802. int block_id;
  803. block_id = ocelot_chain_to_block(f->common.chain_index, ingress);
  804. if (block_id < 0)
  805. return 0;
  806. if (block_id == PSFP_BLOCK_ID) {
  807. if (ocelot->ops->psfp_filter_del)
  808. return ocelot->ops->psfp_filter_del(ocelot, f);
  809. return -EOPNOTSUPP;
  810. }
  811. block = &ocelot->block[block_id];
  812. filter = ocelot_vcap_block_find_filter_by_id(block, f->cookie, true);
  813. if (!filter)
  814. return 0;
  815. if (filter->type == OCELOT_VCAP_FILTER_DUMMY)
  816. return ocelot_vcap_dummy_filter_del(ocelot, filter);
  817. if (ingress) {
  818. filter->ingress_port_mask &= ~BIT(port);
  819. if (filter->ingress_port_mask)
  820. return ocelot_vcap_filter_replace(ocelot, filter);
  821. }
  822. return ocelot_vcap_filter_del(ocelot, filter);
  823. }
  824. EXPORT_SYMBOL_GPL(ocelot_cls_flower_destroy);
  825. int ocelot_cls_flower_stats(struct ocelot *ocelot, int port,
  826. struct flow_cls_offload *f, bool ingress)
  827. {
  828. struct ocelot_vcap_filter *filter;
  829. struct ocelot_vcap_block *block;
  830. struct flow_stats stats = {0};
  831. int block_id, ret;
  832. block_id = ocelot_chain_to_block(f->common.chain_index, ingress);
  833. if (block_id < 0)
  834. return 0;
  835. if (block_id == PSFP_BLOCK_ID) {
  836. if (ocelot->ops->psfp_stats_get) {
  837. ret = ocelot->ops->psfp_stats_get(ocelot, f, &stats);
  838. if (ret)
  839. return ret;
  840. goto stats_update;
  841. }
  842. return -EOPNOTSUPP;
  843. }
  844. block = &ocelot->block[block_id];
  845. filter = ocelot_vcap_block_find_filter_by_id(block, f->cookie, true);
  846. if (!filter || filter->type == OCELOT_VCAP_FILTER_DUMMY)
  847. return 0;
  848. ret = ocelot_vcap_filter_stats_update(ocelot, filter);
  849. if (ret)
  850. return ret;
  851. stats.pkts = filter->stats.pkts;
  852. stats_update:
  853. flow_stats_update(&f->stats, 0x0, stats.pkts, stats.drops, 0x0,
  854. FLOW_ACTION_HW_STATS_IMMEDIATE);
  855. return 0;
  856. }
  857. EXPORT_SYMBOL_GPL(ocelot_cls_flower_stats);