On 22 Jan 2021, at 4:27, Chris Mi wrote:

On 1/13/2021 3:49 AM, Eelco Chaudron wrote:


On 15 Dec 2020, at 4:38, Chris Mi wrote:

<SNIP>

+
+static void
+gid_cleanup(void)
+{
+    long long int now = time_msec();
+    struct gid_node *node;
+
+    /* Do maintenance at most 4 times / sec. */
+    ovs_rwlock_rdlock(&gid_rwlock);
+    if (now - gid_last_run < GID_RUN_INTERVAL) {
+        ovs_rwlock_unlock(&gid_rwlock);
+        return;
+    }
+    ovs_rwlock_unlock(&gid_rwlock);
+
+    ovs_rwlock_wrlock(&gid_rwlock);
+    gid_last_run = now;
+
+    LIST_FOR_EACH_POP (node, exp_node, &gid_expired) {
+        cmap_remove(&gid_map, &node->id_node, node->id);
+        ovsrcu_postpone(gid_node_free, node);
+    }
+
+    if (!ovs_list_is_empty(&gid_expiring)) {
+        /* 'gid_expired' is now empty, move nodes in
+         * 'gid_expiring' to it. */
+        ovs_list_splice(&gid_expired,
+                        ovs_list_front(&gid_expiring),
+                        &gid_expiring);
+    }

Trying to understand why we have two list? Why can't we directly cleanup from expiring list?
The code takes the recirc id management for example (ofproto-dpif-rid.c). I'm not 100% sure the two lists are really needed here. But the recirc id code exists for a long time.
I think it is mature. And I don't want to re-invent something.

And when psample thread receives the sampled packets, it needs to lookup the sgid_node based on the group id. But the sgid_node could be deleted anytime by the revalidator. So I think two list can resolve this issue. We have 250 ms interval to wait for the sampled packets
on the fly to be processed.

Just adding code because it exists somewhere else does not make sense to me. If you do not have a valid reason, why add all this complexity?

I would like some other reviewer's comments on this, maybe I missed something, Ilya?

+    ovs_rwlock_unlock(&gid_rwlock);
+}
+

<SNIP>

+
+static void
+gid_node_unref(const struct gid_node *node_)
+    OVS_EXCLUDED(gid_rwlock)
+{
+    struct gid_node *node = CONST_CAST(struct gid_node *, node_);
+
+    ovs_rwlock_wrlock(&gid_rwlock);
+    if (node && ovs_refcount_unref(&node->refcount) == 1) {
+        /* Prevent re-use of this node by removing the node from
+         * gid_metadata_map' */
+        cmap_remove(&gid_metadata_map, &node->metadata_node, node->hash); +        /* We keep the node in the 'gid_map' so that it can be found as +         * long as it lingers, and add it to the 'gid_expiring' list. */
+        ovs_list_insert(&gid_expiring, &node->exp_node);

Why do we do a delayed remove here? Any sflow packets in the pipeline can be silently deleted, based on a failing sgid_find().
Please see my above comment for the two list issue.
The only thing concern might be ID reuse. But I think with 32^2 IDs, and the current allocator schema, this is unlikely to happen.

It would make the code cleaner, and the rwlock can be a normal lock.

+    }
+    ovs_rwlock_unlock(&gid_rwlock);
+}
+
+static void
+gid_free(uint32_t id)
+{
+    const struct gid_node *node;


<SNIP>


@@ -398,6 +651,8 @@ netdev_tc_flow_dump_create(struct netdev *netdev,

     *dump_out = dump;

+    gid_cleanup();
+

I guess this can be removed if we can delete the pigs directly, if not, we might want to put a comment here explaining why this is called from this function.
OK, I'll put a comment here.

     return 0;
 }

@@ -1797,6 +2052,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_SAMPLE) {
+            struct dpif_sflow_attr sflow_attr;
+
+            memset(&sflow_attr, 0, sizeof sflow_attr);
+            gid_alloc_ctx(&sflow_attr);


_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to