From: Jiri Pirko <jiri@resnulli.us>
To: Victor Nogueira <victor@mojatatu.com>
Cc: jhs@mojatatu.com, davem@davemloft.net, edumazet@google.com,
kuba@kernel.org, pabeni@redhat.com, xiyou.wangcong@gmail.com,
mleitner@redhat.com, vladbu@nvidia.com, paulb@nvidia.com,
pctammela@mojatatu.com, netdev@vger.kernel.org,
kernel@mojatatu.com
Subject: Re: [PATCH net-next RFC v5 1/4] net/sched: act_mirred: Separate mirror and redirect into two distinct functions
Date: Thu, 23 Nov 2023 07:58:48 +0100 [thread overview]
Message-ID: <ZV74KFOpn6PilY72@nanopsycho> (raw)
In-Reply-To: <20231110214618.1883611-2-victor@mojatatu.com>
Fri, Nov 10, 2023 at 10:46:15PM CET, victor@mojatatu.com wrote:
>Separate mirror and redirect code into two into two separate functions
>(tcf_mirror_act and tcf_redirect_act). This not only cleans up the code and
>improves both readability and maintainability in addition to reducing the
>complexity given different expectations for mirroring and redirecting.
>
>This patchset has a use case for the mirror part in action "blockcast".
Patchset? Which one? You mean this patch?
>
>Co-developed-by: Jamal Hadi Salim <jhs@mojatatu.com>
>Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
>Co-developed-by: Pedro Tammela <pctammela@mojatatu.com>
>Signed-off-by: Pedro Tammela <pctammela@mojatatu.com>
>Signed-off-by: Victor Nogueira <victor@mojatatu.com>
>---
> include/net/act_api.h | 85 ++++++++++++++++++++++++++++++++++
> net/sched/act_mirred.c | 103 +++++++++++------------------------------
> 2 files changed, 113 insertions(+), 75 deletions(-)
>
>diff --git a/include/net/act_api.h b/include/net/act_api.h
>index 4ae0580b63ca..8d288040aeb8 100644
>--- a/include/net/act_api.h
>+++ b/include/net/act_api.h
>@@ -12,6 +12,7 @@
> #include <net/pkt_sched.h>
> #include <net/net_namespace.h>
> #include <net/netns/generic.h>
>+#include <net/dst.h>
>
> struct tcf_idrinfo {
> struct mutex lock;
>@@ -293,5 +294,89 @@ static inline void tcf_action_stats_update(struct tc_action *a, u64 bytes,
> #endif
> }
>
>+static inline int tcf_mirred_forward(bool to_ingress, bool nested_call,
>+ struct sk_buff *skb)
>+{
>+ int err;
>+
>+ if (!to_ingress)
>+ err = tcf_dev_queue_xmit(skb, dev_queue_xmit);
>+ else if (nested_call)
>+ err = netif_rx(skb);
>+ else
>+ err = netif_receive_skb(skb);
>+
>+ return err;
>+}
>+
>+static inline struct sk_buff *
>+tcf_mirred_common(struct sk_buff *skb, bool want_ingress, bool dont_clone,
>+ bool expects_nh, struct net_device *dest_dev)
>+{
>+ struct sk_buff *skb_to_send = skb;
>+ bool at_ingress;
>+ int mac_len;
>+ bool at_nh;
>+ int err;
>+
>+ if (unlikely(!(dest_dev->flags & IFF_UP)) ||
>+ !netif_carrier_ok(dest_dev)) {
>+ net_notice_ratelimited("tc mirred to Houston: device %s is down\n",
>+ dest_dev->name);
>+ err = -ENODEV;
>+ goto err_out;
>+ }
>+
>+ if (!dont_clone) {
>+ skb_to_send = skb_clone(skb, GFP_ATOMIC);
>+ if (!skb_to_send) {
>+ err = -ENOMEM;
>+ goto err_out;
>+ }
>+ }
>+
>+ at_ingress = skb_at_tc_ingress(skb);
>+
>+ /* All mirred/redirected skbs should clear previous ct info */
>+ nf_reset_ct(skb_to_send);
>+ if (want_ingress && !at_ingress) /* drop dst for egress -> ingress */
>+ skb_dst_drop(skb_to_send);
>+
>+ at_nh = skb->data == skb_network_header(skb);
>+ if (at_nh != expects_nh) {
>+ mac_len = at_ingress ? skb->mac_len :
>+ skb_network_offset(skb);
>+ if (expects_nh) {
>+ /* target device/action expect data at nh */
>+ skb_pull_rcsum(skb_to_send, mac_len);
>+ } else {
>+ /* target device/action expect data at mac */
>+ skb_push_rcsum(skb_to_send, mac_len);
>+ }
>+ }
>+
>+ skb_to_send->skb_iif = skb->dev->ifindex;
>+ skb_to_send->dev = dest_dev;
>+
>+ return skb_to_send;
>+
>+err_out:
>+ return ERR_PTR(err);
>+}
It's odd to see functions this size as inlined in header files. I don't
think that is good idea.
>+
>+static inline int
>+tcf_redirect_act(struct sk_buff *skb,
>+ bool nested_call, bool want_ingress)
>+{
>+ skb_set_redirected(skb, skb->tc_at_ingress);
>+
>+ return tcf_mirred_forward(want_ingress, nested_call, skb);
>+}
>+
>+static inline int
>+tcf_mirror_act(struct sk_buff *skb, bool nested_call, bool want_ingress)
>+{
>+ return tcf_mirred_forward(want_ingress, nested_call, skb);
>+}
>
> #endif
>diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
>index 0a711c184c29..95d30cb06e54 100644
>--- a/net/sched/act_mirred.c
>+++ b/net/sched/act_mirred.c
>@@ -211,38 +211,22 @@ static bool is_mirred_nested(void)
> return unlikely(__this_cpu_read(mirred_nest_level) > 1);
> }
>
>-static int tcf_mirred_forward(bool want_ingress, struct sk_buff *skb)
>-{
>- int err;
>-
>- if (!want_ingress)
>- err = tcf_dev_queue_xmit(skb, dev_queue_xmit);
>- else if (is_mirred_nested())
>- err = netif_rx(skb);
>- else
>- err = netif_receive_skb(skb);
>-
>- return err;
>-}
>-
> TC_INDIRECT_SCOPE int tcf_mirred_act(struct sk_buff *skb,
> const struct tc_action *a,
> struct tcf_result *res)
> {
> struct tcf_mirred *m = to_mirred(a);
>- struct sk_buff *skb2 = skb;
>+ struct sk_buff *skb_to_send;
>+ unsigned int nest_level;
> bool m_mac_header_xmit;
> struct net_device *dev;
>- unsigned int nest_level;
>- int retval, err = 0;
>- bool use_reinsert;
> bool want_ingress;
> bool is_redirect;
> bool expects_nh;
>- bool at_ingress;
>+ bool dont_clone;
> int m_eaction;
>- int mac_len;
>- bool at_nh;
>+ int err = 0;
>+ int retval;
>
> nest_level = __this_cpu_inc_return(mirred_nest_level);
> if (unlikely(nest_level > MIRRED_NEST_LIMIT)) {
>@@ -255,80 +239,49 @@ TC_INDIRECT_SCOPE int tcf_mirred_act(struct sk_buff *skb,
> tcf_lastuse_update(&m->tcf_tm);
> tcf_action_update_bstats(&m->common, skb);
>
>- m_mac_header_xmit = READ_ONCE(m->tcfm_mac_header_xmit);
> m_eaction = READ_ONCE(m->tcfm_eaction);
>- retval = READ_ONCE(m->tcf_action);
>+ is_redirect = tcf_mirred_is_act_redirect(m_eaction);
>+ retval = READ_ONCE(a->tcfa_action);
> dev = rcu_dereference_bh(m->tcfm_dev);
> if (unlikely(!dev)) {
> pr_notice_once("tc mirred: target device is gone\n");
>+ err = -ENODEV;
> goto out;
> }
>
>- if (unlikely(!(dev->flags & IFF_UP)) || !netif_carrier_ok(dev)) {
>- net_notice_ratelimited("tc mirred to Houston: device %s is down\n",
>- dev->name);
>- goto out;
>- }
>+ m_mac_header_xmit = READ_ONCE(m->tcfm_mac_header_xmit);
>+ want_ingress = tcf_mirred_act_wants_ingress(m_eaction);
>+ expects_nh = want_ingress || !m_mac_header_xmit;
>
> /* we could easily avoid the clone only if called by ingress and clsact;
> * since we can't easily detect the clsact caller, skip clone only for
> * ingress - that covers the TC S/W datapath.
> */
>- is_redirect = tcf_mirred_is_act_redirect(m_eaction);
>- at_ingress = skb_at_tc_ingress(skb);
>- use_reinsert = at_ingress && is_redirect &&
>- tcf_mirred_can_reinsert(retval);
>- if (!use_reinsert) {
>- skb2 = skb_clone(skb, GFP_ATOMIC);
>- if (!skb2)
>- goto out;
>- }
>-
>- want_ingress = tcf_mirred_act_wants_ingress(m_eaction);
>-
>- /* All mirred/redirected skbs should clear previous ct info */
>- nf_reset_ct(skb2);
>- if (want_ingress && !at_ingress) /* drop dst for egress -> ingress */
>- skb_dst_drop(skb2);
>+ dont_clone = skb_at_tc_ingress(skb) && is_redirect &&
>+ tcf_mirred_can_reinsert(retval);
>
>- expects_nh = want_ingress || !m_mac_header_xmit;
>- at_nh = skb->data == skb_network_header(skb);
>- if (at_nh != expects_nh) {
>- mac_len = skb_at_tc_ingress(skb) ? skb->mac_len :
>- skb_network_offset(skb);
>- if (expects_nh) {
>- /* target device/action expect data at nh */
>- skb_pull_rcsum(skb2, mac_len);
>- } else {
>- /* target device/action expect data at mac */
>- skb_push_rcsum(skb2, mac_len);
>- }
>+ skb_to_send = tcf_mirred_common(skb, want_ingress, dont_clone,
>+ expects_nh, dev);
>+ if (IS_ERR(skb_to_send)) {
>+ err = PTR_ERR(skb_to_send);
>+ goto out;
> }
>
>- skb2->skb_iif = skb->dev->ifindex;
>- skb2->dev = dev;
>-
>- /* mirror is always swallowed */
> if (is_redirect) {
>- skb_set_redirected(skb2, skb2->tc_at_ingress);
>-
>- /* let's the caller reinsert the packet, if possible */
>- if (use_reinsert) {
>- err = tcf_mirred_forward(want_ingress, skb);
>- if (err)
>- tcf_action_inc_overlimit_qstats(&m->common);
>- __this_cpu_dec(mirred_nest_level);
>- return TC_ACT_CONSUMED;
>- }
>+ if (skb == skb_to_send)
>+ retval = TC_ACT_CONSUMED;
>+
>+ err = tcf_redirect_act(skb_to_send, is_mirred_nested(),
>+ want_ingress);
>+ } else {
>+ err = tcf_mirror_act(skb_to_send, is_mirred_nested(),
>+ want_ingress);
> }
>
>- err = tcf_mirred_forward(want_ingress, skb2);
>- if (err) {
> out:
>+ if (err)
> tcf_action_inc_overlimit_qstats(&m->common);
>- if (tcf_mirred_is_act_redirect(m_eaction))
>- retval = TC_ACT_SHOT;
>- }
>+
> __this_cpu_dec(mirred_nest_level);
>
> return retval;
>--
>2.25.1
>
next prev parent reply other threads:[~2023-11-23 6:58 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-11-10 21:46 [PATCH net-next RFC v5 0/4] net/sched: Introduce tc block ports tracking and use Victor Nogueira
2023-11-10 21:46 ` [PATCH net-next RFC v5 1/4] net/sched: act_mirred: Separate mirror and redirect into two distinct functions Victor Nogueira
2023-11-23 6:58 ` Jiri Pirko [this message]
2023-11-10 21:46 ` [PATCH net-next RFC v5 2/4] net/sched: Introduce tc block netdev tracking infra Victor Nogueira
2023-11-10 21:46 ` [PATCH net-next RFC v5 3/4] net/sched: cls_api: Expose tc block to the datapath Victor Nogueira
2023-11-10 21:46 ` [PATCH net-next RFC v5 4/4] net/sched: act_blockcast: Introduce blockcast tc action Victor Nogueira
2023-11-23 8:51 ` Jiri Pirko
2023-11-23 13:37 ` Jamal Hadi Salim
2023-11-23 14:04 ` Jiri Pirko
2023-11-23 14:38 ` Jamal Hadi Salim
2023-11-23 15:17 ` Jiri Pirko
2023-11-23 16:20 ` Jamal Hadi Salim
2023-11-23 16:51 ` Jiri Pirko
2023-11-23 16:21 ` Jamal Hadi Salim
2023-11-23 16:52 ` Jiri Pirko
2023-11-27 15:50 ` Jamal Hadi Salim
2023-11-27 18:52 ` Marcelo Ricardo Leitner
2023-12-01 18:45 ` Jamal Hadi Salim
2023-12-04 9:49 ` Jiri Pirko
2023-12-04 20:10 ` Jamal Hadi Salim
2023-12-05 8:41 ` Jiri Pirko
2023-12-05 14:51 ` Marcelo Ricardo Leitner
2023-12-05 15:27 ` Jamal Hadi Salim
2023-12-05 22:12 ` Marcelo Ricardo Leitner
2023-12-06 7:55 ` Jiri Pirko
2023-12-06 15:09 ` Jamal Hadi Salim
2023-11-23 14:29 ` Marcelo Ricardo Leitner
2023-11-23 15:18 ` Jiri Pirko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ZV74KFOpn6PilY72@nanopsycho \
--to=jiri@resnulli.us \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=jhs@mojatatu.com \
--cc=kernel@mojatatu.com \
--cc=kuba@kernel.org \
--cc=mleitner@redhat.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=paulb@nvidia.com \
--cc=pctammela@mojatatu.com \
--cc=victor@mojatatu.com \
--cc=vladbu@nvidia.com \
--cc=xiyou.wangcong@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox