diff mbox series

[ovs-dev,v2] tc: Add TCA_KIND flower to delete and get operation to avoid rtnl_lock().

Message ID 167481813172.1146345.9238649094707887654.stgit@ebuild.local
State Accepted
Commit e1e5eac5b0167c65c802bd60ed37605b1e1c9c92
Headers show
Series [ovs-dev,v2] tc: Add TCA_KIND flower to delete and get operation to avoid rtnl_lock(). | expand

Checks

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

Commit Message

Eelco Chaudron Jan. 27, 2023, 11:16 a.m. UTC
A long long time ago, an effort was made to make tc flower
rtnl_lock() free. However, on the OVS part we forgot to add
the TCA_KIND "flower" attribute, which tell the kernel to skip
the lock. This patch corrects this by adding the attribute for
the delete and get operations.

The kernel code calls tcf_proto_is_unlocked() to determine the
rtnl_lock() is needed for the specific tc protocol. It does this
in the tc_new_tfilter(), tc_del_tfilter(), and in tc_get_tfilter().

If the name is not set, tcf_proto_is_unlocked() will always return
false. If set, the specific protocol is queried for unlocked support.

Fixes: f98e418fbdb6 ("tc: Add tc flower functions")
Signed-off-by: Eelco Chaudron <echaudro@redhat.com>
---
 lib/netdev-linux.c      |    2 +-
 lib/netdev-offload-tc.c |   20 ++++++++++----------
 lib/tc.c                |   10 +++++++++-
 lib/tc.h                |    3 ++-
 4 files changed, 22 insertions(+), 13 deletions(-)

Comments

