act_skbedit.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2008, Intel Corporation.
  4. *
  5. * Author: Alexander Duyck <alexander.h.duyck@intel.com>
  6. */
  7. #include <linux/module.h>
  8. #include <linux/init.h>
  9. #include <linux/kernel.h>
  10. #include <linux/skbuff.h>
  11. #include <linux/rtnetlink.h>
  12. #include <net/netlink.h>
  13. #include <net/pkt_sched.h>
  14. #include <net/ip.h>
  15. #include <net/ipv6.h>
  16. #include <net/dsfield.h>
  17. #include <net/pkt_cls.h>
  18. #include <net/tc_wrapper.h>
  19. #include <linux/tc_act/tc_skbedit.h>
  20. #include <net/tc_act/tc_skbedit.h>
  21. static struct tc_action_ops act_skbedit_ops;
  22. static u16 tcf_skbedit_hash(struct tcf_skbedit_params *params,
  23. struct sk_buff *skb)
  24. {
  25. u16 queue_mapping = params->queue_mapping;
  26. if (params->flags & SKBEDIT_F_TXQ_SKBHASH) {
  27. u32 hash = skb_get_hash(skb);
  28. queue_mapping += hash % params->mapping_mod;
  29. }
  30. return netdev_cap_txqueue(skb->dev, queue_mapping);
  31. }
  32. TC_INDIRECT_SCOPE int tcf_skbedit_act(struct sk_buff *skb,
  33. const struct tc_action *a,
  34. struct tcf_result *res)
  35. {
  36. struct tcf_skbedit *d = to_skbedit(a);
  37. struct tcf_skbedit_params *params;
  38. int action;
  39. tcf_lastuse_update(&d->tcf_tm);
  40. bstats_update(this_cpu_ptr(d->common.cpu_bstats), skb);
  41. params = rcu_dereference_bh(d->params);
  42. action = READ_ONCE(d->tcf_action);
  43. if (params->flags & SKBEDIT_F_PRIORITY)
  44. skb->priority = params->priority;
  45. if (params->flags & SKBEDIT_F_INHERITDSFIELD) {
  46. int wlen = skb_network_offset(skb);
  47. switch (skb_protocol(skb, true)) {
  48. case htons(ETH_P_IP):
  49. wlen += sizeof(struct iphdr);
  50. if (!pskb_may_pull(skb, wlen))
  51. goto err;
  52. skb->priority = ipv4_get_dsfield(ip_hdr(skb)) >> 2;
  53. break;
  54. case htons(ETH_P_IPV6):
  55. wlen += sizeof(struct ipv6hdr);
  56. if (!pskb_may_pull(skb, wlen))
  57. goto err;
  58. skb->priority = ipv6_get_dsfield(ipv6_hdr(skb)) >> 2;
  59. break;
  60. }
  61. }
  62. if (params->flags & SKBEDIT_F_QUEUE_MAPPING &&
  63. skb->dev->real_num_tx_queues > params->queue_mapping) {
  64. #ifdef CONFIG_NET_EGRESS
  65. netdev_xmit_skip_txqueue(true);
  66. #endif
  67. skb_set_queue_mapping(skb, tcf_skbedit_hash(params, skb));
  68. }
  69. if (params->flags & SKBEDIT_F_MARK) {
  70. skb->mark &= ~params->mask;
  71. skb->mark |= params->mark & params->mask;
  72. }
  73. if (params->flags & SKBEDIT_F_PTYPE)
  74. skb->pkt_type = params->ptype;
  75. return action;
  76. err:
  77. qstats_drop_inc(this_cpu_ptr(d->common.cpu_qstats));
  78. return TC_ACT_SHOT;
  79. }
  80. static void tcf_skbedit_stats_update(struct tc_action *a, u64 bytes,
  81. u64 packets, u64 drops,
  82. u64 lastuse, bool hw)
  83. {
  84. struct tcf_skbedit *d = to_skbedit(a);
  85. struct tcf_t *tm = &d->tcf_tm;
  86. tcf_action_update_stats(a, bytes, packets, drops, hw);
  87. tm->lastuse = max_t(u64, tm->lastuse, lastuse);
  88. }
  89. static const struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX + 1] = {
  90. [TCA_SKBEDIT_PARMS] = { .len = sizeof(struct tc_skbedit) },
  91. [TCA_SKBEDIT_PRIORITY] = { .len = sizeof(u32) },
  92. [TCA_SKBEDIT_QUEUE_MAPPING] = { .len = sizeof(u16) },
  93. [TCA_SKBEDIT_MARK] = { .len = sizeof(u32) },
  94. [TCA_SKBEDIT_PTYPE] = { .len = sizeof(u16) },
  95. [TCA_SKBEDIT_MASK] = { .len = sizeof(u32) },
  96. [TCA_SKBEDIT_FLAGS] = { .len = sizeof(u64) },
  97. [TCA_SKBEDIT_QUEUE_MAPPING_MAX] = { .len = sizeof(u16) },
  98. };
  99. static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
  100. struct nlattr *est, struct tc_action **a,
  101. struct tcf_proto *tp, u32 act_flags,
  102. struct netlink_ext_ack *extack)
  103. {
  104. struct tc_action_net *tn = net_generic(net, act_skbedit_ops.net_id);
  105. bool bind = act_flags & TCA_ACT_FLAGS_BIND;
  106. struct tcf_skbedit_params *params_new;
  107. struct nlattr *tb[TCA_SKBEDIT_MAX + 1];
  108. struct tcf_chain *goto_ch = NULL;
  109. struct tc_skbedit *parm;
  110. struct tcf_skbedit *d;
  111. u32 flags = 0, *priority = NULL, *mark = NULL, *mask = NULL;
  112. u16 *queue_mapping = NULL, *ptype = NULL;
  113. u16 mapping_mod = 1;
  114. bool exists = false;
  115. int ret = 0, err;
  116. u32 index;
  117. if (nla == NULL)
  118. return -EINVAL;
  119. err = nla_parse_nested_deprecated(tb, TCA_SKBEDIT_MAX, nla,
  120. skbedit_policy, NULL);
  121. if (err < 0)
  122. return err;
  123. if (tb[TCA_SKBEDIT_PARMS] == NULL)
  124. return -EINVAL;
  125. if (tb[TCA_SKBEDIT_PRIORITY] != NULL) {
  126. flags |= SKBEDIT_F_PRIORITY;
  127. priority = nla_data(tb[TCA_SKBEDIT_PRIORITY]);
  128. }
  129. if (tb[TCA_SKBEDIT_QUEUE_MAPPING] != NULL) {
  130. if (is_tcf_skbedit_ingress(act_flags) &&
  131. !(act_flags & TCA_ACT_FLAGS_SKIP_SW)) {
  132. NL_SET_ERR_MSG_MOD(extack, "\"queue_mapping\" option on receive side is hardware only, use skip_sw");
  133. return -EOPNOTSUPP;
  134. }
  135. flags |= SKBEDIT_F_QUEUE_MAPPING;
  136. queue_mapping = nla_data(tb[TCA_SKBEDIT_QUEUE_MAPPING]);
  137. }
  138. if (tb[TCA_SKBEDIT_PTYPE] != NULL) {
  139. ptype = nla_data(tb[TCA_SKBEDIT_PTYPE]);
  140. if (!skb_pkt_type_ok(*ptype))
  141. return -EINVAL;
  142. flags |= SKBEDIT_F_PTYPE;
  143. }
  144. if (tb[TCA_SKBEDIT_MARK] != NULL) {
  145. flags |= SKBEDIT_F_MARK;
  146. mark = nla_data(tb[TCA_SKBEDIT_MARK]);
  147. }
  148. if (tb[TCA_SKBEDIT_MASK] != NULL) {
  149. flags |= SKBEDIT_F_MASK;
  150. mask = nla_data(tb[TCA_SKBEDIT_MASK]);
  151. }
  152. if (tb[TCA_SKBEDIT_FLAGS] != NULL) {
  153. u64 *pure_flags = nla_data(tb[TCA_SKBEDIT_FLAGS]);
  154. if (*pure_flags & SKBEDIT_F_TXQ_SKBHASH) {
  155. u16 *queue_mapping_max;
  156. if (!tb[TCA_SKBEDIT_QUEUE_MAPPING] ||
  157. !tb[TCA_SKBEDIT_QUEUE_MAPPING_MAX]) {
  158. NL_SET_ERR_MSG_MOD(extack, "Missing required range of queue_mapping.");
  159. return -EINVAL;
  160. }
  161. queue_mapping_max =
  162. nla_data(tb[TCA_SKBEDIT_QUEUE_MAPPING_MAX]);
  163. if (*queue_mapping_max < *queue_mapping) {
  164. NL_SET_ERR_MSG_MOD(extack, "The range of queue_mapping is invalid, max < min.");
  165. return -EINVAL;
  166. }
  167. mapping_mod = *queue_mapping_max - *queue_mapping + 1;
  168. flags |= SKBEDIT_F_TXQ_SKBHASH;
  169. }
  170. if (*pure_flags & SKBEDIT_F_INHERITDSFIELD)
  171. flags |= SKBEDIT_F_INHERITDSFIELD;
  172. }
  173. parm = nla_data(tb[TCA_SKBEDIT_PARMS]);
  174. index = parm->index;
  175. err = tcf_idr_check_alloc(tn, &index, a, bind);
  176. if (err < 0)
  177. return err;
  178. exists = err;
  179. if (exists && bind)
  180. return ACT_P_BOUND;
  181. if (!flags) {
  182. if (exists)
  183. tcf_idr_release(*a, bind);
  184. else
  185. tcf_idr_cleanup(tn, index);
  186. return -EINVAL;
  187. }
  188. if (!exists) {
  189. ret = tcf_idr_create(tn, index, est, a,
  190. &act_skbedit_ops, bind, true, act_flags);
  191. if (ret) {
  192. tcf_idr_cleanup(tn, index);
  193. return ret;
  194. }
  195. d = to_skbedit(*a);
  196. ret = ACT_P_CREATED;
  197. } else {
  198. d = to_skbedit(*a);
  199. if (!(act_flags & TCA_ACT_FLAGS_REPLACE)) {
  200. tcf_idr_release(*a, bind);
  201. return -EEXIST;
  202. }
  203. }
  204. err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack);
  205. if (err < 0)
  206. goto release_idr;
  207. params_new = kzalloc(sizeof(*params_new), GFP_KERNEL);
  208. if (unlikely(!params_new)) {
  209. err = -ENOMEM;
  210. goto put_chain;
  211. }
  212. params_new->flags = flags;
  213. if (flags & SKBEDIT_F_PRIORITY)
  214. params_new->priority = *priority;
  215. if (flags & SKBEDIT_F_QUEUE_MAPPING) {
  216. params_new->queue_mapping = *queue_mapping;
  217. params_new->mapping_mod = mapping_mod;
  218. }
  219. if (flags & SKBEDIT_F_MARK)
  220. params_new->mark = *mark;
  221. if (flags & SKBEDIT_F_PTYPE)
  222. params_new->ptype = *ptype;
  223. /* default behaviour is to use all the bits */
  224. params_new->mask = 0xffffffff;
  225. if (flags & SKBEDIT_F_MASK)
  226. params_new->mask = *mask;
  227. spin_lock_bh(&d->tcf_lock);
  228. goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);
  229. params_new = rcu_replace_pointer(d->params, params_new,
  230. lockdep_is_held(&d->tcf_lock));
  231. spin_unlock_bh(&d->tcf_lock);
  232. if (params_new)
  233. kfree_rcu(params_new, rcu);
  234. if (goto_ch)
  235. tcf_chain_put_by_act(goto_ch);
  236. return ret;
  237. put_chain:
  238. if (goto_ch)
  239. tcf_chain_put_by_act(goto_ch);
  240. release_idr:
  241. tcf_idr_release(*a, bind);
  242. return err;
  243. }
  244. static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a,
  245. int bind, int ref)
  246. {
  247. unsigned char *b = skb_tail_pointer(skb);
  248. struct tcf_skbedit *d = to_skbedit(a);
  249. struct tcf_skbedit_params *params;
  250. struct tc_skbedit opt = {
  251. .index = d->tcf_index,
  252. .refcnt = refcount_read(&d->tcf_refcnt) - ref,
  253. .bindcnt = atomic_read(&d->tcf_bindcnt) - bind,
  254. };
  255. u64 pure_flags = 0;
  256. struct tcf_t t;
  257. spin_lock_bh(&d->tcf_lock);
  258. params = rcu_dereference_protected(d->params,
  259. lockdep_is_held(&d->tcf_lock));
  260. opt.action = d->tcf_action;
  261. if (nla_put(skb, TCA_SKBEDIT_PARMS, sizeof(opt), &opt))
  262. goto nla_put_failure;
  263. if ((params->flags & SKBEDIT_F_PRIORITY) &&
  264. nla_put_u32(skb, TCA_SKBEDIT_PRIORITY, params->priority))
  265. goto nla_put_failure;
  266. if ((params->flags & SKBEDIT_F_QUEUE_MAPPING) &&
  267. nla_put_u16(skb, TCA_SKBEDIT_QUEUE_MAPPING, params->queue_mapping))
  268. goto nla_put_failure;
  269. if ((params->flags & SKBEDIT_F_MARK) &&
  270. nla_put_u32(skb, TCA_SKBEDIT_MARK, params->mark))
  271. goto nla_put_failure;
  272. if ((params->flags & SKBEDIT_F_PTYPE) &&
  273. nla_put_u16(skb, TCA_SKBEDIT_PTYPE, params->ptype))
  274. goto nla_put_failure;
  275. if ((params->flags & SKBEDIT_F_MASK) &&
  276. nla_put_u32(skb, TCA_SKBEDIT_MASK, params->mask))
  277. goto nla_put_failure;
  278. if (params->flags & SKBEDIT_F_INHERITDSFIELD)
  279. pure_flags |= SKBEDIT_F_INHERITDSFIELD;
  280. if (params->flags & SKBEDIT_F_TXQ_SKBHASH) {
  281. if (nla_put_u16(skb, TCA_SKBEDIT_QUEUE_MAPPING_MAX,
  282. params->queue_mapping + params->mapping_mod - 1))
  283. goto nla_put_failure;
  284. pure_flags |= SKBEDIT_F_TXQ_SKBHASH;
  285. }
  286. if (pure_flags != 0 &&
  287. nla_put(skb, TCA_SKBEDIT_FLAGS, sizeof(pure_flags), &pure_flags))
  288. goto nla_put_failure;
  289. tcf_tm_dump(&t, &d->tcf_tm);
  290. if (nla_put_64bit(skb, TCA_SKBEDIT_TM, sizeof(t), &t, TCA_SKBEDIT_PAD))
  291. goto nla_put_failure;
  292. spin_unlock_bh(&d->tcf_lock);
  293. return skb->len;
  294. nla_put_failure:
  295. spin_unlock_bh(&d->tcf_lock);
  296. nlmsg_trim(skb, b);
  297. return -1;
  298. }
  299. static void tcf_skbedit_cleanup(struct tc_action *a)
  300. {
  301. struct tcf_skbedit *d = to_skbedit(a);
  302. struct tcf_skbedit_params *params;
  303. params = rcu_dereference_protected(d->params, 1);
  304. if (params)
  305. kfree_rcu(params, rcu);
  306. }
  307. static size_t tcf_skbedit_get_fill_size(const struct tc_action *act)
  308. {
  309. return nla_total_size(sizeof(struct tc_skbedit))
  310. + nla_total_size(sizeof(u32)) /* TCA_SKBEDIT_PRIORITY */
  311. + nla_total_size(sizeof(u16)) /* TCA_SKBEDIT_QUEUE_MAPPING */
  312. + nla_total_size(sizeof(u16)) /* TCA_SKBEDIT_QUEUE_MAPPING_MAX */
  313. + nla_total_size(sizeof(u32)) /* TCA_SKBEDIT_MARK */
  314. + nla_total_size(sizeof(u16)) /* TCA_SKBEDIT_PTYPE */
  315. + nla_total_size(sizeof(u32)) /* TCA_SKBEDIT_MASK */
  316. + nla_total_size_64bit(sizeof(u64)); /* TCA_SKBEDIT_FLAGS */
  317. }
  318. static int tcf_skbedit_offload_act_setup(struct tc_action *act, void *entry_data,
  319. u32 *index_inc, bool bind,
  320. struct netlink_ext_ack *extack)
  321. {
  322. if (bind) {
  323. struct flow_action_entry *entry = entry_data;
  324. if (is_tcf_skbedit_mark(act)) {
  325. entry->id = FLOW_ACTION_MARK;
  326. entry->mark = tcf_skbedit_mark(act);
  327. } else if (is_tcf_skbedit_ptype(act)) {
  328. entry->id = FLOW_ACTION_PTYPE;
  329. entry->ptype = tcf_skbedit_ptype(act);
  330. } else if (is_tcf_skbedit_priority(act)) {
  331. entry->id = FLOW_ACTION_PRIORITY;
  332. entry->priority = tcf_skbedit_priority(act);
  333. } else if (is_tcf_skbedit_tx_queue_mapping(act)) {
  334. NL_SET_ERR_MSG_MOD(extack, "Offload not supported when \"queue_mapping\" option is used on transmit side");
  335. return -EOPNOTSUPP;
  336. } else if (is_tcf_skbedit_rx_queue_mapping(act)) {
  337. entry->id = FLOW_ACTION_RX_QUEUE_MAPPING;
  338. entry->rx_queue = tcf_skbedit_rx_queue_mapping(act);
  339. } else if (is_tcf_skbedit_inheritdsfield(act)) {
  340. NL_SET_ERR_MSG_MOD(extack, "Offload not supported when \"inheritdsfield\" option is used");
  341. return -EOPNOTSUPP;
  342. } else {
  343. NL_SET_ERR_MSG_MOD(extack, "Unsupported skbedit option offload");
  344. return -EOPNOTSUPP;
  345. }
  346. *index_inc = 1;
  347. } else {
  348. struct flow_offload_action *fl_action = entry_data;
  349. if (is_tcf_skbedit_mark(act))
  350. fl_action->id = FLOW_ACTION_MARK;
  351. else if (is_tcf_skbedit_ptype(act))
  352. fl_action->id = FLOW_ACTION_PTYPE;
  353. else if (is_tcf_skbedit_priority(act))
  354. fl_action->id = FLOW_ACTION_PRIORITY;
  355. else if (is_tcf_skbedit_rx_queue_mapping(act))
  356. fl_action->id = FLOW_ACTION_RX_QUEUE_MAPPING;
  357. else
  358. return -EOPNOTSUPP;
  359. }
  360. return 0;
  361. }
  362. static struct tc_action_ops act_skbedit_ops = {
  363. .kind = "skbedit",
  364. .id = TCA_ID_SKBEDIT,
  365. .owner = THIS_MODULE,
  366. .act = tcf_skbedit_act,
  367. .stats_update = tcf_skbedit_stats_update,
  368. .dump = tcf_skbedit_dump,
  369. .init = tcf_skbedit_init,
  370. .cleanup = tcf_skbedit_cleanup,
  371. .get_fill_size = tcf_skbedit_get_fill_size,
  372. .offload_act_setup = tcf_skbedit_offload_act_setup,
  373. .size = sizeof(struct tcf_skbedit),
  374. };
  375. MODULE_ALIAS_NET_ACT("skbedit");
  376. static __net_init int skbedit_init_net(struct net *net)
  377. {
  378. struct tc_action_net *tn = net_generic(net, act_skbedit_ops.net_id);
  379. return tc_action_net_init(net, tn, &act_skbedit_ops);
  380. }
  381. static void __net_exit skbedit_exit_net(struct list_head *net_list)
  382. {
  383. tc_action_net_exit(net_list, act_skbedit_ops.net_id);
  384. }
  385. static struct pernet_operations skbedit_net_ops = {
  386. .init = skbedit_init_net,
  387. .exit_batch = skbedit_exit_net,
  388. .id = &act_skbedit_ops.net_id,
  389. .size = sizeof(struct tc_action_net),
  390. };
  391. MODULE_AUTHOR("Alexander Duyck, <alexander.h.duyck@intel.com>");
  392. MODULE_DESCRIPTION("SKB Editing");
  393. MODULE_LICENSE("GPL");
  394. static int __init skbedit_init_module(void)
  395. {
  396. return tcf_register_action(&act_skbedit_ops, &skbedit_net_ops);
  397. }
  398. static void __exit skbedit_cleanup_module(void)
  399. {
  400. tcf_unregister_action(&act_skbedit_ops, &skbedit_net_ops);
  401. }
  402. module_init(skbedit_init_module);
  403. module_exit(skbedit_cleanup_module);