On Tue, Apr 2, 2019 at 4:05 PM Roi Dayan <r...@mellanox.com> wrote:
>
>
>
> On 02/04/2019 12:27, John Hurley wrote:
> > The TC datapath only permits the offload of mirr actions if they are
> > egress. To offload TC actions that output to OvS internal ports, ingress
> > mirr actions are required. At the TC layer, an ingress mirr action passes
> > the packet back into the network stack as if it came in the action port
> > rather than attempting to egress the port.
> >
> > Update OvS-TC offloads to support ingress mirr actions. To ensure packets
> > that match these rules are properly passed into the network stack, add a
> > TC skbedit action along with ingress mirr that sets the pkt_type to
> > PACKET_HOST. This mirrors the functionality of the OvS internal port
> > kernel module.
> >
> > Signed-off-by: John Hurley <john.hur...@netronome.com>
> > Reviewed-by: Simon Horman <simon.hor...@netronome.com>
> > ---
> >  lib/netdev-tc-offloads.c | 15 +++++++++---
> >  lib/tc.c                 | 62 
> > ++++++++++++++++++++++++++++++++++++++++++------
> >  lib/tc.h                 |  5 +++-
> >  3 files changed, 71 insertions(+), 11 deletions(-)
> >
> > diff --git a/lib/netdev-tc-offloads.c b/lib/netdev-tc-offloads.c
> > index f5555e4..78ad023 100644
> > --- a/lib/netdev-tc-offloads.c
> > +++ b/lib/netdev-tc-offloads.c
> > @@ -1,3 +1,4 @@
> > +
> >  /*
> >   * Copyright (c) 2016 Mellanox Technologies, Ltd.
> >   *
> > @@ -52,6 +53,12 @@ struct netlink_field {
> >      int size;
> >  };
> >
> > +static bool
> > +is_internal_port(const char *type)
> > +{
> > +    return !strcmp(type, "internal");
> > +}
> > +
> >  static struct netlink_field set_flower_map[][4] = {
> >      [OVS_KEY_ATTR_IPV4] = {
> >          { offsetof(struct ovs_key_ipv4, ipv4_src),
> > @@ -682,8 +689,9 @@ parse_tc_flower_to_match(struct tc_flower *flower,
> >              }
> >              break;
> >              case TC_ACT_OUTPUT: {
> > -                if (action->ifindex_out) {
> > -                    outport = 
> > netdev_ifindex_to_odp_port(action->ifindex_out);
> > +                if (action->out.ifindex_out) {
> > +                    outport =
> > +                        
> > netdev_ifindex_to_odp_port(action->out.ifindex_out);
> >                      if (!outport) {
> >                          return ENOENT;
> >                      }
> > @@ -1286,7 +1294,8 @@ netdev_tc_flow_put(struct netdev *netdev, struct 
> > match *match,
> >              odp_port_t port = nl_attr_get_odp_port(nla);
> >              struct netdev *outdev = netdev_ports_get(port, 
> > info->dpif_class);
> >
> > -            action->ifindex_out = netdev_get_ifindex(outdev);
> > +            action->out.ifindex_out = netdev_get_ifindex(outdev);
> > +            action->out.ingress = 
> > is_internal_port(netdev_get_type(outdev));
> >              action->type = TC_ACT_OUTPUT;
> >              flower.action_count++;
> >              netdev_close(outdev);
> > diff --git a/lib/tc.c b/lib/tc.c
> > index 07b50b2..3548760 100644
> > --- a/lib/tc.c
> > +++ b/lib/tc.c
> > @@ -25,6 +25,7 @@
> >  #include <linux/tc_act/tc_gact.h>
> >  #include <linux/tc_act/tc_mirred.h>
> >  #include <linux/tc_act/tc_pedit.h>
> > +#include <linux/tc_act/tc_skbedit.h>
> >  #include <linux/tc_act/tc_tunnel_key.h>
> >  #include <linux/tc_act/tc_vlan.h>
> >  #include <linux/gen_stats.h>
> > @@ -1151,14 +1152,20 @@ nl_parse_act_mirred(struct nlattr *options, struct 
> > tc_flower *flower)
> >      mirred_parms = mirred_attrs[TCA_MIRRED_PARMS];
> >      m = nl_attr_get_unspec(mirred_parms, sizeof *m);
> >
> > -    if (m->eaction != TCA_EGRESS_REDIR && m->eaction != TCA_EGRESS_MIRROR) 
> > {
> > +    if (m->eaction != TCA_EGRESS_REDIR && m->eaction != TCA_EGRESS_MIRROR 
> > &&
> > +        m->eaction != TCA_INGRESS_REDIR && m->eaction != 
> > TCA_INGRESS_MIRROR) {
> >          VLOG_ERR_RL(&error_rl, "unknown mirred action: %d, %d, %d",
> >                      m->action, m->eaction, m->ifindex);
> >          return EINVAL;
> >      }
> >
> >      action = &flower->actions[flower->action_count++];
> > -    action->ifindex_out = m->ifindex;
> > +    action->out.ifindex_out = m->ifindex;
> > +    if (m->eaction == TCA_INGRESS_REDIR || m->eaction == 
> > TCA_INGRESS_MIRROR) {
> > +        action->out.ingress = true;
> > +    } else {
> > +        action->out.ingress = false;
> > +    }
> >      action->type = TC_ACT_OUTPUT;
> >
> >      mirred_tm = mirred_attrs[TCA_MIRRED_TM];
> > @@ -1301,6 +1308,8 @@ nl_parse_single_action(struct nlattr *action, struct 
> > tc_flower *flower)
> >          err = nl_parse_act_pedit(act_options, flower);
> >      } else if (!strcmp(act_kind, "csum")) {
> >          nl_parse_act_csum(act_options, flower);
> > +    } else if (!strcmp(act_kind, "skbedit")) {
> > +        /* Added for TC rule only (not in OvS rule) so ignore. */
> >      } else {
> >          VLOG_ERR_RL(&error_rl, "unknown tc action kind: %s", act_kind);
> >          err = EINVAL;
> > @@ -1729,6 +1738,24 @@ nl_msg_put_act_drop(struct ofpbuf *request)
> >  }
> >
> >  static void
> > +nl_msg_put_act_skbedit_to_host(struct ofpbuf *request)
> > +{
> > +    ovs_be16 packet_host = 0;
>
> can you use the PACKET_HOST definition here instead of 0 ?
>

I think that would require more compat code but let me look again.


> > +    size_t offset;
> > +
> > +    nl_msg_put_string(request, TCA_ACT_KIND, "skbedit");
> > +    offset = nl_msg_start_nested(request, TCA_ACT_OPTIONS);
> > +    {
> > +        struct tc_skbedit s = { .action = TC_ACT_PIPE };
> > +
> > +        nl_msg_put_unspec(request, TCA_SKBEDIT_PARMS, &s, sizeof s);
> > +        nl_msg_put_unspec(request, TCA_SKBEDIT_PTYPE, &packet_host,
> > +                          sizeof packet_host);
> > +    }
> > +    nl_msg_end_nested(request, offset);
> > +}
> > +
> > +static void
> >  nl_msg_put_act_mirred(struct ofpbuf *request, int ifindex, int action,
> >                        int eaction)
> >  {
> > @@ -1916,6 +1943,7 @@ nl_msg_put_flower_acts(struct ofpbuf *request, struct 
> > tc_flower *flower)
> >      uint16_t act_index = 1;
> >      struct tc_action *action;
> >      int i, ifindex = 0;
> > +    bool ingress;
> >
> >      offset = nl_msg_start_nested(request, TCA_FLOWER_ACT);
> >      {
> > @@ -1977,19 +2005,39 @@ nl_msg_put_flower_acts(struct ofpbuf *request, 
> > struct tc_flower *flower)
> >              }
> >              break;
> >              case TC_ACT_OUTPUT: {
> > -                ifindex = action->ifindex_out;
> > +                ingress = action->out.ingress;
> > +                ifindex = action->out.ifindex_out;
> >                  if (ifindex < 1) {
> >                      VLOG_ERR_RL(&error_rl, "%s: invalid ifindex: %d, type: 
> > %d",
> >                                  __func__, ifindex, action->type);
> >                      return EINVAL;
> >                  }
> > +
> > +                if (ingress) {
> > +                    /* If redirecting to ingress (internal port) ensure
> > +                     * pkt_type on skb is set to PACKET_HOST. */
> > +                    act_offset = nl_msg_start_nested(request, act_index++);
> > +                    nl_msg_put_act_skbedit_to_host(request);
> > +                    nl_msg_end_nested(request, act_offset);
> > +                }
> > +
> >                  act_offset = nl_msg_start_nested(request, act_index++);
> >                  if (i == flower->action_count - 1) {
> > -                    nl_msg_put_act_mirred(request, ifindex, TC_ACT_STOLEN,
> > -                                          TCA_EGRESS_REDIR);
> > +                    if (ingress) {
> > +                        nl_msg_put_act_mirred(request, ifindex, 
> > TC_ACT_STOLEN,
> > +                                              TCA_INGRESS_REDIR);
> > +                    } else {
> > +                        nl_msg_put_act_mirred(request, ifindex, 
> > TC_ACT_STOLEN,
> > +                                              TCA_EGRESS_REDIR);
> > +                    }
> >                  } else {
> > -                    nl_msg_put_act_mirred(request, ifindex, TC_ACT_PIPE,
> > -                                          TCA_EGRESS_MIRROR);
> > +                    if (ingress) {
> > +                        nl_msg_put_act_mirred(request, ifindex, 
> > TC_ACT_PIPE,
> > +                                              TCA_INGRESS_MIRROR);
> > +                    } else {
> > +                        nl_msg_put_act_mirred(request, ifindex, 
> > TC_ACT_PIPE,
> > +                                              TCA_EGRESS_MIRROR);
> > +                    }
> >                  }
> >                  nl_msg_put_act_cookie(request, &flower->act_cookie);
> >                  nl_msg_end_nested(request, act_offset);
> > diff --git a/lib/tc.h b/lib/tc.h
> > index d374711..154e120 100644
> > --- a/lib/tc.h
> > +++ b/lib/tc.h
> > @@ -147,7 +147,10 @@ enum tc_action_type {
> >
> >  struct tc_action {
> >      union {
> > -        int ifindex_out;
> > +        struct {
> > +            int ifindex_out;
> > +            bool ingress;
> > +        } out;
> >
> >          struct {
> >              ovs_be16 vlan_push_tpid;
> >
_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to