Roi Dayan Jan. 29, 2023, 8:18 a.m. UTC | #1
On 27/01/2023 13:16, Eelco Chaudron wrote:
> A long long time ago, an effort was made to make tc flower
> rtnl_lock() free. However, on the OVS part we forgot to add
> the TCA_KIND "flower" attribute, which tell the kernel to skip
> the lock. This patch corrects this by adding the attribute for
> the delete and get operations.
> 
> The kernel code calls tcf_proto_is_unlocked() to determine the
> rtnl_lock() is needed for the specific tc protocol. It does this
> in the tc_new_tfilter(), tc_del_tfilter(), and in tc_get_tfilter().
> 
> If the name is not set, tcf_proto_is_unlocked() will always return
> false. If set, the specific protocol is queried for unlocked support.
> 
> Fixes: f98e418fbdb6 ("tc: Add tc flower functions")
> Signed-off-by: Eelco Chaudron <echaudro@redhat.com>
> ---
>  lib/netdev-linux.c      |    2 +-
>  lib/netdev-offload-tc.c |   20 ++++++++++----------
>  lib/tc.c                |   10 +++++++++-
>  lib/tc.h                |    3 ++-
>  4 files changed, 22 insertions(+), 13 deletions(-)
> 
> diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c
> index f6d7a1b97..65bdd51db 100644
> --- a/lib/netdev-linux.c
> +++ b/lib/netdev-linux.c
> @@ -2735,7 +2735,7 @@ tc_del_matchall_policer(struct netdev *netdev)
>      }
>  
>      id = tc_make_tcf_id(ifindex, block_id, prio, TC_INGRESS);
> -    err = tc_del_filter(&id);
> +    err = tc_del_filter(&id, "matchall");
>      if (err) {
>          return err;
>      }
> diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c
> index ce7f8ad97..2d7e74b1a 100644
> --- a/lib/netdev-offload-tc.c
> +++ b/lib/netdev-offload-tc.c
> @@ -239,7 +239,7 @@ del_filter_and_ufid_mapping(struct tcf_id *id, const ovs_u128 *ufid)
>  {
>      int err;
>  
> -    err = tc_del_filter(id);
> +    err = tc_del_flower_filter(id);
>      if (!err) {
>          del_ufid_tc_mapping(ufid);
>      }
> @@ -461,7 +461,7 @@ delete_chains_from_netdev(struct netdev *netdev, struct tcf_id *id)
>           */
>          HMAP_FOR_EACH_POP (chain_node, node, &map) {
>              id->chain = chain_node->chain;
> -            tc_del_filter(id);
> +            tc_del_flower_filter(id);
>              free(chain_node);
>          }
>      }
> @@ -482,7 +482,7 @@ netdev_tc_flow_flush(struct netdev *netdev)
>              continue;
>          }
>  
> -        err = tc_del_filter(&data->id);
> +        err = tc_del_flower_filter(&data->id);
>          if (!err) {
>              del_ufid_tc_mapping_unlocked(&data->ufid);
>          }
> @@ -2498,13 +2498,13 @@ probe_multi_mask_per_prio(int ifindex)
>  
>      id2 = tc_make_tcf_id(ifindex, block_id, prio, TC_INGRESS);
>      error = tc_replace_flower(&id2, &flower);
> -    tc_del_filter(&id1);
> +    tc_del_flower_filter(&id1);
>  
>      if (error) {
>          goto out;
>      }
>  
> -    tc_del_filter(&id2);
> +    tc_del_flower_filter(&id2);
>  
>      multi_mask_per_prio = true;
>      VLOG_INFO("probe tc: multiple masks on single tc prio is supported.");
> @@ -2556,7 +2556,7 @@ probe_ct_state_support(int ifindex)
>          goto out_del;
>      }
>  
> -    tc_del_filter(&id);
> +    tc_del_flower_filter(&id);
>      ct_state_support = OVS_CS_F_NEW |
>                         OVS_CS_F_ESTABLISHED |
>                         OVS_CS_F_TRACKED |
> @@ -2570,7 +2570,7 @@ probe_ct_state_support(int ifindex)
>          goto out_del;
>      }
>  
> -    tc_del_filter(&id);
> +    tc_del_flower_filter(&id);
>  
>      /* Test for ct_state INVALID support */
>      memset(&flower, 0, sizeof flower);
> @@ -2581,7 +2581,7 @@ probe_ct_state_support(int ifindex)
>          goto out;
>      }
>  
> -    tc_del_filter(&id);
> +    tc_del_flower_filter(&id);
>      ct_state_support |= OVS_CS_F_INVALID;
>  
>      /* Test for ct_state REPLY support */
> @@ -2597,7 +2597,7 @@ probe_ct_state_support(int ifindex)
>      ct_state_support |= OVS_CS_F_REPLY_DIR;
>  
>  out_del:
> -    tc_del_filter(&id);
> +    tc_del_flower_filter(&id);
>  out:
>      tc_add_del_qdisc(ifindex, false, 0, TC_INGRESS);
>      VLOG_INFO("probe tc: supported ovs ct_state bits: 0x%x", ct_state_support);
> @@ -2750,7 +2750,7 @@ netdev_tc_init_flow_api(struct netdev *netdev)
>  
>      /* fallback here if delete chains fail */
>      if (!get_chain_supported) {
> -        tc_del_filter(&id);
> +        tc_del_flower_filter(&id);
>      }
>  
>      /* make sure there is no ingress/egress qdisc */
> diff --git a/lib/tc.c b/lib/tc.c
> index 447ab376e..1fb2b4a92 100644
> --- a/lib/tc.c
> +++ b/lib/tc.c
> @@ -2337,14 +2337,21 @@ parse_netlink_to_tc_policer(struct ofpbuf *reply, uint32_t police_idx[])
>  }
>  
>  int
> -tc_del_filter(struct tcf_id *id)
> +tc_del_filter(struct tcf_id *id, const char *kind)
>  {
>      struct ofpbuf request;
>  
>      request_from_tcf_id(id, 0, RTM_DELTFILTER, NLM_F_ACK, &request);
> +    nl_msg_put_string(&request, TCA_KIND, kind);
>      return tc_transact(&request, NULL);
>  }
>  
> +int
> +tc_del_flower_filter(struct tcf_id *id)
> +{
> +    return tc_del_filter(id, "flower");
> +}
> +
>  int
>  tc_get_flower(struct tcf_id *id, struct tc_flower *flower)
>  {
> @@ -2353,6 +2360,7 @@ tc_get_flower(struct tcf_id *id, struct tc_flower *flower)
>      int error;
>  
>      request_from_tcf_id(id, 0, RTM_GETTFILTER, NLM_F_ECHO, &request);
> +    nl_msg_put_string(&request, TCA_KIND, "flower");
>      error = tc_transact(&request, &reply);
>      if (error) {
>          return error;
> diff --git a/lib/tc.h b/lib/tc.h
> index a828fd3e3..ea4ce806b 100644
> --- a/lib/tc.h
> +++ b/lib/tc.h
> @@ -384,7 +384,8 @@ struct tc_flower {
>  };
>  
>  int tc_replace_flower(struct tcf_id *id, struct tc_flower *flower);
> -int tc_del_filter(struct tcf_id *id);
> +int tc_del_filter(struct tcf_id *id, const char *kind);
> +int tc_del_flower_filter(struct tcf_id *id);
>  int tc_get_flower(struct tcf_id *id, struct tc_flower *flower);
>  int tc_dump_flower_start(struct tcf_id *id, struct nl_dump *dump, bool terse);
>  int tc_dump_tc_chain_start(struct tcf_id *id, struct nl_dump *dump);
> 
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev

thanks. looks good.
Did few ovs tc tests to verify all good.

Reviewed-by: Roi Dayan <roid@nvidia.com>
Ilya Maximets Jan. 30, 2023, 9:08 p.m. UTC | #2
On 1/29/23 09:18, Roi Dayan wrote:
> 
> 
> On 27/01/2023 13:16, Eelco Chaudron wrote:
>> A long long time ago, an effort was made to make tc flower
>> rtnl_lock() free. However, on the OVS part we forgot to add
>> the TCA_KIND "flower" attribute, which tell the kernel to skip
>> the lock. This patch corrects this by adding the attribute for
>> the delete and get operations.
>>
>> The kernel code calls tcf_proto_is_unlocked() to determine the
>> rtnl_lock() is needed for the specific tc protocol. It does this
>> in the tc_new_tfilter(), tc_del_tfilter(), and in tc_get_tfilter().
>>
>> If the name is not set, tcf_proto_is_unlocked() will always return
>> false. If set, the specific protocol is queried for unlocked support.
>>
>> Fixes: f98e418fbdb6 ("tc: Add tc flower functions")
>> Signed-off-by: Eelco Chaudron <echaudro@redhat.com>
>> ---
> thanks. looks good.
> Did few ovs tc tests to verify all good.
> 
> Reviewed-by: Roi Dayan <roid@nvidia.com>


Thanks!  Applied and backported down to 2.17.

Best regards, Ilya Maximets.
diff mbox series

Patch

diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c
index f6d7a1b97..65bdd51db 100644
--- a/lib/netdev-linux.c
+++ b/lib/netdev-linux.c
@@ -2735,7 +2735,7 @@  tc_del_matchall_policer(struct netdev *netdev)
     }
 
     id = tc_make_tcf_id(ifindex, block_id, prio, TC_INGRESS);
-    err = tc_del_filter(&id);
+    err = tc_del_filter(&id, "matchall");
     if (err) {
         return err;
     }
diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c
index ce7f8ad97..2d7e74b1a 100644
--- a/lib/netdev-offload-tc.c
+++ b/lib/netdev-offload-tc.c
@@ -239,7 +239,7 @@  del_filter_and_ufid_mapping(struct tcf_id *id, const ovs_u128 *ufid)
 {
     int err;
 
-    err = tc_del_filter(id);
+    err = tc_del_flower_filter(id);
     if (!err) {
         del_ufid_tc_mapping(ufid);
     }
@@ -461,7 +461,7 @@  delete_chains_from_netdev(struct netdev *netdev, struct tcf_id *id)
          */
         HMAP_FOR_EACH_POP (chain_node, node, &map) {
             id->chain = chain_node->chain;
-            tc_del_filter(id);
+            tc_del_flower_filter(id);
             free(chain_node);
         }
     }
@@ -482,7 +482,7 @@  netdev_tc_flow_flush(struct netdev *netdev)
             continue;
         }
 
