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

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


TC can now be used to push an MPLS header onto a packet. The MPLS label is
the only information that needs to be passed here with the rest reverting
to default values if none are supplied. OvS, however, gives the entire
MPLS header to be pushed along with the MPLS protocol to use. TC can
optionally accept these values so can be made replicate the OvS datapath
rule.

Convert OvS MPLS push datapath rules to TC format and offload to a TC
datapath.

Signed-off-by: John Hurley <john.hurley at netronome.com>
Reviewed-by: Simon Horman <simon.horman at netronome.com>
---
 lib/netdev-offload-tc.c | 25 ++++++++++++++++++++
 lib/packets.h           | 24 +++++++++++++++++++
 lib/tc.c                | 61 +++++++++++++++++++++++++++++++++++++++++++++++++
 lib/tc.h                |  5 ++++
 4 files changed, 115 insertions(+)

diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c
index 2e282c9..03610d8 100644
--- a/lib/netdev-offload-tc.c
+++ b/lib/netdev-offload-tc.c
@@ -650,6 +650,21 @@ parse_tc_flower_to_match(struct tc_flower *flower,
                                 action->mpls.proto);
             }
             break;
+            case TC_ACT_MPLS_PUSH: {
+                struct ovs_action_push_mpls *push;
+                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);
+
+                push = nl_msg_put_unspec_zero(buf, OVS_ACTION_ATTR_PUSH_MPLS,
+                                              sizeof *push);
+                push->mpls_ethertype = action->mpls.proto;
+                push->mpls_lse = mpls_lse;
+            }
+            break;
             case TC_ACT_PEDIT: {
                 parse_flower_rewrite_to_netlink_action(buf, flower);
             }
@@ -1333,6 +1348,16 @@ 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_PUSH_MPLS) {
+            const struct ovs_action_push_mpls *mpls_push = nl_attr_get(nla);
+
+            action->mpls.proto = mpls_push->mpls_ethertype;
+            action->mpls.label = mpls_lse_to_label(mpls_push->mpls_lse);
+            action->mpls.tc = mpls_lse_to_tc(mpls_push->mpls_lse);
+            action->mpls.ttl = mpls_lse_to_ttl(mpls_push->mpls_lse);
+            action->mpls.bos = mpls_lse_to_bos(mpls_push->mpls_lse);
+            action->type = TC_ACT_MPLS_PUSH;
+            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;
diff --git a/lib/packets.h b/lib/packets.h
index 4124490..a4bee38 100644
--- a/lib/packets.h
+++ b/lib/packets.h
@@ -574,6 +574,30 @@ mpls_lse_to_ttl(ovs_be32 mpls_lse)
     return (ntohl(mpls_lse) & MPLS_TTL_MASK) >> MPLS_TTL_SHIFT;
 }
 
+/* Set label in mpls lse. */
+static inline void
+flow_set_mpls_lse_label(ovs_be32 *mpls_lse, uint32_t label)
+{
+    *mpls_lse &= ~htonl(MPLS_LABEL_MASK);
+    *mpls_lse |= htonl(label << MPLS_LABEL_SHIFT);
+}
+
+/* Set TC in mpls lse. */
+static inline void
+flow_set_mpls_lse_tc(ovs_be32 *mpls_lse, uint8_t tc)
+{
+    *mpls_lse &= ~htonl(MPLS_TC_MASK);
+    *mpls_lse |= htonl((tc & 0x7) << MPLS_TC_SHIFT);
+}
+
+/* Set BOS in mpls lse. */
+static inline void
+flow_set_mpls_lse_bos(ovs_be32 *mpls_lse, uint8_t bos)
+{
+    *mpls_lse &= ~htonl(MPLS_BOS_MASK);
+    *mpls_lse |= htonl((bos & 0x1) << MPLS_BOS_SHIFT);
+}
+
 /* Set TTL in mpls lse. */
 static inline void
 flow_set_mpls_lse_ttl(ovs_be32 *mpls_lse, uint8_t ttl)
diff --git a/lib/tc.c b/lib/tc.c
index 85aa9a1..71aa55c 100644
--- a/lib/tc.c
+++ b/lib/tc.c
@@ -1243,6 +1243,10 @@ static const struct nl_policy mpls_policy[] = {
                          .min_len = sizeof(struct tc_mpls),
                          .optional = false, },
     [TCA_MPLS_PROTO] = { .type = NL_A_U16, .optional = true, },
+    [TCA_MPLS_LABEL] = { .type = NL_A_U32, .optional = true, },
+    [TCA_MPLS_TC] = { .type = NL_A_U8, .optional = true, },
+    [TCA_MPLS_TTL] = { .type = NL_A_U8, .optional = true, },
+    [TCA_MPLS_BOS] = { .type = NL_A_U8, .optional = true, },
 };
 
 static int
@@ -1251,8 +1255,12 @@ 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 nlattr *mpls_label;
     struct tc_action *action;
     const struct tc_mpls *m;
+    struct nlattr *mpls_ttl;
+    struct nlattr *mpls_bos;
+    struct nlattr *mpls_tc;
 
     if (!nl_parse_nested(options, mpls_policy, mpls_attrs,
                          ARRAY_SIZE(mpls_policy))) {
@@ -1272,6 +1280,29 @@ nl_parse_act_mpls(struct nlattr *options, struct tc_flower *flower)
         }
         action->type = TC_ACT_MPLS_POP;
         break;
+    case TCA_MPLS_ACT_PUSH:
+        mpls_proto = mpls_attrs[TCA_MPLS_PROTO];
+        if (mpls_proto) {
+            action->mpls.proto = nl_attr_get_be16(mpls_proto);
+        }
+        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_PUSH;
+        break;
     default:
         VLOG_ERR_RL(&error_rl, "unknown mpls action: %d, %d",
                     m->action, m->m_action);
@@ -1712,6 +1743,28 @@ nl_msg_put_act_pop_mpls(struct ofpbuf *request, ovs_be16 proto)
 }
 
 static void
+nl_msg_put_act_push_mpls(struct ofpbuf *request, ovs_be16 proto,
+                         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_PUSH };
+
+        nl_msg_put_unspec(request, TCA_MPLS_PARMS, &parm, sizeof parm);
+        nl_msg_put_be16(request, TCA_MPLS_PROTO, proto);
+        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;
@@ -2094,6 +2147,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_PUSH: {
+                act_offset = nl_msg_start_nested(request, act_index++);
+                nl_msg_put_act_push_mpls(request, action->mpls.proto,
+                                         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;
diff --git a/lib/tc.h b/lib/tc.h
index 7805f69..a498a84 100644
--- a/lib/tc.h
+++ b/lib/tc.h
@@ -154,6 +154,7 @@ enum tc_action_type {
     TC_ACT_VLAN_POP,
     TC_ACT_VLAN_PUSH,
     TC_ACT_MPLS_POP,
+    TC_ACT_MPLS_PUSH,
 };
 
 struct tc_action {
@@ -171,6 +172,10 @@ struct tc_action {
 
         struct {
             ovs_be16 proto;
+            uint32_t label;
+            uint8_t tc;
+            uint8_t ttl;
+            uint8_t bos;
         } mpls;
 
         struct {
-- 
2.7.4



More information about the dev mailing list