/net/sched/act_mirred.c

http://github.com/mirrors/linux · C · 498 lines · 408 code · 70 blank · 20 comment · 57 complexity · 2b84c8dca2cb5bc5d668b8170c7214ff MD5 · raw file

  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * net/sched/act_mirred.c packet mirroring and redirect actions
  4. *
  5. * Authors: Jamal Hadi Salim (2002-4)
  6. *
  7. * TODO: Add ingress support (and socket redirect support)
  8. */
  9. #include <linux/types.h>
  10. #include <linux/kernel.h>
  11. #include <linux/string.h>
  12. #include <linux/errno.h>
  13. #include <linux/skbuff.h>
  14. #include <linux/rtnetlink.h>
  15. #include <linux/module.h>
  16. #include <linux/init.h>
  17. #include <linux/gfp.h>
  18. #include <linux/if_arp.h>
  19. #include <net/net_namespace.h>
  20. #include <net/netlink.h>
  21. #include <net/pkt_sched.h>
  22. #include <net/pkt_cls.h>
  23. #include <linux/tc_act/tc_mirred.h>
  24. #include <net/tc_act/tc_mirred.h>
  25. static LIST_HEAD(mirred_list);
  26. static DEFINE_SPINLOCK(mirred_list_lock);
  27. #define MIRRED_RECURSION_LIMIT 4
  28. static DEFINE_PER_CPU(unsigned int, mirred_rec_level);
  29. static bool tcf_mirred_is_act_redirect(int action)
  30. {
  31. return action == TCA_EGRESS_REDIR || action == TCA_INGRESS_REDIR;
  32. }
  33. static bool tcf_mirred_act_wants_ingress(int action)
  34. {
  35. switch (action) {
  36. case TCA_EGRESS_REDIR:
  37. case TCA_EGRESS_MIRROR:
  38. return false;
  39. case TCA_INGRESS_REDIR:
  40. case TCA_INGRESS_MIRROR:
  41. return true;
  42. default:
  43. BUG();
  44. }
  45. }
  46. static bool tcf_mirred_can_reinsert(int action)
  47. {
  48. switch (action) {
  49. case TC_ACT_SHOT:
  50. case TC_ACT_STOLEN:
  51. case TC_ACT_QUEUED:
  52. case TC_ACT_TRAP:
  53. return true;
  54. }
  55. return false;
  56. }
  57. static struct net_device *tcf_mirred_dev_dereference(struct tcf_mirred *m)
  58. {
  59. return rcu_dereference_protected(m->tcfm_dev,
  60. lockdep_is_held(&m->tcf_lock));
  61. }
  62. static void tcf_mirred_release(struct tc_action *a)
  63. {
  64. struct tcf_mirred *m = to_mirred(a);
  65. struct net_device *dev;
  66. spin_lock(&mirred_list_lock);
  67. list_del(&m->tcfm_list);
  68. spin_unlock(&mirred_list_lock);
  69. /* last reference to action, no need to lock */
  70. dev = rcu_dereference_protected(m->tcfm_dev, 1);
  71. if (dev)
  72. dev_put(dev);
  73. }
  74. static const struct nla_policy mirred_policy[TCA_MIRRED_MAX + 1] = {
  75. [TCA_MIRRED_PARMS] = { .len = sizeof(struct tc_mirred) },
  76. };
  77. static unsigned int mirred_net_id;
  78. static struct tc_action_ops act_mirred_ops;
  79. static int tcf_mirred_init(struct net *net, struct nlattr *nla,
  80. struct nlattr *est, struct tc_action **a,
  81. int ovr, int bind, bool rtnl_held,
  82. struct tcf_proto *tp,
  83. u32 flags, struct netlink_ext_ack *extack)
  84. {
  85. struct tc_action_net *tn = net_generic(net, mirred_net_id);
  86. struct nlattr *tb[TCA_MIRRED_MAX + 1];
  87. struct tcf_chain *goto_ch = NULL;
  88. bool mac_header_xmit = false;
  89. struct tc_mirred *parm;
  90. struct tcf_mirred *m;
  91. struct net_device *dev;
  92. bool exists = false;
  93. int ret, err;
  94. u32 index;
  95. if (!nla) {
  96. NL_SET_ERR_MSG_MOD(extack, "Mirred requires attributes to be passed");
  97. return -EINVAL;
  98. }
  99. ret = nla_parse_nested_deprecated(tb, TCA_MIRRED_MAX, nla,
  100. mirred_policy, extack);
  101. if (ret < 0)
  102. return ret;
  103. if (!tb[TCA_MIRRED_PARMS]) {
  104. NL_SET_ERR_MSG_MOD(extack, "Missing required mirred parameters");
  105. return -EINVAL;
  106. }
  107. parm = nla_data(tb[TCA_MIRRED_PARMS]);
  108. index = parm->index;
  109. err = tcf_idr_check_alloc(tn, &index, a, bind);
  110. if (err < 0)
  111. return err;
  112. exists = err;
  113. if (exists && bind)
  114. return 0;
  115. switch (parm->eaction) {
  116. case TCA_EGRESS_MIRROR:
  117. case TCA_EGRESS_REDIR:
  118. case TCA_INGRESS_REDIR:
  119. case TCA_INGRESS_MIRROR:
  120. break;
  121. default:
  122. if (exists)
  123. tcf_idr_release(*a, bind);
  124. else
  125. tcf_idr_cleanup(tn, index);
  126. NL_SET_ERR_MSG_MOD(extack, "Unknown mirred option");
  127. return -EINVAL;
  128. }
  129. if (!exists) {
  130. if (!parm->ifindex) {
  131. tcf_idr_cleanup(tn, index);
  132. NL_SET_ERR_MSG_MOD(extack, "Specified device does not exist");
  133. return -EINVAL;
  134. }
  135. ret = tcf_idr_create_from_flags(tn, index, est, a,
  136. &act_mirred_ops, bind, flags);
  137. if (ret) {
  138. tcf_idr_cleanup(tn, index);
  139. return ret;
  140. }
  141. ret = ACT_P_CREATED;
  142. } else if (!ovr) {
  143. tcf_idr_release(*a, bind);
  144. return -EEXIST;
  145. }
  146. m = to_mirred(*a);
  147. if (ret == ACT_P_CREATED)
  148. INIT_LIST_HEAD(&m->tcfm_list);
  149. err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack);
  150. if (err < 0)
  151. goto release_idr;
  152. spin_lock_bh(&m->tcf_lock);
  153. if (parm->ifindex) {
  154. dev = dev_get_by_index(net, parm->ifindex);
  155. if (!dev) {
  156. spin_unlock_bh(&m->tcf_lock);
  157. err = -ENODEV;
  158. goto put_chain;
  159. }
  160. mac_header_xmit = dev_is_mac_header_xmit(dev);
  161. dev = rcu_replace_pointer(m->tcfm_dev, dev,
  162. lockdep_is_held(&m->tcf_lock));
  163. if (dev)
  164. dev_put(dev);
  165. m->tcfm_mac_header_xmit = mac_header_xmit;
  166. }
  167. goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);
  168. m->tcfm_eaction = parm->eaction;
  169. spin_unlock_bh(&m->tcf_lock);
  170. if (goto_ch)
  171. tcf_chain_put_by_act(goto_ch);
  172. if (ret == ACT_P_CREATED) {
  173. spin_lock(&mirred_list_lock);
  174. list_add(&m->tcfm_list, &mirred_list);
  175. spin_unlock(&mirred_list_lock);
  176. tcf_idr_insert(tn, *a);
  177. }
  178. return ret;
  179. put_chain:
  180. if (goto_ch)
  181. tcf_chain_put_by_act(goto_ch);
  182. release_idr:
  183. tcf_idr_release(*a, bind);
  184. return err;
  185. }
  186. static int tcf_mirred_act(struct sk_buff *skb, const struct tc_action *a,
  187. struct tcf_result *res)
  188. {
  189. struct tcf_mirred *m = to_mirred(a);
  190. struct sk_buff *skb2 = skb;
  191. bool m_mac_header_xmit;
  192. struct net_device *dev;
  193. unsigned int rec_level;
  194. int retval, err = 0;
  195. bool use_reinsert;
  196. bool want_ingress;
  197. bool is_redirect;
  198. bool expects_nh;
  199. int m_eaction;
  200. int mac_len;
  201. bool at_nh;
  202. rec_level = __this_cpu_inc_return(mirred_rec_level);
  203. if (unlikely(rec_level > MIRRED_RECURSION_LIMIT)) {
  204. net_warn_ratelimited("Packet exceeded mirred recursion limit on dev %s\n",
  205. netdev_name(skb->dev));
  206. __this_cpu_dec(mirred_rec_level);
  207. return TC_ACT_SHOT;
  208. }
  209. tcf_lastuse_update(&m->tcf_tm);
  210. tcf_action_update_bstats(&m->common, skb);
  211. m_mac_header_xmit = READ_ONCE(m->tcfm_mac_header_xmit);
  212. m_eaction = READ_ONCE(m->tcfm_eaction);
  213. retval = READ_ONCE(m->tcf_action);
  214. dev = rcu_dereference_bh(m->tcfm_dev);
  215. if (unlikely(!dev)) {
  216. pr_notice_once("tc mirred: target device is gone\n");
  217. goto out;
  218. }
  219. if (unlikely(!(dev->flags & IFF_UP))) {
  220. net_notice_ratelimited("tc mirred to Houston: device %s is down\n",
  221. dev->name);
  222. goto out;
  223. }
  224. /* we could easily avoid the clone only if called by ingress and clsact;
  225. * since we can't easily detect the clsact caller, skip clone only for
  226. * ingress - that covers the TC S/W datapath.
  227. */
  228. is_redirect = tcf_mirred_is_act_redirect(m_eaction);
  229. use_reinsert = skb_at_tc_ingress(skb) && is_redirect &&
  230. tcf_mirred_can_reinsert(retval);
  231. if (!use_reinsert) {
  232. skb2 = skb_clone(skb, GFP_ATOMIC);
  233. if (!skb2)
  234. goto out;
  235. }
  236. want_ingress = tcf_mirred_act_wants_ingress(m_eaction);
  237. expects_nh = want_ingress || !m_mac_header_xmit;
  238. at_nh = skb->data == skb_network_header(skb);
  239. if (at_nh != expects_nh) {
  240. mac_len = skb_at_tc_ingress(skb) ? skb->mac_len :
  241. skb_network_header(skb) - skb_mac_header(skb);
  242. if (expects_nh) {
  243. /* target device/action expect data at nh */
  244. skb_pull_rcsum(skb2, mac_len);
  245. } else {
  246. /* target device/action expect data at mac */
  247. skb_push_rcsum(skb2, mac_len);
  248. }
  249. }
  250. skb2->skb_iif = skb->dev->ifindex;
  251. skb2->dev = dev;
  252. /* mirror is always swallowed */
  253. if (is_redirect) {
  254. skb_set_redirected(skb2, skb2->tc_at_ingress);
  255. /* let's the caller reinsert the packet, if possible */
  256. if (use_reinsert) {
  257. res->ingress = want_ingress;
  258. if (skb_tc_reinsert(skb, res))
  259. tcf_action_inc_overlimit_qstats(&m->common);
  260. __this_cpu_dec(mirred_rec_level);
  261. return TC_ACT_CONSUMED;
  262. }
  263. }
  264. if (!want_ingress)
  265. err = dev_queue_xmit(skb2);
  266. else
  267. err = netif_receive_skb(skb2);
  268. if (err) {
  269. out:
  270. tcf_action_inc_overlimit_qstats(&m->common);
  271. if (tcf_mirred_is_act_redirect(m_eaction))
  272. retval = TC_ACT_SHOT;
  273. }
  274. __this_cpu_dec(mirred_rec_level);
  275. return retval;
  276. }
  277. static void tcf_stats_update(struct tc_action *a, u64 bytes, u32 packets,
  278. u64 lastuse, bool hw)
  279. {
  280. struct tcf_mirred *m = to_mirred(a);
  281. struct tcf_t *tm = &m->tcf_tm;
  282. tcf_action_update_stats(a, bytes, packets, false, hw);
  283. tm->lastuse = max_t(u64, tm->lastuse, lastuse);
  284. }
  285. static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind,
  286. int ref)
  287. {
  288. unsigned char *b = skb_tail_pointer(skb);
  289. struct tcf_mirred *m = to_mirred(a);
  290. struct tc_mirred opt = {
  291. .index = m->tcf_index,
  292. .refcnt = refcount_read(&m->tcf_refcnt) - ref,
  293. .bindcnt = atomic_read(&m->tcf_bindcnt) - bind,
  294. };
  295. struct net_device *dev;
  296. struct tcf_t t;
  297. spin_lock_bh(&m->tcf_lock);
  298. opt.action = m->tcf_action;
  299. opt.eaction = m->tcfm_eaction;
  300. dev = tcf_mirred_dev_dereference(m);
  301. if (dev)
  302. opt.ifindex = dev->ifindex;
  303. if (nla_put(skb, TCA_MIRRED_PARMS, sizeof(opt), &opt))
  304. goto nla_put_failure;
  305. tcf_tm_dump(&t, &m->tcf_tm);
  306. if (nla_put_64bit(skb, TCA_MIRRED_TM, sizeof(t), &t, TCA_MIRRED_PAD))
  307. goto nla_put_failure;
  308. spin_unlock_bh(&m->tcf_lock);
  309. return skb->len;
  310. nla_put_failure:
  311. spin_unlock_bh(&m->tcf_lock);
  312. nlmsg_trim(skb, b);
  313. return -1;
  314. }
  315. static int tcf_mirred_walker(struct net *net, struct sk_buff *skb,
  316. struct netlink_callback *cb, int type,
  317. const struct tc_action_ops *ops,
  318. struct netlink_ext_ack *extack)
  319. {
  320. struct tc_action_net *tn = net_generic(net, mirred_net_id);
  321. return tcf_generic_walker(tn, skb, cb, type, ops, extack);
  322. }
  323. static int tcf_mirred_search(struct net *net, struct tc_action **a, u32 index)
  324. {
  325. struct tc_action_net *tn = net_generic(net, mirred_net_id);
  326. return tcf_idr_search(tn, a, index);
  327. }
  328. static int mirred_device_event(struct notifier_block *unused,
  329. unsigned long event, void *ptr)
  330. {
  331. struct net_device *dev = netdev_notifier_info_to_dev(ptr);
  332. struct tcf_mirred *m;
  333. ASSERT_RTNL();
  334. if (event == NETDEV_UNREGISTER) {
  335. spin_lock(&mirred_list_lock);
  336. list_for_each_entry(m, &mirred_list, tcfm_list) {
  337. spin_lock_bh(&m->tcf_lock);
  338. if (tcf_mirred_dev_dereference(m) == dev) {
  339. dev_put(dev);
  340. /* Note : no rcu grace period necessary, as
  341. * net_device are already rcu protected.
  342. */
  343. RCU_INIT_POINTER(m->tcfm_dev, NULL);
  344. }
  345. spin_unlock_bh(&m->tcf_lock);
  346. }
  347. spin_unlock(&mirred_list_lock);
  348. }
  349. return NOTIFY_DONE;
  350. }
  351. static struct notifier_block mirred_device_notifier = {
  352. .notifier_call = mirred_device_event,
  353. };
  354. static void tcf_mirred_dev_put(void *priv)
  355. {
  356. struct net_device *dev = priv;
  357. dev_put(dev);
  358. }
  359. static struct net_device *
  360. tcf_mirred_get_dev(const struct tc_action *a,
  361. tc_action_priv_destructor *destructor)
  362. {
  363. struct tcf_mirred *m = to_mirred(a);
  364. struct net_device *dev;
  365. rcu_read_lock();
  366. dev = rcu_dereference(m->tcfm_dev);
  367. if (dev) {
  368. dev_hold(dev);
  369. *destructor = tcf_mirred_dev_put;
  370. }
  371. rcu_read_unlock();
  372. return dev;
  373. }
  374. static size_t tcf_mirred_get_fill_size(const struct tc_action *act)
  375. {
  376. return nla_total_size(sizeof(struct tc_mirred));
  377. }
  378. static struct tc_action_ops act_mirred_ops = {
  379. .kind = "mirred",
  380. .id = TCA_ID_MIRRED,
  381. .owner = THIS_MODULE,
  382. .act = tcf_mirred_act,
  383. .stats_update = tcf_stats_update,
  384. .dump = tcf_mirred_dump,
  385. .cleanup = tcf_mirred_release,
  386. .init = tcf_mirred_init,
  387. .walk = tcf_mirred_walker,
  388. .lookup = tcf_mirred_search,
  389. .get_fill_size = tcf_mirred_get_fill_size,
  390. .size = sizeof(struct tcf_mirred),
  391. .get_dev = tcf_mirred_get_dev,
  392. };
  393. static __net_init int mirred_init_net(struct net *net)
  394. {
  395. struct tc_action_net *tn = net_generic(net, mirred_net_id);
  396. return tc_action_net_init(net, tn, &act_mirred_ops);
  397. }
  398. static void __net_exit mirred_exit_net(struct list_head *net_list)
  399. {
  400. tc_action_net_exit(net_list, mirred_net_id);
  401. }
  402. static struct pernet_operations mirred_net_ops = {
  403. .init = mirred_init_net,
  404. .exit_batch = mirred_exit_net,
  405. .id = &mirred_net_id,
  406. .size = sizeof(struct tc_action_net),
  407. };
  408. MODULE_AUTHOR("Jamal Hadi Salim(2002)");
  409. MODULE_DESCRIPTION("Device Mirror/redirect actions");
  410. MODULE_LICENSE("GPL");
  411. static int __init mirred_init_module(void)
  412. {
  413. int err = register_netdevice_notifier(&mirred_device_notifier);
  414. if (err)
  415. return err;
  416. pr_info("Mirror/redirect action on\n");
  417. err = tcf_register_action(&act_mirred_ops, &mirred_net_ops);
  418. if (err)
  419. unregister_netdevice_notifier(&mirred_device_notifier);
  420. return err;
  421. }
  422. static void __exit mirred_cleanup_module(void)
  423. {
  424. tcf_unregister_action(&act_mirred_ops, &mirred_net_ops);
  425. unregister_netdevice_notifier(&mirred_device_notifier);
  426. }
  427. module_init(mirred_init_module);
  428. module_exit(mirred_cleanup_module);