diff mbox series

[ovs-dev,v2,6/6] netdev-offload-tc: Offloading rules with police actions

Message ID 20210902125949.3412301-7-roid@nvidia.com
State Superseded
Headers show
Series Add support for ovs metering with tc offload | expand

Checks

Context Check Description
ovsrobot/apply-robot success apply and check: success
ovsrobot/github-robot-_Build_and_Test success github build: passed

Commit Message

Roi Dayan Sept. 2, 2021, 12:59 p.m. UTC
From: Jianbo Liu <jianbol@nvidia.com>

To offload OVS meter, a meter is mapped to police action. While
offoading rule, tc should be filled with police index, instead of
meter id. So dpif passes police indexes in the additional info to tc
offload, then they are used to replace meter id in tc rule.
An action cookie is created to save meter id on rule creation, so
meter id can be retrieved from the cookie, and pass to dpif while
dumping.

Signed-off-by: Jianbo Liu <jianbol@nvidia.com>
Reviewed-by: Roi Dayan <roid@nvidia.com>
---
 lib/dpif-netlink.c      | 14 ++++++++++++++
 lib/netdev-offload-tc.c |  9 ++++++++-
 lib/netdev-offload.h    |  4 ++++
 lib/tc.c                | 25 ++++++++++++++++++++++++-
 4 files changed, 50 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c
index 409f3f4b6d2b..2ca8ff308c91 100644
--- a/lib/dpif-netlink.c
+++ b/lib/dpif-netlink.c
@@ -2205,6 +2205,7 @@  parse_flow_put(struct dpif_netlink *dpif, struct dpif_flow_put *put)
     struct offload_info info;
     ovs_be16 dst_port = 0;
     uint8_t csum_on = false;
+    int n_meters = 0;
     int err;
 
     info.tc_modify_flow_deleted = false;
@@ -2245,6 +2246,19 @@  parse_flow_put(struct dpif_netlink *dpif, struct dpif_flow_put *put)
                 csum_on = tnl_cfg->csum;
             }
             netdev_close(outdev);
+        } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_METER) {
+            uint32_t meter_id = nl_attr_get_u32(nla);
+            uint32_t police_idx;
+
+            if (meter_id_lookup(meter_id, &police_idx)) {
+                err = EINVAL;
+                goto out;
+            }
+            if (n_meters >= MAX_OFFLOAD_METERS) {
+                err = EOPNOTSUPP;
+                goto out;
+            }
+            info.police_ids[n_meters++] = police_idx;
         }
     }
 
diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c
index 7210f968a2de..757f60fbe8bf 100644
--- a/lib/netdev-offload-tc.c
+++ b/lib/netdev-offload-tc.c
@@ -1016,7 +1016,8 @@  parse_tc_flower_to_match(struct tc_flower *flower,
             }
             break;
             case TC_ACT_POLICE: {
-                /* Not supported yet */
+                nl_msg_put_u32(buf, OVS_ACTION_ATTR_METER,
+                               action->police.meter_id);
             }
             break;
             }
@@ -1584,6 +1585,7 @@  netdev_tc_flow_put(struct netdev *netdev, struct match *match,
     uint32_t block_id = 0;
     struct nlattr *nla;
     struct tcf_id id;
+    int n_meters = 0;
     uint32_t chain;
     size_t left;
     int prio = 0;
@@ -1921,6 +1923,11 @@  netdev_tc_flow_put(struct netdev *netdev, struct match *match,
             action->type = TC_ACT_GOTO;
             action->chain = 0;  /* 0 is reserved and not used by recirc. */
             flower.action_count++;
+        } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_METER) {
+            action->type = TC_ACT_POLICE;
+            action->police.meter_id = nl_attr_get_u32(nla);
+            action->police.index = info->police_ids[n_meters++];
+            flower.action_count++;
         } else {
             VLOG_DBG_RL(&rl, "unsupported put action type: %d",
                         nl_attr_type(nla));
diff --git a/lib/netdev-offload.h b/lib/netdev-offload.h
index e7fcedae9397..370542e2315c 100644
--- a/lib/netdev-offload.h
+++ b/lib/netdev-offload.h
@@ -27,6 +27,8 @@ 
 extern "C" {
 #endif
 
+#define MAX_OFFLOAD_METERS 4
+
 struct dp_packet_batch;
 struct dp_packet;
 struct netdev_class;
@@ -77,6 +79,8 @@  struct offload_info {
     bool tc_modify_flow_deleted; /* Indicate the tc modify flow put success
                                   * to delete the original flow. */
     odp_port_t orig_in_port; /* Originating in_port for tnl flows. */
+    uint32_t police_ids[MAX_OFFLOAD_METERS]; /* police ids of the offloaded
+                                              * meters in the flow */
 };
 
 int netdev_flow_flush(struct netdev *);
diff --git a/lib/tc.c b/lib/tc.c
index 160f769c0418..4685fc22f4e2 100644
--- a/lib/tc.c
+++ b/lib/tc.c
@@ -2333,6 +2333,22 @@  nl_msg_put_act_gact(struct ofpbuf *request, uint32_t chain)
 }
 
 static void
+nl_msg_put_act_police_index(struct ofpbuf *request, uint32_t police_idx)
+{
+    struct tc_police police;
+    size_t offset;
+
+    memset(&police, 0, sizeof police);
+    police.index = police_idx;
+
+    nl_msg_put_string(request, TCA_ACT_KIND, "police");
+    offset = nl_msg_start_nested(request, TCA_ACT_OPTIONS);
+    nl_msg_put_unspec(request, TCA_POLICE_TBF, &police, sizeof police);
+    nl_msg_put_u32(request, TCA_POLICE_RESULT, TC_ACT_PIPE);
+    nl_msg_end_nested(request, offset);
+}
+
+static void
 nl_msg_put_act_ct(struct ofpbuf *request, struct tc_action *action)
 {
     uint16_t ct_action = 0;
@@ -2783,7 +2799,14 @@  nl_msg_put_flower_acts(struct ofpbuf *request, struct tc_flower *flower)
             }
             break;
             case TC_ACT_POLICE: {
-                /* Not supported yet */
+                struct tc_cookie act_cookie;
+
+                act_offset = nl_msg_start_nested(request, act_index++);
+                nl_msg_put_act_police_index(request, action->police.index);
+                act_cookie.data = &action->police.meter_id;
+                act_cookie.len = sizeof(action->police.meter_id);
+                nl_msg_put_act_cookie(request, &act_cookie);
+                nl_msg_end_nested(request, act_offset);
             }
             break;
             }