[qca-nss-sfe] Remove active list for the ipv4
to maintain the active list needs use lock, use new packets
number to mark active connection.
Change-Id: Id676f6b47c72ea898f45f014848f5d24d6cb98e0
Signed-off-by: Ken Zhu <quic_guigenz@quicinc.com>
diff --git a/sfe_ipv4.c b/sfe_ipv4.c
index 70b1e53..de2e383 100644
--- a/sfe_ipv4.c
+++ b/sfe_ipv4.c
@@ -381,23 +381,6 @@
hlist_del_init_rcu(&cm->hnode);
- /*
- * If the connection match entry is in the active list remove it.
- */
- if (cm->active) {
- if (likely(cm->active_prev)) {
- cm->active_prev->active_next = cm->active_next;
- } else {
- si->active_head = cm->active_next;
- }
-
- if (likely(cm->active_next)) {
- cm->active_next->active_prev = cm->active_prev;
- } else {
- si->active_tail = cm->active_prev;
- }
- }
-
}
/*
@@ -575,6 +558,13 @@
si->all_connections_tail = c->all_connections_prev;
}
+ /*
+ * If I am the next sync connection, move the sync to my next or head.
+ */
+ if (unlikely(si->wc_next == c)) {
+ si->wc_next = c->all_connections_next;
+ }
+
c->removed = true;
si->num_connections--;
return true;
@@ -959,25 +949,6 @@
atomic_inc(&cm->rx_packet_count);
atomic_add(len, &cm->rx_byte_count);
- /*
- * If we're not already on the active list then insert ourselves at the tail
- * of the current list.
- */
- if (unlikely(!cm->active)) {
- spin_lock_bh(&si->lock);
- if (unlikely(!cm->active)) {
- cm->active = true;
- cm->active_prev = si->active_tail;
- if (likely(si->active_tail)) {
- si->active_tail->active_next = cm;
- } else {
- si->active_head = cm;
- }
- si->active_tail = cm;
- }
- spin_unlock_bh(&si->lock);
- }
-
xmit_dev = cm->xmit_dev;
skb->dev = xmit_dev;
@@ -1564,26 +1535,6 @@
atomic_inc(&cm->rx_packet_count);
atomic_add(len, &cm->rx_byte_count);
- /*
- * If we're not already on the active list then insert ourselves at the tail
- * of the current list.
- */
- if (unlikely(!cm->active)) {
- spin_lock_bh(&si->lock);
- if (unlikely(!cm->active)) {
-
- cm->active = true;
- cm->active_prev = si->active_tail;
- if (likely(si->active_tail)) {
- si->active_tail->active_next = cm;
- } else {
- si->active_head = cm;
- }
- si->active_tail = cm;
- }
- spin_unlock_bh(&si->lock);
- }
-
xmit_dev = cm->xmit_dev;
skb->dev = xmit_dev;
@@ -2172,9 +2123,6 @@
}
#endif
- original_cm->active_next = NULL;
- original_cm->active_prev = NULL;
- original_cm->active = false;
/*
* For PPP links we don't write an L2 header. For everything else we do.
@@ -2239,9 +2187,6 @@
}
#endif
- reply_cm->active_next = NULL;
- reply_cm->active_prev = NULL;
- reply_cm->active = false;
/*
* For PPP links we don't write an L2 header. For everything else we do.
@@ -2473,6 +2418,7 @@
u64 now_jiffies;
int quota;
sfe_sync_rule_callback_t sync_rule_callback;
+ struct sfe_ipv4_connection *c;
now_jiffies = get_jiffies_64();
@@ -2486,75 +2432,65 @@
spin_lock_bh(&si->lock);
/*
+ * If we have reached the end of the connection list, walk from
+ * the connection head.
+ */
+ c = si->wc_next;
+ if (unlikely(!c)) {
+ c = si->all_connections_head;
+ }
+
+ /*
* Get an estimate of the number of connections to parse in this sync.
*/
quota = (si->num_connections + 63) / 64;
/*
- * Walk the "active" list and sync the connection state.
+ * Walk the "all connection" list and sync the connection state.
*/
- while (quota--) {
+ while (likely(c && quota)) {
struct sfe_ipv4_connection_match *cm;
struct sfe_ipv4_connection_match *counter_cm;
- struct sfe_ipv4_connection *c;
struct sfe_connection_sync sis;
- cm = si->active_head;
- if (!cm) {
- break;
- }
+ cm = c->original_match;
+ counter_cm = c->reply_match;
/*
- * There's a possibility that our counter match is in the active list too.
- * If it is then remove it.
+ * Didn't receive packets in the original direction or reply
+ * direction, move to the next connection.
*/
- counter_cm = cm->counter_match;
- if (counter_cm->active) {
- counter_cm->active = false;
-
- /*
- * We must have a connection preceding this counter match
- * because that's the one that got us to this point, so we don't have
- * to worry about removing the head of the list.
- */
- counter_cm->active_prev->active_next = counter_cm->active_next;
-
- if (likely(counter_cm->active_next)) {
- counter_cm->active_next->active_prev = counter_cm->active_prev;
- } else {
- si->active_tail = counter_cm->active_prev;
- }
-
- counter_cm->active_next = NULL;
- counter_cm->active_prev = NULL;
+ if ((!atomic_read(&cm->rx_packet_count)) && !(atomic_read(&counter_cm->rx_packet_count))) {
+ c = c->all_connections_next;
+ continue;
}
- /*
- * Now remove the head of the active scan list.
- */
- cm->active = false;
- si->active_head = cm->active_next;
- if (likely(cm->active_next)) {
- cm->active_next->active_prev = NULL;
- } else {
- si->active_tail = NULL;
- }
- cm->active_next = NULL;
+ quota--;
- /*
- * Sync the connection state.
- */
- c = cm->connection;
sfe_ipv4_gen_sync_sfe_ipv4_connection(si, c, &sis, SFE_SYNC_REASON_STATS, now_jiffies);
+ si->wc_next = c->all_connections_next;
+
/*
* We don't want to be holding the lock when we sync!
*/
spin_unlock_bh(&si->lock);
sync_rule_callback(&sis);
spin_lock_bh(&si->lock);
+
+ /*
+ * c must be set and used in the same lock/unlock window;
+ * because c could be removed when we don't hold the lock,
+ * so delay grabbing until after the callback and relock.
+ */
+ c = si->wc_next;
}
+ /*
+ * At the end of the sync, put the wc_next to the connection we left.
+ */
+ si->wc_next = c;
+
spin_unlock_bh(&si->lock);
rcu_read_unlock();
diff --git a/sfe_ipv4.h b/sfe_ipv4.h
index 25411aa..da2f748 100644
--- a/sfe_ipv4.h
+++ b/sfe_ipv4.h
@@ -66,10 +66,6 @@
struct sfe_ipv4_connection *connection;
struct sfe_ipv4_connection_match *counter_match;
/* Matches the flow in the opposite direction as the one in *connection */
- struct sfe_ipv4_connection_match *active_next;
- struct sfe_ipv4_connection_match *active_prev;
- bool active; /* Flag to indicate if we're on the active list */
-
/*
* Characteristics that identify flows that match this rule.
*/
@@ -260,10 +256,6 @@
*/
struct sfe_ipv4 {
spinlock_t lock; /* Lock for SMP correctness */
- struct sfe_ipv4_connection_match *active_head;
- /* Head of the list of recently active connections */
- struct sfe_ipv4_connection_match *active_tail;
- /* Tail of the list of recently active connections */
struct sfe_ipv4_connection *all_connections_head;
/* Head of the list of all connections */
struct sfe_ipv4_connection *all_connections_tail;
@@ -290,6 +282,8 @@
struct sfe_ipv4_stats __percpu *stats_pcpu;
/* Per CPU statistics. */
+ struct sfe_ipv4_connection *wc_next; /* Connection list walk pointer for stats sync */
+
/*
* Control state.
*/