[ovs-dev,v5,04/10] netdev-offload-tc: Implement netdev tc flush via tc filter del
diff mbox series

Message ID 1576511601-12348-5-git-send-email-paulb@mellanox.com
State Changes Requested
Headers show
Series
  • Add support for offloading CT datapath rules to TC
Related show

Commit Message

Paul Blakey Dec. 16, 2019, 3:53 p.m. UTC
To be consistent with our tc-ufid mapping after flush, and to support tc
chains flushing in the next commit, implement flush operation via
deleting all the filters we actually added and delete their mappings.

This will also not delete the configured qos policing via matchall filters,
while old code did.

Signed-off-by: Paul Blakey <paulb@mellanox.com>
Reviewed-by: Roi Dayan <roid@mellanox.com>
---
 lib/netdev-offload-tc.c | 74 +++++++++++++++++++++++++++----------------------
 1 file changed, 41 insertions(+), 33 deletions(-)

Patch
diff mbox series

diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c
index 460c27f..15b39e6 100644
--- a/lib/netdev-offload-tc.c
+++ b/lib/netdev-offload-tc.c
@@ -43,7 +43,8 @@  VLOG_DEFINE_THIS_MODULE(netdev_offload_tc);
 
 static struct vlog_rate_limit error_rl = VLOG_RATE_LIMIT_INIT(60, 5);
 
-static struct hmap ufid_tc = HMAP_INITIALIZER(&ufid_tc);
+static struct hmap ufid_to_tc = HMAP_INITIALIZER(&ufid_to_tc);
+static struct hmap tc_to_ufid = HMAP_INITIALIZER(&tc_to_ufid);
 static bool multi_mask_per_prio = false;
 static bool block_support = false;
 
