1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * net/sched/act_mirred.c packet mirroring and redirect actions
5 * Authors: Jamal Hadi Salim (2002-4)
7 * TODO: Add ingress support (and socket redirect support)
10 #include <linux/types.h>
11 #include <linux/kernel.h>
12 #include <linux/string.h>
13 #include <linux/errno.h>
14 #include <linux/skbuff.h>
15 #include <linux/rtnetlink.h>
16 #include <linux/module.h>
17 #include <linux/init.h>
18 #include <linux/gfp.h>
19 #include <linux/if_arp.h>
20 #include <net/net_namespace.h>
21 #include <net/netlink.h>
23 #include <net/pkt_sched.h>
24 #include <net/pkt_cls.h>
25 #include <linux/tc_act/tc_mirred.h>
26 #include <net/tc_act/tc_mirred.h>
27 #include <net/tc_wrapper.h>
29 static LIST_HEAD(mirred_list
);
30 static DEFINE_SPINLOCK(mirred_list_lock
);
32 #define MIRRED_NEST_LIMIT 4
33 static DEFINE_PER_CPU(unsigned int, mirred_nest_level
);
35 static bool tcf_mirred_is_act_redirect(int action
)
37 return action
== TCA_EGRESS_REDIR
|| action
== TCA_INGRESS_REDIR
;
40 static bool tcf_mirred_act_wants_ingress(int action
)
43 case TCA_EGRESS_REDIR
:
44 case TCA_EGRESS_MIRROR
:
46 case TCA_INGRESS_REDIR
:
47 case TCA_INGRESS_MIRROR
:
54 static bool tcf_mirred_can_reinsert(int action
)
66 static struct net_device
*tcf_mirred_dev_dereference(struct tcf_mirred
*m
)
68 return rcu_dereference_protected(m
->tcfm_dev
,
69 lockdep_is_held(&m
->tcf_lock
));
72 static void tcf_mirred_release(struct tc_action
*a
)
74 struct tcf_mirred
*m
= to_mirred(a
);
75 struct net_device
*dev
;
77 spin_lock(&mirred_list_lock
);
78 list_del(&m
->tcfm_list
);
79 spin_unlock(&mirred_list_lock
);
81 /* last reference to action, no need to lock */
82 dev
= rcu_dereference_protected(m
->tcfm_dev
, 1);
83 netdev_put(dev
, &m
->tcfm_dev_tracker
);
86 static const struct nla_policy mirred_policy
[TCA_MIRRED_MAX
+ 1] = {
87 [TCA_MIRRED_PARMS
] = { .len
= sizeof(struct tc_mirred
) },
88 [TCA_MIRRED_BLOCKID
] = NLA_POLICY_MIN(NLA_U32
, 1),
91 static struct tc_action_ops act_mirred_ops
;
93 static void tcf_mirred_replace_dev(struct tcf_mirred
*m
,
94 struct net_device
*ndev
)
96 struct net_device
*odev
;
98 odev
= rcu_replace_pointer(m
->tcfm_dev
, ndev
,
99 lockdep_is_held(&m
->tcf_lock
));
100 netdev_put(odev
, &m
->tcfm_dev_tracker
);
103 static int tcf_mirred_init(struct net
*net
, struct nlattr
*nla
,
104 struct nlattr
*est
, struct tc_action
**a
,
105 struct tcf_proto
*tp
,
106 u32 flags
, struct netlink_ext_ack
*extack
)
108 struct tc_action_net
*tn
= net_generic(net
, act_mirred_ops
.net_id
);
109 bool bind
= flags
& TCA_ACT_FLAGS_BIND
;
110 struct nlattr
*tb
[TCA_MIRRED_MAX
+ 1];
111 struct tcf_chain
*goto_ch
= NULL
;
112 bool mac_header_xmit
= false;
113 struct tc_mirred
*parm
;
114 struct tcf_mirred
*m
;
120 NL_SET_ERR_MSG_MOD(extack
, "Mirred requires attributes to be passed");
123 ret
= nla_parse_nested_deprecated(tb
, TCA_MIRRED_MAX
, nla
,
124 mirred_policy
, extack
);
127 if (!tb
[TCA_MIRRED_PARMS
]) {
128 NL_SET_ERR_MSG_MOD(extack
, "Missing required mirred parameters");
131 parm
= nla_data(tb
[TCA_MIRRED_PARMS
]);
133 err
= tcf_idr_check_alloc(tn
, &index
, a
, bind
);
140 if (tb
[TCA_MIRRED_BLOCKID
] && parm
->ifindex
) {
141 NL_SET_ERR_MSG_MOD(extack
,
142 "Cannot specify Block ID and dev simultaneously");
144 tcf_idr_release(*a
, bind
);
146 tcf_idr_cleanup(tn
, index
);
151 switch (parm
->eaction
) {
152 case TCA_EGRESS_MIRROR
:
153 case TCA_EGRESS_REDIR
:
154 case TCA_INGRESS_REDIR
:
155 case TCA_INGRESS_MIRROR
:
159 tcf_idr_release(*a
, bind
);
161 tcf_idr_cleanup(tn
, index
);
162 NL_SET_ERR_MSG_MOD(extack
, "Unknown mirred option");
167 if (!parm
->ifindex
&& !tb
[TCA_MIRRED_BLOCKID
]) {
168 tcf_idr_cleanup(tn
, index
);
169 NL_SET_ERR_MSG_MOD(extack
,
170 "Must specify device or block");
173 ret
= tcf_idr_create_from_flags(tn
, index
, est
, a
,
174 &act_mirred_ops
, bind
, flags
);
176 tcf_idr_cleanup(tn
, index
);
180 } else if (!(flags
& TCA_ACT_FLAGS_REPLACE
)) {
181 tcf_idr_release(*a
, bind
);
186 if (ret
== ACT_P_CREATED
)
187 INIT_LIST_HEAD(&m
->tcfm_list
);
189 err
= tcf_action_check_ctrlact(parm
->action
, tp
, &goto_ch
, extack
);
193 spin_lock_bh(&m
->tcf_lock
);
196 struct net_device
*ndev
;
198 ndev
= dev_get_by_index(net
, parm
->ifindex
);
200 spin_unlock_bh(&m
->tcf_lock
);
204 mac_header_xmit
= dev_is_mac_header_xmit(ndev
);
205 tcf_mirred_replace_dev(m
, ndev
);
206 netdev_tracker_alloc(ndev
, &m
->tcfm_dev_tracker
, GFP_ATOMIC
);
207 m
->tcfm_mac_header_xmit
= mac_header_xmit
;
209 } else if (tb
[TCA_MIRRED_BLOCKID
]) {
210 tcf_mirred_replace_dev(m
, NULL
);
211 m
->tcfm_mac_header_xmit
= false;
212 m
->tcfm_blockid
= nla_get_u32(tb
[TCA_MIRRED_BLOCKID
]);
214 goto_ch
= tcf_action_set_ctrlact(*a
, parm
->action
, goto_ch
);
215 m
->tcfm_eaction
= parm
->eaction
;
216 spin_unlock_bh(&m
->tcf_lock
);
218 tcf_chain_put_by_act(goto_ch
);
220 if (ret
== ACT_P_CREATED
) {
221 spin_lock(&mirred_list_lock
);
222 list_add(&m
->tcfm_list
, &mirred_list
);
223 spin_unlock(&mirred_list_lock
);
229 tcf_chain_put_by_act(goto_ch
);
231 tcf_idr_release(*a
, bind
);
236 tcf_mirred_forward(bool at_ingress
, bool want_ingress
, struct sk_buff
*skb
)
241 err
= tcf_dev_queue_xmit(skb
, dev_queue_xmit
);
242 else if (!at_ingress
)
245 err
= netif_receive_skb(skb
);
250 static int tcf_mirred_to_dev(struct sk_buff
*skb
, struct tcf_mirred
*m
,
251 struct net_device
*dev
,
252 const bool m_mac_header_xmit
, int m_eaction
,
255 struct sk_buff
*skb_to_send
= skb
;
265 is_redirect
= tcf_mirred_is_act_redirect(m_eaction
);
266 if (unlikely(!(dev
->flags
& IFF_UP
)) || !netif_carrier_ok(dev
)) {
267 net_notice_ratelimited("tc mirred to Houston: device %s is down\n",
272 /* we could easily avoid the clone only if called by ingress and clsact;
273 * since we can't easily detect the clsact caller, skip clone only for
274 * ingress - that covers the TC S/W datapath.
276 at_ingress
= skb_at_tc_ingress(skb
);
277 dont_clone
= skb_at_tc_ingress(skb
) && is_redirect
&&
278 tcf_mirred_can_reinsert(retval
);
280 skb_to_send
= skb_clone(skb
, GFP_ATOMIC
);
285 want_ingress
= tcf_mirred_act_wants_ingress(m_eaction
);
287 /* All mirred/redirected skbs should clear previous ct info */
288 nf_reset_ct(skb_to_send
);
289 if (want_ingress
&& !at_ingress
) /* drop dst for egress -> ingress */
290 skb_dst_drop(skb_to_send
);
292 expects_nh
= want_ingress
|| !m_mac_header_xmit
;
293 at_nh
= skb
->data
== skb_network_header(skb
);
294 if (at_nh
!= expects_nh
) {
295 mac_len
= at_ingress
? skb
->mac_len
:
296 skb_network_offset(skb
);
298 /* target device/action expect data at nh */
299 skb_pull_rcsum(skb_to_send
, mac_len
);
301 /* target device/action expect data at mac */
302 skb_push_rcsum(skb_to_send
, mac_len
);
306 skb_to_send
->skb_iif
= skb
->dev
->ifindex
;
307 skb_to_send
->dev
= dev
;
310 if (skb
== skb_to_send
)
311 retval
= TC_ACT_CONSUMED
;
313 skb_set_redirected(skb_to_send
, skb_to_send
->tc_at_ingress
);
315 err
= tcf_mirred_forward(at_ingress
, want_ingress
, skb_to_send
);
317 err
= tcf_mirred_forward(at_ingress
, want_ingress
, skb_to_send
);
320 tcf_action_inc_overlimit_qstats(&m
->common
);
326 retval
= TC_ACT_SHOT
;
327 tcf_action_inc_overlimit_qstats(&m
->common
);
331 static int tcf_blockcast_redir(struct sk_buff
*skb
, struct tcf_mirred
*m
,
332 struct tcf_block
*block
, int m_eaction
,
333 const u32 exception_ifindex
, int retval
)
335 struct net_device
*dev_prev
= NULL
;
336 struct net_device
*dev
= NULL
;
340 mirred_eaction
= tcf_mirred_act_wants_ingress(m_eaction
) ?
341 TCA_INGRESS_MIRROR
: TCA_EGRESS_MIRROR
;
343 xa_for_each(&block
->ports
, index
, dev
) {
344 if (index
== exception_ifindex
)
350 tcf_mirred_to_dev(skb
, m
, dev_prev
,
351 dev_is_mac_header_xmit(dev
),
352 mirred_eaction
, retval
);
358 return tcf_mirred_to_dev(skb
, m
, dev_prev
,
359 dev_is_mac_header_xmit(dev_prev
),
365 static int tcf_blockcast_mirror(struct sk_buff
*skb
, struct tcf_mirred
*m
,
366 struct tcf_block
*block
, int m_eaction
,
367 const u32 exception_ifindex
, int retval
)
369 struct net_device
*dev
= NULL
;
372 xa_for_each(&block
->ports
, index
, dev
) {
373 if (index
== exception_ifindex
)
376 tcf_mirred_to_dev(skb
, m
, dev
,
377 dev_is_mac_header_xmit(dev
),
384 static int tcf_blockcast(struct sk_buff
*skb
, struct tcf_mirred
*m
,
385 const u32 blockid
, struct tcf_result
*res
,
388 const u32 exception_ifindex
= skb
->dev
->ifindex
;
389 struct tcf_block
*block
;
393 m_eaction
= READ_ONCE(m
->tcfm_eaction
);
394 is_redirect
= tcf_mirred_is_act_redirect(m_eaction
);
396 /* we are already under rcu protection, so can call block lookup
399 block
= tcf_block_lookup(dev_net(skb
->dev
), blockid
);
400 if (!block
|| xa_empty(&block
->ports
)) {
401 tcf_action_inc_overlimit_qstats(&m
->common
);
406 return tcf_blockcast_redir(skb
, m
, block
, m_eaction
,
407 exception_ifindex
, retval
);
409 /* If it's not redirect, it is mirror */
410 return tcf_blockcast_mirror(skb
, m
, block
, m_eaction
, exception_ifindex
,
414 TC_INDIRECT_SCOPE
int tcf_mirred_act(struct sk_buff
*skb
,
415 const struct tc_action
*a
,
416 struct tcf_result
*res
)
418 struct tcf_mirred
*m
= to_mirred(a
);
419 int retval
= READ_ONCE(m
->tcf_action
);
420 unsigned int nest_level
;
421 bool m_mac_header_xmit
;
422 struct net_device
*dev
;
426 nest_level
= __this_cpu_inc_return(mirred_nest_level
);
427 if (unlikely(nest_level
> MIRRED_NEST_LIMIT
)) {
428 net_warn_ratelimited("Packet exceeded mirred recursion limit on dev %s\n",
429 netdev_name(skb
->dev
));
430 retval
= TC_ACT_SHOT
;
434 tcf_lastuse_update(&m
->tcf_tm
);
435 tcf_action_update_bstats(&m
->common
, skb
);
437 blockid
= READ_ONCE(m
->tcfm_blockid
);
439 retval
= tcf_blockcast(skb
, m
, blockid
, res
, retval
);
443 dev
= rcu_dereference_bh(m
->tcfm_dev
);
444 if (unlikely(!dev
)) {
445 pr_notice_once("tc mirred: target device is gone\n");
446 tcf_action_inc_overlimit_qstats(&m
->common
);
450 m_mac_header_xmit
= READ_ONCE(m
->tcfm_mac_header_xmit
);
451 m_eaction
= READ_ONCE(m
->tcfm_eaction
);
453 retval
= tcf_mirred_to_dev(skb
, m
, dev
, m_mac_header_xmit
, m_eaction
,
457 __this_cpu_dec(mirred_nest_level
);
462 static void tcf_stats_update(struct tc_action
*a
, u64 bytes
, u64 packets
,
463 u64 drops
, u64 lastuse
, bool hw
)
465 struct tcf_mirred
*m
= to_mirred(a
);
466 struct tcf_t
*tm
= &m
->tcf_tm
;
468 tcf_action_update_stats(a
, bytes
, packets
, drops
, hw
);
469 tm
->lastuse
= max_t(u64
, tm
->lastuse
, lastuse
);
472 static int tcf_mirred_dump(struct sk_buff
*skb
, struct tc_action
*a
, int bind
,
475 unsigned char *b
= skb_tail_pointer(skb
);
476 struct tcf_mirred
*m
= to_mirred(a
);
477 struct tc_mirred opt
= {
478 .index
= m
->tcf_index
,
479 .refcnt
= refcount_read(&m
->tcf_refcnt
) - ref
,
480 .bindcnt
= atomic_read(&m
->tcf_bindcnt
) - bind
,
482 struct net_device
*dev
;
486 spin_lock_bh(&m
->tcf_lock
);
487 opt
.action
= m
->tcf_action
;
488 opt
.eaction
= m
->tcfm_eaction
;
489 dev
= tcf_mirred_dev_dereference(m
);
491 opt
.ifindex
= dev
->ifindex
;
493 if (nla_put(skb
, TCA_MIRRED_PARMS
, sizeof(opt
), &opt
))
494 goto nla_put_failure
;
496 blockid
= m
->tcfm_blockid
;
497 if (blockid
&& nla_put_u32(skb
, TCA_MIRRED_BLOCKID
, blockid
))
498 goto nla_put_failure
;
500 tcf_tm_dump(&t
, &m
->tcf_tm
);
501 if (nla_put_64bit(skb
, TCA_MIRRED_TM
, sizeof(t
), &t
, TCA_MIRRED_PAD
))
502 goto nla_put_failure
;
503 spin_unlock_bh(&m
->tcf_lock
);
508 spin_unlock_bh(&m
->tcf_lock
);
513 static int mirred_device_event(struct notifier_block
*unused
,
514 unsigned long event
, void *ptr
)
516 struct net_device
*dev
= netdev_notifier_info_to_dev(ptr
);
517 struct tcf_mirred
*m
;
520 if (event
== NETDEV_UNREGISTER
) {
521 spin_lock(&mirred_list_lock
);
522 list_for_each_entry(m
, &mirred_list
, tcfm_list
) {
523 spin_lock_bh(&m
->tcf_lock
);
524 if (tcf_mirred_dev_dereference(m
) == dev
) {
525 netdev_put(dev
, &m
->tcfm_dev_tracker
);
526 /* Note : no rcu grace period necessary, as
527 * net_device are already rcu protected.
529 RCU_INIT_POINTER(m
->tcfm_dev
, NULL
);
531 spin_unlock_bh(&m
->tcf_lock
);
533 spin_unlock(&mirred_list_lock
);
539 static struct notifier_block mirred_device_notifier
= {
540 .notifier_call
= mirred_device_event
,
543 static void tcf_mirred_dev_put(void *priv
)
545 struct net_device
*dev
= priv
;
550 static struct net_device
*
551 tcf_mirred_get_dev(const struct tc_action
*a
,
552 tc_action_priv_destructor
*destructor
)
554 struct tcf_mirred
*m
= to_mirred(a
);
555 struct net_device
*dev
;
558 dev
= rcu_dereference(m
->tcfm_dev
);
561 *destructor
= tcf_mirred_dev_put
;
568 static size_t tcf_mirred_get_fill_size(const struct tc_action
*act
)
570 return nla_total_size(sizeof(struct tc_mirred
));
573 static void tcf_offload_mirred_get_dev(struct flow_action_entry
*entry
,
574 const struct tc_action
*act
)
576 entry
->dev
= act
->ops
->get_dev(act
, &entry
->destructor
);
579 entry
->destructor_priv
= entry
->dev
;
582 static int tcf_mirred_offload_act_setup(struct tc_action
*act
, void *entry_data
,
583 u32
*index_inc
, bool bind
,
584 struct netlink_ext_ack
*extack
)
587 struct flow_action_entry
*entry
= entry_data
;
589 if (is_tcf_mirred_egress_redirect(act
)) {
590 entry
->id
= FLOW_ACTION_REDIRECT
;
591 tcf_offload_mirred_get_dev(entry
, act
);
592 } else if (is_tcf_mirred_egress_mirror(act
)) {
593 entry
->id
= FLOW_ACTION_MIRRED
;
594 tcf_offload_mirred_get_dev(entry
, act
);
595 } else if (is_tcf_mirred_ingress_redirect(act
)) {
596 entry
->id
= FLOW_ACTION_REDIRECT_INGRESS
;
597 tcf_offload_mirred_get_dev(entry
, act
);
598 } else if (is_tcf_mirred_ingress_mirror(act
)) {
599 entry
->id
= FLOW_ACTION_MIRRED_INGRESS
;
600 tcf_offload_mirred_get_dev(entry
, act
);
602 NL_SET_ERR_MSG_MOD(extack
, "Unsupported mirred offload");
607 struct flow_offload_action
*fl_action
= entry_data
;
609 if (is_tcf_mirred_egress_redirect(act
))
610 fl_action
->id
= FLOW_ACTION_REDIRECT
;
611 else if (is_tcf_mirred_egress_mirror(act
))
612 fl_action
->id
= FLOW_ACTION_MIRRED
;
613 else if (is_tcf_mirred_ingress_redirect(act
))
614 fl_action
->id
= FLOW_ACTION_REDIRECT_INGRESS
;
615 else if (is_tcf_mirred_ingress_mirror(act
))
616 fl_action
->id
= FLOW_ACTION_MIRRED_INGRESS
;
624 static struct tc_action_ops act_mirred_ops
= {
627 .owner
= THIS_MODULE
,
628 .act
= tcf_mirred_act
,
629 .stats_update
= tcf_stats_update
,
630 .dump
= tcf_mirred_dump
,
631 .cleanup
= tcf_mirred_release
,
632 .init
= tcf_mirred_init
,
633 .get_fill_size
= tcf_mirred_get_fill_size
,
634 .offload_act_setup
= tcf_mirred_offload_act_setup
,
635 .size
= sizeof(struct tcf_mirred
),
636 .get_dev
= tcf_mirred_get_dev
,
638 MODULE_ALIAS_NET_ACT("mirred");
640 static __net_init
int mirred_init_net(struct net
*net
)
642 struct tc_action_net
*tn
= net_generic(net
, act_mirred_ops
.net_id
);
644 return tc_action_net_init(net
, tn
, &act_mirred_ops
);
647 static void __net_exit
mirred_exit_net(struct list_head
*net_list
)
649 tc_action_net_exit(net_list
, act_mirred_ops
.net_id
);
652 static struct pernet_operations mirred_net_ops
= {
653 .init
= mirred_init_net
,
654 .exit_batch
= mirred_exit_net
,
655 .id
= &act_mirred_ops
.net_id
,
656 .size
= sizeof(struct tc_action_net
),
659 MODULE_AUTHOR("Jamal Hadi Salim(2002)");
660 MODULE_DESCRIPTION("Device Mirror/redirect actions");
661 MODULE_LICENSE("GPL");
663 static int __init
mirred_init_module(void)
665 int err
= register_netdevice_notifier(&mirred_device_notifier
);
669 pr_info("Mirror/redirect action on\n");
670 err
= tcf_register_action(&act_mirred_ops
, &mirred_net_ops
);
672 unregister_netdevice_notifier(&mirred_device_notifier
);
677 static void __exit
mirred_cleanup_module(void)
679 tcf_unregister_action(&act_mirred_ops
, &mirred_net_ops
);
680 unregister_netdevice_notifier(&mirred_device_notifier
);
683 module_init(mirred_init_module
);
684 module_exit(mirred_cleanup_module
);