mirror of
https://github.com/openvswitch/ovs
synced 2025-09-02 15:25:22 +00:00
ovs-tc: offload MPLS set actions to TC datapath
Recent modifications to TC allows the modifying of fields within the outermost MPLS header of a packet. OvS datapath rules impliment an MPLS set action by supplying a new MPLS header that should overwrite the current one. Convert the OvS datapath MPLS set action to a TC modify action and allow such rules to be offloaded to a TC datapath. Signed-off-by: John Hurley <john.hurley@netronome.com> Reviewed-by: Simon Horman <simon.horman@netronome.com> Signed-off-by: Simon Horman <simon.horman@netronome.com>
This commit is contained in:
committed by
Simon Horman
parent
283dcf850d
commit
a8f005cf26
@@ -665,6 +665,23 @@ parse_tc_flower_to_match(struct tc_flower *flower,
|
||||
push->mpls_lse = mpls_lse;
|
||||
}
|
||||
break;
|
||||
case TC_ACT_MPLS_SET: {
|
||||
size_t set_offset = nl_msg_start_nested(buf,
|
||||
OVS_ACTION_ATTR_SET);
|
||||
struct ovs_key_mpls *set_mpls;
|
||||
ovs_be32 mpls_lse = 0;
|
||||
|
||||
flow_set_mpls_lse_label(&mpls_lse, action->mpls.label);
|
||||
flow_set_mpls_lse_tc(&mpls_lse, action->mpls.tc);
|
||||
flow_set_mpls_lse_ttl(&mpls_lse, action->mpls.ttl);
|
||||
flow_set_mpls_lse_bos(&mpls_lse, action->mpls.bos);
|
||||
|
||||
set_mpls = nl_msg_put_unspec_zero(buf, OVS_KEY_ATTR_MPLS,
|
||||
sizeof *set_mpls);
|
||||
set_mpls->mpls_lse = mpls_lse;
|
||||
nl_msg_end_nested(buf, set_offset);
|
||||
}
|
||||
break;
|
||||
case TC_ACT_PEDIT: {
|
||||
parse_flower_rewrite_to_netlink_action(buf, flower);
|
||||
}
|
||||
@@ -789,6 +806,22 @@ netdev_tc_flow_dump_next(struct netdev_flow_dump *dump,
|
||||
return false;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_mpls_set_action(struct tc_flower *flower, struct tc_action *action,
|
||||
const struct nlattr *set)
|
||||
{
|
||||
const struct ovs_key_mpls *mpls_set = nl_attr_get(set);
|
||||
|
||||
action->mpls.label = mpls_lse_to_label(mpls_set->mpls_lse);
|
||||
action->mpls.tc = mpls_lse_to_tc(mpls_set->mpls_lse);
|
||||
action->mpls.ttl = mpls_lse_to_ttl(mpls_set->mpls_lse);
|
||||
action->mpls.bos = mpls_lse_to_bos(mpls_set->mpls_lse);
|
||||
action->type = TC_ACT_MPLS_SET;
|
||||
flower->action_count++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_put_flow_set_masked_action(struct tc_flower *flower,
|
||||
struct tc_action *action,
|
||||
@@ -870,6 +903,10 @@ parse_put_flow_set_action(struct tc_flower *flower, struct tc_action *action,
|
||||
const struct nlattr *tun_attr;
|
||||
size_t tun_left, tunnel_len;
|
||||
|
||||
if (nl_attr_type(set) == OVS_KEY_ATTR_MPLS) {
|
||||
return parse_mpls_set_action(flower, action, set);
|
||||
}
|
||||
|
||||
if (nl_attr_type(set) != OVS_KEY_ATTR_TUNNEL) {
|
||||
return parse_put_flow_set_masked_action(flower, action, set,
|
||||
set_len, false);
|
||||
|
48
lib/tc.c
48
lib/tc.c
@@ -1303,6 +1303,25 @@ nl_parse_act_mpls(struct nlattr *options, struct tc_flower *flower)
|
||||
}
|
||||
action->type = TC_ACT_MPLS_PUSH;
|
||||
break;
|
||||
case TCA_MPLS_ACT_MODIFY:
|
||||
mpls_label = mpls_attrs[TCA_MPLS_LABEL];
|
||||
if (mpls_label) {
|
||||
action->mpls.label = nl_attr_get_u32(mpls_label);
|
||||
}
|
||||
mpls_tc = mpls_attrs[TCA_MPLS_TC];
|
||||
if (mpls_tc) {
|
||||
action->mpls.tc = nl_attr_get_u8(mpls_tc);
|
||||
}
|
||||
mpls_ttl = mpls_attrs[TCA_MPLS_TTL];
|
||||
if (mpls_ttl) {
|
||||
action->mpls.ttl = nl_attr_get_u8(mpls_ttl);
|
||||
}
|
||||
mpls_bos = mpls_attrs[TCA_MPLS_BOS];
|
||||
if (mpls_bos) {
|
||||
action->mpls.bos = nl_attr_get_u8(mpls_bos);
|
||||
}
|
||||
action->type = TC_ACT_MPLS_SET;
|
||||
break;
|
||||
default:
|
||||
VLOG_ERR_RL(&error_rl, "unknown mpls action: %d, %d",
|
||||
m->action, m->m_action);
|
||||
@@ -1764,6 +1783,27 @@ nl_msg_put_act_push_mpls(struct ofpbuf *request, ovs_be16 proto,
|
||||
nl_msg_end_nested(request, offset);
|
||||
}
|
||||
|
||||
static void
|
||||
nl_msg_put_act_set_mpls(struct ofpbuf *request, uint32_t label, uint8_t tc,
|
||||
uint8_t ttl, uint8_t bos)
|
||||
{
|
||||
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_MODIFY };
|
||||
|
||||
nl_msg_put_unspec(request, TCA_MPLS_PARMS, &parm, sizeof parm);
|
||||
nl_msg_put_u32(request, TCA_MPLS_LABEL, label);
|
||||
nl_msg_put_u8(request, TCA_MPLS_TC, tc);
|
||||
nl_msg_put_u8(request, TCA_MPLS_TTL, ttl);
|
||||
nl_msg_put_u8(request, TCA_MPLS_BOS, bos);
|
||||
}
|
||||
nl_msg_end_nested(request, offset);
|
||||
}
|
||||
|
||||
static void
|
||||
nl_msg_put_act_tunnel_key_release(struct ofpbuf *request)
|
||||
{
|
||||
@@ -2155,6 +2195,14 @@ nl_msg_put_flower_acts(struct ofpbuf *request, struct tc_flower *flower)
|
||||
nl_msg_end_nested(request, act_offset);
|
||||
}
|
||||
break;
|
||||
case TC_ACT_MPLS_SET: {
|
||||
act_offset = nl_msg_start_nested(request, act_index++);
|
||||
nl_msg_put_act_set_mpls(request, action->mpls.label,
|
||||
action->mpls.tc, action->mpls.ttl,
|
||||
action->mpls.bos);
|
||||
nl_msg_end_nested(request, act_offset);
|
||||
}
|
||||
break;
|
||||
case TC_ACT_OUTPUT: {
|
||||
ingress = action->out.ingress;
|
||||
ifindex = action->out.ifindex_out;
|
||||
|
Reference in New Issue
Block a user