@@ -143,44 +144,49 @@  static struct netlink_field set_flower_map[][4] = {
 static struct ovs_mutex ufid_lock = OVS_MUTEX_INITIALIZER;
 
 /**
- * struct ufid_tc_data - data entry for ufid_tc hmap.
- * @ufid_node: Element in @ufid_tc hash table by ufid key.
- * @tc_node: Element in @ufid_tc hash table by tcf_id key.
+ * struct ufid_tc_data - data entry for ufid-tc hashmaps.
+ * @ufid_to_tc_node: Element in @ufid_to_tc hash table by ufid key.
+ * @tc_to_ufid_node: Element in @tc_to_ufid hash table by tcf_id key.
  * @ufid: ufid assigned to the flow
  * @id: tc filter id (tcf_id)
  * @netdev: netdev associated with the tc rule
  */
 struct ufid_tc_data {
-    struct hmap_node ufid_node;
-    struct hmap_node tc_node;
+    struct hmap_node ufid_to_tc_node;
+    struct hmap_node tc_to_ufid_node;
     ovs_u128 ufid;
     struct tcf_id id;
     struct netdev *netdev;
 };
 
-/* Remove matching ufid entry from ufid_tc hashmap. */
 static void
-del_ufid_tc_mapping(const ovs_u128 *ufid)
+del_ufid_tc_mapping_unlocked(const ovs_u128 *ufid)
 {
     size_t ufid_hash = hash_bytes(ufid, sizeof *ufid, 0);
     struct ufid_tc_data *data;
 
-    ovs_mutex_lock(&ufid_lock);
-    HMAP_FOR_EACH_WITH_HASH(data, ufid_node, ufid_hash, &ufid_tc) {
+    HMAP_FOR_EACH_WITH_HASH (data, ufid_to_tc_node, ufid_hash, &ufid_to_tc) {
         if (ovs_u128_equals(*ufid, data->ufid)) {
             break;
         }
     }
 
     if (!data) {
-        ovs_mutex_unlock(&ufid_lock);
         return;
     }
 
-    hmap_remove(&ufid_tc, &data->ufid_node);
-    hmap_remove(&ufid_tc, &data->tc_node);
+    hmap_remove(&ufid_to_tc, &data->ufid_to_tc_node);
+    hmap_remove(&tc_to_ufid, &data->tc_to_ufid_node);
     netdev_close(data->netdev);
     free(data);
+}
+
+/* Remove matching ufid entry from ufid-tc hashmaps. */
+static void
+del_ufid_tc_mapping(const ovs_u128 *ufid)
+{
+    ovs_mutex_lock(&ufid_lock);
+    del_ufid_tc_mapping_unlocked(ufid);
     ovs_mutex_unlock(&ufid_lock);
 }
 
@@ -195,7 +201,7 @@  del_filter_and_ufid_mapping(struct tcf_id *id, const ovs_u128 *ufid)
     return err;
 }
 
-/* Add ufid entry to ufid_tc hashmap. */
+/* Add ufid entry to ufid_to_tc hashmap. */
 static void
 add_ufid_tc_mapping(struct netdev *netdev, const ovs_u128 *ufid,
                     struct tcf_id *id)
@@ -209,12 +215,12 @@  add_ufid_tc_mapping(struct netdev *netdev, const ovs_u128 *ufid,
     new_data->netdev = netdev_ref(netdev);
 
     ovs_mutex_lock(&ufid_lock);
-    hmap_insert(&ufid_tc, &new_data->ufid_node, ufid_hash);
-    hmap_insert(&ufid_tc, &new_data->tc_node, tc_hash);
+    hmap_insert(&ufid_to_tc, &new_data->ufid_to_tc_node, ufid_hash);
+    hmap_insert(&tc_to_ufid, &new_data->tc_to_ufid_node, tc_hash);
     ovs_mutex_unlock(&ufid_lock);
 }
 
-/* Get tc id from ufid_tc hashmap.
+/* Get tc id from ufid_to_tc hashmap.
  *
  * Returns 0 if successful and fills id.
  * Otherwise returns the error.
@@ -226,7 +232,7 @@  get_ufid_tc_mapping(const ovs_u128 *ufid, struct tcf_id *id)
     struct ufid_tc_data *data;
 
     ovs_mutex_lock(&ufid_lock);
-    HMAP_FOR_EACH_WITH_HASH(data, ufid_node, ufid_hash, &ufid_tc) {
+    HMAP_FOR_EACH_WITH_HASH (data, ufid_to_tc_node, ufid_hash, &ufid_to_tc) {
         if (ovs_u128_equals(*ufid, data->ufid)) {
             *id = data->id;
             ovs_mutex_unlock(&ufid_lock);
@@ -238,7 +244,7 @@  get_ufid_tc_mapping(const ovs_u128 *ufid, struct tcf_id *id)
     return ENOENT;
 }
 
-/* Find ufid entry in ufid_tc hashmap using tcf_id id.
+/* Find ufid entry in ufid_to_tc hashmap using tcf_id id.
  * The result is saved in ufid.
  *
  * Returns true on success.
@@ -250,7 +256,7 @@  find_ufid(struct netdev *netdev, struct tcf_id *id, ovs_u128 *ufid)
     struct ufid_tc_data *data;
 
     ovs_mutex_lock(&ufid_lock);
-    HMAP_FOR_EACH_WITH_HASH(data, tc_node, tc_hash,  &ufid_tc) {
+    HMAP_FOR_EACH_WITH_HASH (data, tc_to_ufid_node, tc_hash,  &tc_to_ufid) {
         if (netdev == data->netdev && is_tcf_id_eq(&data->id, id)) {
             *ufid = data->ufid;
             break;
@@ -293,7 +299,7 @@  get_prio_for_tc_flower(struct tc_flower *flower)
      * different prio if not. Flower classifier will reject same prio for
      * different mask combination unless multi mask per prio is supported. */
     ovs_mutex_lock(&prios_lock);
-    HMAP_FOR_EACH_WITH_HASH(data, node, hash, &prios) {
+    HMAP_FOR_EACH_WITH_HASH (data, node, hash, &prios) {
         if ((multi_mask_per_prio
              || !memcmp(&flower->mask, &data->mask, key_len))
             && data->protocol == flower->key.eth_type) {
@@ -332,21 +338,23 @@  get_block_id_from_netdev(struct netdev *netdev)
 static int
 netdev_tc_flow_flush(struct netdev *netdev)
 {
-    enum tc_qdisc_hook hook = get_tc_qdisc_hook(netdev);
-    int ifindex = netdev_get_ifindex(netdev);
-    uint32_t block_id = 0;
-    struct tcf_id id;
-    int prio = 0;
+    struct ufid_tc_data *data, *next;
+    int err;
 
-    if (ifindex < 0) {
-        VLOG_ERR_RL(&error_rl, "flow_flush: failed to get ifindex for %s: %s",
-                    netdev_get_name(netdev), ovs_strerror(-ifindex));
-        return -ifindex;
+    ovs_mutex_lock(&ufid_lock);
+    HMAP_FOR_EACH_SAFE (data, next, tc_to_ufid_node, &tc_to_ufid) {
+        if (data->netdev != netdev) {
+            continue;
+        }
+
+        err = tc_del_filter(&data->id);
+        if (!err) {
+            del_ufid_tc_mapping_unlocked(&data->ufid);
+        }
     }
+    ovs_mutex_unlock(&ufid_lock);
 
-    block_id = get_block_id_from_netdev(netdev);
-    id = tc_make_tcf_id(ifindex, block_id, prio, hook);
-    return tc_del_filter(&id);
+    return 0;
 }
 
 static int