mirror of
https://github.com/openvswitch/ovs
synced 2025-10-23 14:57:06 +00:00
From the connection tracker perspective, an ICMP connection is a tuple identified by source ip address, destination ip address and ICMP id. While this allows basic ICMP traffic (pings) to work, it doesn't take into account the icmp type: the connection tracker will allow requests/replies in any directions. This is improved by making the ICMP type and code part of the connection tuple. An ICMP echo request packet from A to B, will create a connection that matches ICMP echo request from A to B and ICMP echo replies from B to A. The same is done for timestamp and info request/replies, and for ICMPv6. A new modules conntrack-icmp is implemented, to allow only "request" types to create new connections. Also, since they're tracked in both userspace and kernel implementations, ICMP type and code are always printed in ct-dpif (a few testcase are updated as a consequence). Reported-by: Subramani Paramasivam <subramani.paramasivam@wipro.com> Signed-off-by: Daniele Di Proietto <diproiettod@vmware.com> Acked-by: Joe Stringer <joe@ovn.org>
189 lines
4.9 KiB
C
189 lines
4.9 KiB
C
/*
|
|
* Copyright (c) 2015 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.
|
|
*/
|
|
|
|
#ifndef CT_DPIF_H
|
|
#define CT_DPIF_H
|
|
|
|
#include "openvswitch/types.h"
|
|
#include "packets.h"
|
|
|
|
union ct_dpif_inet_addr {
|
|
ovs_be32 ip;
|
|
ovs_be32 ip6[4];
|
|
struct in_addr in;
|
|
struct in6_addr in6;
|
|
};
|
|
|
|
struct ct_dpif_tuple {
|
|
uint16_t l3_type; /* Address family. */
|
|
uint8_t ip_proto;
|
|
union ct_dpif_inet_addr src;
|
|
union ct_dpif_inet_addr dst;
|
|
union {
|
|
ovs_be16 src_port;
|
|
ovs_be16 icmp_id;
|
|
};
|
|
union {
|
|
ovs_be16 dst_port;
|
|
struct {
|
|
uint8_t icmp_type;
|
|
uint8_t icmp_code;
|
|
};
|
|
};
|
|
};
|
|
BUILD_ASSERT_DECL(sizeof(struct ct_dpif_tuple) % 8 == 0);
|
|
|
|
struct ct_dpif_counters {
|
|
uint64_t packets;
|
|
uint64_t bytes;
|
|
};
|
|
|
|
/* Nanoseconds from January 1, 1970 */
|
|
struct ct_dpif_timestamp {
|
|
/* When the entry was created */
|
|
uint64_t start;
|
|
/* When the entry was deleted */
|
|
uint64_t stop;
|
|
};
|
|
|
|
#define CT_DPIF_TCP_STATES \
|
|
CT_DPIF_TCP_STATE(CLOSED) \
|
|
CT_DPIF_TCP_STATE(LISTEN) \
|
|
CT_DPIF_TCP_STATE(SYN_SENT) \
|
|
CT_DPIF_TCP_STATE(SYN_RECV) \
|
|
CT_DPIF_TCP_STATE(ESTABLISHED) \
|
|
CT_DPIF_TCP_STATE(CLOSE_WAIT) \
|
|
CT_DPIF_TCP_STATE(FIN_WAIT_1) \
|
|
CT_DPIF_TCP_STATE(CLOSING) \
|
|
CT_DPIF_TCP_STATE(LAST_ACK) \
|
|
CT_DPIF_TCP_STATE(FIN_WAIT_2) \
|
|
CT_DPIF_TCP_STATE(TIME_WAIT)
|
|
|
|
enum ct_dpif_tcp_state {
|
|
#define CT_DPIF_TCP_STATE(STATE) CT_DPIF_TCPS_##STATE,
|
|
CT_DPIF_TCP_STATES
|
|
#undef CT_DPIF_TCP_STATE
|
|
};
|
|
|
|
extern const char *ct_dpif_tcp_state_string[];
|
|
|
|
#define CT_DPIF_TCP_FLAGS \
|
|
CT_DPIF_TCP_FLAG(WINDOW_SCALE) \
|
|
CT_DPIF_TCP_FLAG(SACK_PERM) \
|
|
CT_DPIF_TCP_FLAG(CLOSE_INIT) \
|
|
CT_DPIF_TCP_FLAG(BE_LIBERAL) \
|
|
CT_DPIF_TCP_FLAG(DATA_UNACKNOWLEDGED) \
|
|
CT_DPIF_TCP_FLAG(MAXACK_SET) \
|
|
|
|
enum ct_dpif_tcp_flags_count_ {
|
|
#define CT_DPIF_TCP_FLAG(FLAG) FLAG##_COUNT_,
|
|
CT_DPIF_TCP_FLAGS
|
|
#undef CT_DPIF_TCP_FLAG
|
|
};
|
|
|
|
enum ct_dpif_tcp_flags {
|
|
#define CT_DPIF_TCP_FLAG(FLAG) CT_DPIF_TCPF_##FLAG = (1 << FLAG##_COUNT_),
|
|
CT_DPIF_TCP_FLAGS
|
|
#undef CT_DPIF_TCP_FLAG
|
|
};
|
|
|
|
struct ct_dpif_protoinfo {
|
|
uint16_t proto; /* IPPROTO_* */
|
|
union {
|
|
struct {
|
|
uint8_t state_orig;
|
|
uint8_t state_reply;
|
|
uint8_t wscale_orig;
|
|
uint8_t wscale_reply;
|
|
uint8_t flags_orig;
|
|
uint8_t flags_reply;
|
|
} tcp;
|
|
};
|
|
};
|
|
|
|
struct ct_dpif_helper {
|
|
char *name;
|
|
};
|
|
|
|
#define CT_DPIF_STATUS_FLAGS \
|
|
CT_DPIF_STATUS_FLAG(EXPECTED) \
|
|
CT_DPIF_STATUS_FLAG(SEEN_REPLY) \
|
|
CT_DPIF_STATUS_FLAG(ASSURED) \
|
|
CT_DPIF_STATUS_FLAG(CONFIRMED) \
|
|
CT_DPIF_STATUS_FLAG(SRC_NAT) \
|
|
CT_DPIF_STATUS_FLAG(DST_NAT) \
|
|
CT_DPIF_STATUS_FLAG(SEQ_ADJUST) \
|
|
CT_DPIF_STATUS_FLAG(SRC_NAT_DONE) \
|
|
CT_DPIF_STATUS_FLAG(DST_NAT_DONE) \
|
|
CT_DPIF_STATUS_FLAG(DYING) \
|
|
CT_DPIF_STATUS_FLAG(FIXED_TIMEOUT) \
|
|
CT_DPIF_STATUS_FLAG(TEMPLATE) \
|
|
CT_DPIF_STATUS_FLAG(UNTRACKED) \
|
|
|
|
enum ct_dpif_status_flags_count_ {
|
|
#define CT_DPIF_STATUS_FLAG(FLAG) FLAG##_COUNT_,
|
|
CT_DPIF_STATUS_FLAGS
|
|
#undef CT_DPIF_STATUS_FLAG
|
|
};
|
|
|
|
enum ct_dpif_status_flags {
|
|
#define CT_DPIF_STATUS_FLAG(FLAG) CT_DPIF_STATUS_##FLAG = (1 << FLAG##_COUNT_),
|
|
CT_DPIF_STATUS_FLAGS
|
|
#undef CT_DPIF_STATUS_FLAG
|
|
};
|
|
|
|
struct ct_dpif_entry {
|
|
/* Const members. */
|
|
struct ct_dpif_tuple tuple_orig;
|
|
struct ct_dpif_tuple tuple_reply;
|
|
struct ct_dpif_tuple tuple_master;
|
|
struct ct_dpif_helper helper;
|
|
uint32_t id;
|
|
uint16_t zone;
|
|
|
|
/* Modifiable members. */
|
|
|
|
struct ct_dpif_counters counters_orig;
|
|
struct ct_dpif_counters counters_reply;
|
|
|
|
struct ct_dpif_timestamp timestamp;
|
|
struct ct_dpif_protoinfo protoinfo;
|
|
|
|
ovs_u128 labels;
|
|
uint32_t status;
|
|
/* Timeout for this entry in seconds */
|
|
uint32_t timeout;
|
|
uint32_t mark;
|
|
};
|
|
|
|
struct dpif;
|
|
|
|
struct ct_dpif_dump_state {
|
|
struct dpif *dpif;
|
|
};
|
|
|
|
int ct_dpif_dump_start(struct dpif *, struct ct_dpif_dump_state **,
|
|
const uint16_t *zone);
|
|
int ct_dpif_dump_next(struct ct_dpif_dump_state *, struct ct_dpif_entry *);
|
|
int ct_dpif_dump_done(struct ct_dpif_dump_state *);
|
|
int ct_dpif_flush(struct dpif *, const uint16_t *zone);
|
|
void ct_dpif_entry_uninit(struct ct_dpif_entry *);
|
|
void ct_dpif_format_entry(const struct ct_dpif_entry *, struct ds *,
|
|
bool verbose, bool print_stats);
|
|
void ct_dpif_format_tuple(struct ds *, const struct ct_dpif_tuple *);
|
|
|
|
#endif /* CT_DPIF_H */
|