-        err = tc_del_filter(&data->id);
+        err = tc_del_flower_filter(&data->id);
         if (!err) {
             del_ufid_tc_mapping_unlocked(&data->ufid);
         }
@@ -2498,13 +2498,13 @@  probe_multi_mask_per_prio(int ifindex)
 
     id2 = tc_make_tcf_id(ifindex, block_id, prio, TC_INGRESS);
     error = tc_replace_flower(&id2, &flower);
-    tc_del_filter(&id1);
+    tc_del_flower_filter(&id1);
 
     if (error) {
         goto out;
     }
 
-    tc_del_filter(&id2);
+    tc_del_flower_filter(&id2);
 
     multi_mask_per_prio = true;
     VLOG_INFO("probe tc: multiple masks on single tc prio is supported.");
@@ -2556,7 +2556,7 @@  probe_ct_state_support(int ifindex)
         goto out_del;
     }
 
-    tc_del_filter(&id);
+    tc_del_flower_filter(&id);
     ct_state_support = OVS_CS_F_NEW |
                        OVS_CS_F_ESTABLISHED |
                        OVS_CS_F_TRACKED |
@@ -2570,7 +2570,7 @@  probe_ct_state_support(int ifindex)
         goto out_del;
     }
 
-    tc_del_filter(&id);
+    tc_del_flower_filter(&id);
 
     /* Test for ct_state INVALID support */
     memset(&flower, 0, sizeof flower);
