diff options
author | John Hurley <john.hurley@netronome.com> | 2019-07-30 12:05:17 +0100 |
---|---|---|
committer | Simon Horman <simon.horman@netronome.com> | 2019-08-01 18:09:42 +0200 |
commit | a8f005cf26fd16f77133d67fe4b205409fc444db (patch) | |
tree | 78d211eed3cc529f1938510e1b016d88e981d584 /lib | |
parent | 283dcf850d564afdbccd2cc14fd5d0b407625669 (diff) | |
download | openvswitch-a8f005cf26fd16f77133d67fe4b205409fc444db.tar.gz |
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>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/netdev-offload-tc.c | 37 | ||||
-rw-r--r-- | lib/tc.c | 48 | ||||
-rw-r--r-- | lib/tc.h | 1 |
3 files changed, 86 insertions, 0 deletions
diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c index 03610d87b..6814390ea 100644 --- a/lib/netdev-offload-tc.c +++ b/lib/netdev-offload-tc.c @@ -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); } @@ -790,6 +807,22 @@ netdev_tc_flow_dump_next(struct netdev_flow_dump *dump, } 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, const struct nlattr *set, @@ -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); @@ -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); @@ -1765,6 +1784,27 @@ nl_msg_put_act_push_mpls(struct ofpbuf *request, ovs_be16 proto, } 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) { size_t offset; @@ -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; @@ -155,6 +155,7 @@ enum tc_action_type { TC_ACT_VLAN_PUSH, TC_ACT_MPLS_POP, TC_ACT_MPLS_PUSH, + TC_ACT_MPLS_SET, }; struct tc_action { |