[ovs-dev] [PATCH OvS 2/4] ovs-tc: offload MPLS pop actions to TC datapath

John Hurley john.hurley at netronome.com
Tue Jul 30 11:05:15 UTC 2019


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 <john.hurley at netronome.com>
Reviewed-by: Simon Horman <simon.horman at netronome.com>
---
 lib/netdev-offload-tc.c |  9 +++++++
 lib/tc.c                | 69 +++++++++++++++++++++++++++++++++++++++++++++++++
 lib/tc.h                |  5 ++++
 3 files changed, 83 insertions(+)

diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c
index 4cc044b..2e282c9 100644
--- a/lib/netdev-offload-tc.c
+++ b/lib/netdev-offload-tc.c
@@ -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);
             }
@@ -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);
diff --git a/lib/tc.c b/lib/tc.c
index 1eca356..85aa9a1 100644
--- a/lib/tc.c
+++ b/lib/tc.c
@@ -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>
@@ -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),
@@ -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")) {
@@ -1649,6 +1695,23 @@ nl_msg_put_act_pop_vlan(struct ofpbuf *request)
 }
 
 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)
 {
     size_t offset;
@@ -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;
diff --git a/lib/tc.h b/lib/tc.h
index 2e0f5e3..7805f69 100644
--- a/lib/tc.h
+++ b/lib/tc.h
@@ -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 {
@@ -169,6 +170,10 @@ struct tc_action {
         } vlan;
 
         struct {
+            ovs_be16 proto;
+        } mpls;
+
+        struct {
             bool id_present;
             ovs_be64 id;
             ovs_be16 tp_src;
-- 
2.7.4



More information about the dev mailing list