Skip to content

Commit

Permalink
ovs-tc: offload MPLS pop actions to TC datapath
Browse files Browse the repository at this point in the history
TC now supports an action to pop the outer MPLS header from a packet. The
next protocol after the header is required alongside this. Currently, OvS
datapath rules also supply this information.

Offload OvS MPLS pop actions to TC along with the next protocol.

Signed-off-by: John Hurley <[email protected]>
Reviewed-by: Simon Horman <[email protected]>
Signed-off-by: Simon Horman <[email protected]>
  • Loading branch information
jahurley authored and shorman-netronome committed Aug 1, 2019
1 parent abef795 commit 55412ea
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 0 deletions.
9 changes: 9 additions & 0 deletions lib/netdev-offload-tc.c
Original file line number Diff line number Diff line change
Expand Up @@ -645,6 +645,11 @@ parse_tc_flower_to_match(struct tc_flower *flower,
| VLAN_CFI);
}
break;
case TC_ACT_MPLS_POP: {
nl_msg_put_be16(buf, OVS_ACTION_ATTR_POP_MPLS,
action->mpls.proto);
}
break;
case TC_ACT_PEDIT: {
parse_flower_rewrite_to_netlink_action(buf, flower);
}
Expand Down Expand Up @@ -1328,6 +1333,10 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match,
} else if (nl_attr_type(nla) == OVS_ACTION_ATTR_POP_VLAN) {
action->type = TC_ACT_VLAN_POP;
flower.action_count++;
} else if (nl_attr_type(nla) == OVS_ACTION_ATTR_POP_MPLS) {
action->mpls.proto = nl_attr_get_be16(nla);
action->type = TC_ACT_MPLS_POP;
flower.action_count++;
} else if (nl_attr_type(nla) == OVS_ACTION_ATTR_SET) {
const struct nlattr *set = nl_attr_get(nla);
const size_t set_len = nl_attr_get_size(nla);
Expand Down
69 changes: 69 additions & 0 deletions lib/tc.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <linux/tc_act/tc_csum.h>
#include <linux/tc_act/tc_gact.h>
#include <linux/tc_act/tc_mirred.h>
#include <linux/tc_act/tc_mpls.h>
#include <linux/tc_act/tc_pedit.h>
#include <linux/tc_act/tc_skbedit.h>
#include <linux/tc_act/tc_tunnel_key.h>
Expand Down Expand Up @@ -1237,6 +1238,49 @@ nl_parse_act_vlan(struct nlattr *options, struct tc_flower *flower)
return 0;
}

static const struct nl_policy mpls_policy[] = {
[TCA_MPLS_PARMS] = { .type = NL_A_UNSPEC,
.min_len = sizeof(struct tc_mpls),
.optional = false, },
[TCA_MPLS_PROTO] = { .type = NL_A_U16, .optional = true, },
};

static int
nl_parse_act_mpls(struct nlattr *options, struct tc_flower *flower)
{
struct nlattr *mpls_attrs[ARRAY_SIZE(mpls_policy)];
const struct nlattr *mpls_parms;
struct nlattr *mpls_proto;
struct tc_action *action;
const struct tc_mpls *m;

if (!nl_parse_nested(options, mpls_policy, mpls_attrs,
ARRAY_SIZE(mpls_policy))) {
VLOG_ERR_RL(&error_rl, "failed to parse mpls action options");
return EPROTO;
}

action = &flower->actions[flower->action_count++];
mpls_parms = mpls_attrs[TCA_MPLS_PARMS];
m = nl_attr_get_unspec(mpls_parms, sizeof *m);

switch (m->m_action) {
case TCA_MPLS_ACT_POP:
mpls_proto = mpls_attrs[TCA_MPLS_PROTO];
if (mpls_proto) {
action->mpls.proto = nl_attr_get_be16(mpls_proto);
}
action->type = TC_ACT_MPLS_POP;
break;
default:
VLOG_ERR_RL(&error_rl, "unknown mpls action: %d, %d",
m->action, m->m_action);
return EINVAL;
}

return 0;
}

static const struct nl_policy csum_policy[] = {
[TCA_CSUM_PARMS] = { .type = NL_A_UNSPEC,
.min_len = sizeof(struct tc_csum),
Expand Down Expand Up @@ -1319,6 +1363,8 @@ nl_parse_single_action(struct nlattr *action, struct tc_flower *flower)
err = nl_parse_act_mirred(act_options, flower);
} else if (!strcmp(act_kind, "vlan")) {
err = nl_parse_act_vlan(act_options, flower);
} else if (!strcmp(act_kind, "mpls")) {
err = nl_parse_act_mpls(act_options, flower);
} else if (!strcmp(act_kind, "tunnel_key")) {
err = nl_parse_act_tunnel_key(act_options, flower);
} else if (!strcmp(act_kind, "pedit")) {
Expand Down Expand Up @@ -1648,6 +1694,23 @@ nl_msg_put_act_pop_vlan(struct ofpbuf *request)
nl_msg_end_nested(request, offset);
}

static void
nl_msg_put_act_pop_mpls(struct ofpbuf *request, ovs_be16 proto)
{
size_t offset;

nl_msg_put_string(request, TCA_ACT_KIND, "mpls");
offset = nl_msg_start_nested(request, TCA_ACT_OPTIONS | NLA_F_NESTED);
{
struct tc_mpls parm = { .action = TC_ACT_PIPE,
.m_action = TCA_MPLS_ACT_POP };

nl_msg_put_unspec(request, TCA_MPLS_PARMS, &parm, sizeof parm);
nl_msg_put_be16(request, TCA_MPLS_PROTO, proto);
}
nl_msg_end_nested(request, offset);
}

static void
nl_msg_put_act_tunnel_key_release(struct ofpbuf *request)
{
Expand Down Expand Up @@ -2025,6 +2088,12 @@ nl_msg_put_flower_acts(struct ofpbuf *request, struct tc_flower *flower)
nl_msg_end_nested(request, act_offset);
}
break;
case TC_ACT_MPLS_POP: {
act_offset = nl_msg_start_nested(request, act_index++);
nl_msg_put_act_pop_mpls(request, action->mpls.proto);
nl_msg_end_nested(request, act_offset);
}
break;
case TC_ACT_OUTPUT: {
ingress = action->out.ingress;
ifindex = action->out.ifindex_out;
Expand Down
5 changes: 5 additions & 0 deletions lib/tc.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ enum tc_action_type {
TC_ACT_PEDIT,
TC_ACT_VLAN_POP,
TC_ACT_VLAN_PUSH,
TC_ACT_MPLS_POP,
};

struct tc_action {
Expand All @@ -168,6 +169,10 @@ struct tc_action {
uint8_t vlan_push_prio;
} vlan;

struct {
ovs_be16 proto;
} mpls;

struct {
bool id_present;
ovs_be64 id;
Expand Down

0 comments on commit 55412ea

Please sign in to comment.