On Tue, Apr 2, 2019 at 4:05 PM Roi Dayan <[email protected]> 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 <[email protected]>
> > Reviewed-by: Simon Horman <[email protected]>
> > ---
> > 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
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev