Message ID | 20200621111924.12397-8-elibr@mellanox.com |
---|---|
State | Changes Requested |
Headers | show |
Series | netdev datapath offload: Support IPv6 and VXLAN encap | expand |
On 6/21/20 1:19 PM, Eli Britstein wrote: > Tunnel encapsulation is done by tnl_push and output actions nested in a > clone action. Support offloading of such flows with > RTE_FLOW_ACTION_TYPE_RAW_ENCAP attribute. > > Signed-off-by: Eli Britstein <elibr@mellanox.com> > Reviewed-by: Oz Shlomo <ozsh@mellanox.com> > --- > Documentation/howto/dpdk.rst | 1 + > NEWS | 2 +- > lib/netdev-offload-dpdk.c | 57 ++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 59 insertions(+), 1 deletion(-) > > diff --git a/Documentation/howto/dpdk.rst b/Documentation/howto/dpdk.rst > index 1756a7149..724c837f5 100644 > --- a/Documentation/howto/dpdk.rst > +++ b/Documentation/howto/dpdk.rst > @@ -396,6 +396,7 @@ Supported actions for hardware offload are: > - Modification of IPv4 (mod_nw_src/mod_nw_dst/mod_nw_ttl). > - Modification of TCP/UDP (mod_tp_src/mod_tp_dst). > - Modification of IPv6 (set_field:<ADDR>->ipv6_src/ipv6_dst/mod_nw_ttl). > +- Clone/output (tnl_push and output) for encapsulating over a tunnel. > > Further Reading > --------------- > diff --git a/NEWS b/NEWS > index 7df8b134d..e7d3ca3c8 100644 > --- a/NEWS > +++ b/NEWS > @@ -11,7 +11,7 @@ Post-v2.13.0 > * Deprecated DPDK ring ports (dpdkr) are no longer supported. > * Add hardware offload support for matching IPv6 protocol. > * Add hardware offload support for set of IPv6 TCP/UDP ports > - actions (experimental). > + and tunnel push-output actions (experimental). > - Linux datapath: > * Support for kernel versions up to 5.5.x. > - AF_XDP: > diff --git a/lib/netdev-offload-dpdk.c b/lib/netdev-offload-dpdk.c > index 13259a669..16df1fedd 100644 > --- a/lib/netdev-offload-dpdk.c > +++ b/lib/netdev-offload-dpdk.c > @@ -475,6 +475,17 @@ dump_flow_action(struct ds *s, const struct rte_flow_action *actions) > } else { > ds_put_format(s, " Set-ipv6-%s = null\n", dirstr); > } > + } else if (actions->type == RTE_FLOW_ACTION_TYPE_RAW_ENCAP) { > + const struct rte_flow_action_raw_encap *raw_encap = actions->conf; > + > + ds_put_cstr(s, "rte flow raw-encap action:\n"); > + if (raw_encap) { > + ds_put_format(s, " Raw-encap: size=%ld\n", raw_encap->size); > + ds_put_format(s, " Raw-encap: encap=\n"); s/ds_put_format/ds_put_cstr/ And why it says "Raw-encap:" twice? > + ds_put_hex_dump(s, raw_encap->data, raw_encap->size, 0, false); > + } else { > + ds_put_cstr(s, " Raw-encap = null\n"); > + } > } else { > ds_put_format(s, "unknown rte flow action (%d)\n", actions->type); > } > @@ -1114,6 +1125,44 @@ parse_set_actions(struct flow_actions *actions, > return 0; > } > > +static int > +parse_clone_actions(struct netdev *netdev, > + struct flow_actions *actions, > + const struct nlattr *clone_actions, > + const size_t clone_actions_len) > +{ > + const struct nlattr *ca; > + unsigned int cleft; > + > + NL_ATTR_FOR_EACH_UNSAFE (ca, cleft, clone_actions, clone_actions_len) { > + int clone_type = nl_attr_type(ca); > + > + if (clone_type == OVS_ACTION_ATTR_TUNNEL_PUSH) { > + const struct ovs_action_push_tnl *tnl_push = nl_attr_get(ca); > + struct rte_flow_action_raw_encap *raw_encap = > + xzalloc(sizeof *raw_encap); > + > + raw_encap->data = (uint8_t *)tnl_push->header; > + raw_encap->preserve = NULL; > + raw_encap->size = tnl_push->header_len; > + > + add_flow_action(actions, RTE_FLOW_ACTION_TYPE_RAW_ENCAP, > + raw_encap); > + } else if (clone_type == OVS_ACTION_ATTR_OUTPUT) { > + if (add_output_action(netdev, actions, ca)) { > + return -1; > + } > + } else { > + VLOG_DBG_RL(&rl, > + "Unsupported nested action inside clone(), " > + "action type: %d", clone_type); > + return -1; > + } > + } > + > + return 0; > +} > + > static int > parse_flow_actions(struct netdev *netdev, > struct flow_actions *actions, > @@ -1141,6 +1190,14 @@ parse_flow_actions(struct netdev *netdev, > masked)) { > return -1; > } > + } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_CLONE) { I believe, we already discussed this somewhere, but we need to check that clone is actually the last action in a list since we do not perform an actual cloning. Otherwise, later actions will be performed on the modified packet. > + const struct nlattr *clone_actions = nl_attr_get(nla); > + size_t clone_actions_len = nl_attr_get_size(nla); > + > + if (parse_clone_actions(netdev, actions, clone_actions, > + clone_actions_len)) { > + return -1; > + } > } else { > VLOG_DBG_RL(&rl, "Unsupported action type %d", nl_attr_type(nla)); > return -1; >
On 6/29/2020 2:12 AM, Ilya Maximets wrote: > On 6/21/20 1:19 PM, Eli Britstein wrote: >> Tunnel encapsulation is done by tnl_push and output actions nested in a >> clone action. Support offloading of such flows with >> RTE_FLOW_ACTION_TYPE_RAW_ENCAP attribute. >> >> Signed-off-by: Eli Britstein <elibr@mellanox.com> >> Reviewed-by: Oz Shlomo <ozsh@mellanox.com> >> --- >> Documentation/howto/dpdk.rst | 1 + >> NEWS | 2 +- >> lib/netdev-offload-dpdk.c | 57 ++++++++++++++++++++++++++++++++++++++++++++ >> 3 files changed, 59 insertions(+), 1 deletion(-) >> >> diff --git a/Documentation/howto/dpdk.rst b/Documentation/howto/dpdk.rst >> index 1756a7149..724c837f5 100644 >> --- a/Documentation/howto/dpdk.rst >> +++ b/Documentation/howto/dpdk.rst >> @@ -396,6 +396,7 @@ Supported actions for hardware offload are: >> - Modification of IPv4 (mod_nw_src/mod_nw_dst/mod_nw_ttl). >> - Modification of TCP/UDP (mod_tp_src/mod_tp_dst). >> - Modification of IPv6 (set_field:<ADDR>->ipv6_src/ipv6_dst/mod_nw_ttl). >> +- Clone/output (tnl_push and output) for encapsulating over a tunnel. >> >> Further Reading >> --------------- >> diff --git a/NEWS b/NEWS >> index 7df8b134d..e7d3ca3c8 100644 >> --- a/NEWS >> +++ b/NEWS >> @@ -11,7 +11,7 @@ Post-v2.13.0 >> * Deprecated DPDK ring ports (dpdkr) are no longer supported. >> * Add hardware offload support for matching IPv6 protocol. >> * Add hardware offload support for set of IPv6 TCP/UDP ports >> - actions (experimental). >> + and tunnel push-output actions (experimental). >> - Linux datapath: >> * Support for kernel versions up to 5.5.x. >> - AF_XDP: >> diff --git a/lib/netdev-offload-dpdk.c b/lib/netdev-offload-dpdk.c >> index 13259a669..16df1fedd 100644 >> --- a/lib/netdev-offload-dpdk.c >> +++ b/lib/netdev-offload-dpdk.c >> @@ -475,6 +475,17 @@ dump_flow_action(struct ds *s, const struct rte_flow_action *actions) >> } else { >> ds_put_format(s, " Set-ipv6-%s = null\n", dirstr); >> } >> + } else if (actions->type == RTE_FLOW_ACTION_TYPE_RAW_ENCAP) { >> + const struct rte_flow_action_raw_encap *raw_encap = actions->conf; >> + >> + ds_put_cstr(s, "rte flow raw-encap action:\n"); >> + if (raw_encap) { >> + ds_put_format(s, " Raw-encap: size=%ld\n", raw_encap->size); >> + ds_put_format(s, " Raw-encap: encap=\n"); > s/ds_put_format/ds_put_cstr/ > > And why it says "Raw-encap:" twice? I changed it as we agreed to drop this format in favor of testpmd format. > >> + ds_put_hex_dump(s, raw_encap->data, raw_encap->size, 0, false); >> + } else { >> + ds_put_cstr(s, " Raw-encap = null\n"); >> + } >> } else { >> ds_put_format(s, "unknown rte flow action (%d)\n", actions->type); >> } >> @@ -1114,6 +1125,44 @@ parse_set_actions(struct flow_actions *actions, >> return 0; >> } >> >> +static int >> +parse_clone_actions(struct netdev *netdev, >> + struct flow_actions *actions, >> + const struct nlattr *clone_actions, >> + const size_t clone_actions_len) >> +{ >> + const struct nlattr *ca; >> + unsigned int cleft; >> + >> + NL_ATTR_FOR_EACH_UNSAFE (ca, cleft, clone_actions, clone_actions_len) { >> + int clone_type = nl_attr_type(ca); >> + >> + if (clone_type == OVS_ACTION_ATTR_TUNNEL_PUSH) { >> + const struct ovs_action_push_tnl *tnl_push = nl_attr_get(ca); >> + struct rte_flow_action_raw_encap *raw_encap = >> + xzalloc(sizeof *raw_encap); >> + >> + raw_encap->data = (uint8_t *)tnl_push->header; >> + raw_encap->preserve = NULL; >> + raw_encap->size = tnl_push->header_len; >> + >> + add_flow_action(actions, RTE_FLOW_ACTION_TYPE_RAW_ENCAP, >> + raw_encap); >> + } else if (clone_type == OVS_ACTION_ATTR_OUTPUT) { >> + if (add_output_action(netdev, actions, ca)) { >> + return -1; >> + } >> + } else { >> + VLOG_DBG_RL(&rl, >> + "Unsupported nested action inside clone(), " >> + "action type: %d", clone_type); >> + return -1; >> + } >> + } >> + >> + return 0; >> +} >> + >> static int >> parse_flow_actions(struct netdev *netdev, >> struct flow_actions *actions, >> @@ -1141,6 +1190,14 @@ parse_flow_actions(struct netdev *netdev, >> masked)) { >> return -1; >> } >> + } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_CLONE) { > I believe, we already discussed this somewhere, but we need to check > that clone is actually the last action in a list since we do not perform > an actual cloning. Otherwise, later actions will be performed on the > modified packet. Actually we discussed about the output *NOT* to limit for the last action, as it was mlx vendor specific limitation. For clone I agree it's different, and I'll change. > >> + const struct nlattr *clone_actions = nl_attr_get(nla); >> + size_t clone_actions_len = nl_attr_get_size(nla); >> + >> + if (parse_clone_actions(netdev, actions, clone_actions, >> + clone_actions_len)) { >> + return -1; >> + } >> } else { >> VLOG_DBG_RL(&rl, "Unsupported action type %d", nl_attr_type(nla)); >> return -1; >>
diff --git a/Documentation/howto/dpdk.rst b/Documentation/howto/dpdk.rst index 1756a7149..724c837f5 100644 --- a/Documentation/howto/dpdk.rst +++ b/Documentation/howto/dpdk.rst @@ -396,6 +396,7 @@ Supported actions for hardware offload are: - Modification of IPv4 (mod_nw_src/mod_nw_dst/mod_nw_ttl). - Modification of TCP/UDP (mod_tp_src/mod_tp_dst). - Modification of IPv6 (set_field:<ADDR>->ipv6_src/ipv6_dst/mod_nw_ttl). +- Clone/output (tnl_push and output) for encapsulating over a tunnel. Further Reading --------------- diff --git a/NEWS b/NEWS index 7df8b134d..e7d3ca3c8 100644 --- a/NEWS +++ b/NEWS @@ -11,7 +11,7 @@ Post-v2.13.0 * Deprecated DPDK ring ports (dpdkr) are no longer supported. * Add hardware offload support for matching IPv6 protocol. * Add hardware offload support for set of IPv6 TCP/UDP ports - actions (experimental). + and tunnel push-output actions (experimental). - Linux datapath: * Support for kernel versions up to 5.5.x. - AF_XDP: diff --git a/lib/netdev-offload-dpdk.c b/lib/netdev-offload-dpdk.c index 13259a669..16df1fedd 100644 --- a/lib/netdev-offload-dpdk.c +++ b/lib/netdev-offload-dpdk.c @@ -475,6 +475,17 @@ dump_flow_action(struct ds *s, const struct rte_flow_action *actions) } else { ds_put_format(s, " Set-ipv6-%s = null\n", dirstr); } + } else if (actions->type == RTE_FLOW_ACTION_TYPE_RAW_ENCAP) { + const struct rte_flow_action_raw_encap *raw_encap = actions->conf; + + ds_put_cstr(s, "rte flow raw-encap action:\n"); + if (raw_encap) { + ds_put_format(s, " Raw-encap: size=%ld\n", raw_encap->size); + ds_put_format(s, " Raw-encap: encap=\n"); + ds_put_hex_dump(s, raw_encap->data, raw_encap->size, 0, false); + } else { + ds_put_cstr(s, " Raw-encap = null\n"); + } } else { ds_put_format(s, "unknown rte flow action (%d)\n", actions->type); } @@ -1114,6 +1125,44 @@ parse_set_actions(struct flow_actions *actions, return 0; } +static int +parse_clone_actions(struct netdev *netdev, + struct flow_actions *actions, + const struct nlattr *clone_actions, + const size_t clone_actions_len) +{ + const struct nlattr *ca; + unsigned int cleft; + + NL_ATTR_FOR_EACH_UNSAFE (ca, cleft, clone_actions, clone_actions_len) { + int clone_type = nl_attr_type(ca); + + if (clone_type == OVS_ACTION_ATTR_TUNNEL_PUSH) { + const struct ovs_action_push_tnl *tnl_push = nl_attr_get(ca); + struct rte_flow_action_raw_encap *raw_encap = + xzalloc(sizeof *raw_encap); + + raw_encap->data = (uint8_t *)tnl_push->header; + raw_encap->preserve = NULL; + raw_encap->size = tnl_push->header_len; + + add_flow_action(actions, RTE_FLOW_ACTION_TYPE_RAW_ENCAP, + raw_encap); + } else if (clone_type == OVS_ACTION_ATTR_OUTPUT) { + if (add_output_action(netdev, actions, ca)) { + return -1; + } + } else { + VLOG_DBG_RL(&rl, + "Unsupported nested action inside clone(), " + "action type: %d", clone_type); + return -1; + } + } + + return 0; +} + static int parse_flow_actions(struct netdev *netdev, struct flow_actions *actions, @@ -1141,6 +1190,14 @@ parse_flow_actions(struct netdev *netdev, masked)) { return -1; } + } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_CLONE) { + const struct nlattr *clone_actions = nl_attr_get(nla); + size_t clone_actions_len = nl_attr_get_size(nla); + + if (parse_clone_actions(netdev, actions, clone_actions, + clone_actions_len)) { + return -1; + } } else { VLOG_DBG_RL(&rl, "Unsupported action type %d", nl_attr_type(nla)); return -1;