|
@@ -1261,6 +1261,16 @@ static inline int todrop_entry(struct ip_vs_conn *cp)
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
+static inline bool ip_vs_conn_ops_mode(struct ip_vs_conn *cp)
|
|
|
+{
|
|
|
+ struct ip_vs_service *svc;
|
|
|
+
|
|
|
+ if (!cp->dest)
|
|
|
+ return false;
|
|
|
+ svc = rcu_dereference(cp->dest->svc);
|
|
|
+ return svc && (svc->flags & IP_VS_SVC_F_ONEPACKET);
|
|
|
+}
|
|
|
+
|
|
|
/* Called from keventd and must protect itself from softirqs */
|
|
|
void ip_vs_random_dropentry(struct netns_ipvs *ipvs)
|
|
|
{
|
|
@@ -1275,11 +1285,16 @@ void ip_vs_random_dropentry(struct netns_ipvs *ipvs)
|
|
|
unsigned int hash = prandom_u32() & ip_vs_conn_tab_mask;
|
|
|
|
|
|
hlist_for_each_entry_rcu(cp, &ip_vs_conn_tab[hash], c_list) {
|
|
|
- if (cp->flags & IP_VS_CONN_F_TEMPLATE)
|
|
|
- /* connection template */
|
|
|
- continue;
|
|
|
if (cp->ipvs != ipvs)
|
|
|
continue;
|
|
|
+ if (cp->flags & IP_VS_CONN_F_TEMPLATE) {
|
|
|
+ if (atomic_read(&cp->n_control) ||
|
|
|
+ !ip_vs_conn_ops_mode(cp))
|
|
|
+ continue;
|
|
|
+ else
|
|
|
+ /* connection template of OPS */
|
|
|
+ goto try_drop;
|
|
|
+ }
|
|
|
if (cp->protocol == IPPROTO_TCP) {
|
|
|
switch(cp->state) {
|
|
|
case IP_VS_TCP_S_SYN_RECV:
|
|
@@ -1307,6 +1322,7 @@ void ip_vs_random_dropentry(struct netns_ipvs *ipvs)
|
|
|
continue;
|
|
|
}
|
|
|
} else {
|
|
|
+try_drop:
|
|
|
if (!todrop_entry(cp))
|
|
|
continue;
|
|
|
}
|