act_skbedit.c 12 KB

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