2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-22 09:58:01 +00:00
ovs/lib/conntrack-other.c
Eli Britstein 97211927f1 conntrack: Fix conntrack multiple new state.
A connection is established if we see packets from both directions.
The cited commit fixed the issue of sending twice in one direction,
but still an issue if more than that.
Fix it.

Fixes: a867c010ee91 ("conntrack: Fix conntrack new state")
Signed-off-by: Eli Britstein <elibr@nvidia.com>
Acked-by: Paolo Valerio <pvalerio@redhat.com>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
2022-07-25 18:42:14 +02:00

92 lines
2.3 KiB
C

/*
* Copyright (c) 2015-2019 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <config.h>
#include "conntrack-private.h"
#include "conntrack-tp.h"
#include "dp-packet.h"
enum OVS_PACKED_ENUM other_state {
OTHERS_FIRST,
OTHERS_MULTIPLE,
OTHERS_BIDIR,
};
struct conn_other {
struct conn up;
enum other_state state; /* 'conn' lock protected. */
};
static const enum ct_timeout other_timeouts[] = {
[OTHERS_FIRST] = CT_TM_OTHER_FIRST,
[OTHERS_MULTIPLE] = CT_TM_OTHER_MULTIPLE,
[OTHERS_BIDIR] = CT_TM_OTHER_BIDIR,
};
static struct conn_other *
conn_other_cast(const struct conn *conn)
{
return CONTAINER_OF(conn, struct conn_other, up);
}
static enum ct_update_res
other_conn_update(struct conntrack *ct, struct conn *conn_,
struct dp_packet *pkt OVS_UNUSED, bool reply, long long now)
{
struct conn_other *conn = conn_other_cast(conn_);
if (reply && conn->state != OTHERS_BIDIR) {
conn->state = OTHERS_BIDIR;
} else if (conn->state == OTHERS_FIRST) {
conn->state = OTHERS_MULTIPLE;
}
conn_update_expiration(ct, &conn->up, other_timeouts[conn->state], now);
if (conn->state == OTHERS_BIDIR) {
return CT_UPDATE_VALID;
}
return CT_UPDATE_VALID_NEW;
}
static bool
other_valid_new(struct dp_packet *pkt OVS_UNUSED)
{
return true;
}
static struct conn *
other_new_conn(struct conntrack *ct, struct dp_packet *pkt OVS_UNUSED,
long long now, uint32_t tp_id)
{
struct conn_other *conn;
conn = xzalloc(sizeof *conn);
conn->state = OTHERS_FIRST;
conn->up.tp_id = tp_id;
conn_init_expiration(ct, &conn->up, other_timeouts[conn->state], now);
return &conn->up;
}
struct ct_l4_proto ct_proto_other = {
.new_conn = other_new_conn,
.valid_new = other_valid_new,
.conn_update = other_conn_update,
};