@@ -2581,7 +2581,7 @@  probe_ct_state_support(int ifindex)
         goto out;
     }
 
-    tc_del_filter(&id);
+    tc_del_flower_filter(&id);
     ct_state_support |= OVS_CS_F_INVALID;
 
     /* Test for ct_state REPLY support */
@@ -2597,7 +2597,7 @@  probe_ct_state_support(int ifindex)
     ct_state_support |= OVS_CS_F_REPLY_DIR;
 
 out_del:
-    tc_del_filter(&id);
+    tc_del_flower_filter(&id);
 out:
     tc_add_del_qdisc(ifindex, false, 0, TC_INGRESS);
     VLOG_INFO("probe tc: supported ovs ct_state bits: 0x%x", ct_state_support);
@@ -2750,7 +2750,7 @@  netdev_tc_init_flow_api(struct netdev *netdev)
 
     /* fallback here if delete chains fail */
     if (!get_chain_supported) {
-        tc_del_filter(&id);
+        tc_del_flower_filter(&id);
     }
 
     /* make sure there is no ingress/egress qdisc */
diff --git a/lib/tc.c b/lib/tc.c
index 447ab376e..1fb2b4a92 100644
--- a/lib/tc.c
+++ b/lib/tc.c
@@ -2337,14 +2337,21 @@  parse_netlink_to_tc_policer(struct ofpbuf *reply, uint32_t police_idx[])
 }
 
 int
-tc_del_filter(struct tcf_id *id)
+tc_del_filter(struct tcf_id *id, const char *kind)
 {
     struct ofpbuf request;
 
     request_from_tcf_id(id, 0, RTM_DELTFILTER, NLM_F_ACK, &request);
+    nl_msg_put_string(&request, TCA_KIND, kind);
     return tc_transact(&request, NULL);
 }
 
+int
+tc_del_flower_filter(struct tcf_id *id)
+{
+    return tc_del_filter(id, "flower");
+}
+
 int
 tc_get_flower(struct tcf_id *id, struct tc_flower *flower)
 {
@@ -2353,6 +2360,7 @@  tc_get_flower(struct tcf_id *id, struct tc_flower *flower)
     int error;
 
     request_from_tcf_id(id, 0, RTM_GETTFILTER, NLM_F_ECHO, &request);
+    nl_msg_put_string(&request, TCA_KIND, "flower");
     error = tc_transact(&request, &reply);
     if (error) {
         return error;
diff --git a/lib/tc.h b/lib/tc.h
index a828fd3e3..ea4ce806b 100644
--- a/lib/tc.h
+++ b/lib/tc.h
@@ -384,7 +384,8 @@  struct tc_flower {
 };
 
 int tc_replace_flower(struct tcf_id *id, struct tc_flower *flower);
-int tc_del_filter(struct tcf_id *id);
+int tc_del_filter(struct tcf_id *id, const char *kind);
+int tc_del_flower_filter(struct tcf_id *id);
 int tc_get_flower(struct tcf_id *id, struct tc_flower *flower);
 int tc_dump_flower_start(struct tcf_id *id, struct nl_dump *dump, bool terse);
 int tc_dump_tc_chain_start(struct tcf_id *id, struct nl_dump *dump);