mirror of
https://github.com/openvswitch/ovs
synced 2025-08-22 01:51:26 +00:00
openflow: Add extension to flush CT by generic match.
Add extension that allows to flush connections from CT by specifying fields that the connections should be matched against. This allows to match only some fields of the connection e.g. source address for orig direction. Reported-at: https://bugzilla.redhat.com/2120546 Signed-off-by: Ales Musil <amusil@redhat.com> Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
This commit is contained in:
parent
a9ae73b916
commit
08146bf7d9
6
NEWS
6
NEWS
@ -21,6 +21,9 @@ Post-v3.0.0
|
||||
10 Gbps link speed by default in case the actual link speed cannot be
|
||||
determined. Previously it was 10 Mbps. Values can still be overridden
|
||||
by specifying 'max-rate' or '[r]stp-path-cost' accordingly.
|
||||
- OpenFlow:
|
||||
* New OpenFlow extension NXT_CT_FLUSH to flush connections matching
|
||||
the specified fields.
|
||||
- ovs-ctl:
|
||||
* New option '--dump-hugepages' to include hugepages in core dumps. This
|
||||
can assist with postmortem analysis involving DPDK, but may also produce
|
||||
@ -28,6 +31,9 @@ Post-v3.0.0
|
||||
- ovs-dpctl and 'ovs-appctl dpctl/' commands:
|
||||
* 'flush-conntrack' is now capable of handling partial 5-tuple,
|
||||
with additional optional parameter to specify the reply direction.
|
||||
- ovs-ofctl:
|
||||
* New command 'flush-conntrack' that accepts zone and 5-tuple (or partial
|
||||
5-tuple) for both directions.
|
||||
- Support for travis-ci.org based continuous integration builds has been
|
||||
dropped.
|
||||
- Userspace datapath:
|
||||
|
@ -1064,4 +1064,41 @@ struct nx_zone_id {
|
||||
};
|
||||
OFP_ASSERT(sizeof(struct nx_zone_id) == 8);
|
||||
|
||||
/* CT flush available TLVs. */
|
||||
enum nx_ct_flush_tlv_type {
|
||||
/* Outer types. */
|
||||
NXT_CT_ORIG_TUPLE = 0, /* Outer type for original tuple TLV.
|
||||
* Nested TLVs are specified
|
||||
* by 'enum nx_ct_flush_tuple_tlv_type'. */
|
||||
NXT_CT_REPLY_TUPLE = 1, /* Outer type for reply tuple TLV. *
|
||||
* Nested TLVs are specified
|
||||
* by 'enum nx_ct_flush_tuple_tlv_type'*/
|
||||
/* Primitive types. */
|
||||
NXT_CT_ZONE_ID = 2, /* be16 zone id. */
|
||||
};
|
||||
|
||||
/* CT flush nested TLVs. */
|
||||
enum nx_ct_flush_tuple_tlv_type {
|
||||
NXT_CT_TUPLE_SRC = 0, /* IPv6 or mapped IPv4 address. */
|
||||
NXT_CT_TUPLE_DST = 1, /* IPv6 or mapped IPv4 address. */
|
||||
NXT_CT_TUPLE_SRC_PORT = 2, /* be16 source port. */
|
||||
NXT_CT_TUPLE_DST_PORT = 3, /* be16 destination port. */
|
||||
NXT_CT_TUPLE_ICMP_ID = 4, /* be16 ICMP id. */
|
||||
NXT_CT_TUPLE_ICMP_TYPE = 5, /* u8 ICMP type. */
|
||||
NXT_CT_TUPLE_ICMP_CODE = 6, /* u8 ICMP code. */
|
||||
};
|
||||
|
||||
/* NXT_CT_FLUSH.
|
||||
*
|
||||
* Flushes the connection tracking entries specified by 5-tuple.
|
||||
* The struct should be followed by TLVs specifying the matching parameters.
|
||||
* Currently there is a limitation for ICMP, in order to partially match on
|
||||
* ICMP parameters the tuple should include at least SRC/DST. */
|
||||
struct nx_ct_flush {
|
||||
uint8_t ip_proto; /* IP protocol. */
|
||||
uint8_t pad[7]; /* Align to 64 bits (must be zero). */
|
||||
/* Followed by optional TLVs of type 'enum nx_ct_flush_tlv_type'. */
|
||||
};
|
||||
OFP_ASSERT(sizeof(struct nx_ct_flush) == 8);
|
||||
|
||||
#endif /* openflow/nicira-ext.h */
|
||||
|
@ -22,6 +22,8 @@
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "openflow/nicira-ext.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -59,6 +61,12 @@ void ofp_ct_match_format(struct ds *, const struct ofp_ct_match *);
|
||||
bool ofp_ct_tuple_parse(struct ofp_ct_tuple *, const char *,
|
||||
struct ds *, uint8_t *ip_proto, uint16_t *l3_type);
|
||||
|
||||
enum ofperr ofp_ct_match_decode(struct ofp_ct_match *, bool *with_zone,
|
||||
uint16_t *zone_id, const struct ofp_header *);
|
||||
struct ofpbuf *ofp_ct_match_encode(const struct ofp_ct_match *,
|
||||
uint16_t *zone_id,
|
||||
enum ofp_version version);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -515,6 +515,9 @@ enum ofpraw {
|
||||
/* NXT 1.0+ (29): struct nx_zone_id. */
|
||||
OFPRAW_NXT_CT_FLUSH_ZONE,
|
||||
|
||||
/* NXT 1.0+ (32): struct nx_ct_flush, uint8_t[8][]. */
|
||||
OFPRAW_NXT_CT_FLUSH,
|
||||
|
||||
/* NXST 1.0+ (3): void. */
|
||||
OFPRAW_NXST_IPFIX_BRIDGE_REQUEST,
|
||||
|
||||
@ -772,6 +775,7 @@ enum ofptype {
|
||||
OFPTYPE_IPFIX_FLOW_STATS_REQUEST, /* OFPRAW_NXST_IPFIX_FLOW_REQUEST */
|
||||
OFPTYPE_IPFIX_FLOW_STATS_REPLY, /* OFPRAW_NXST_IPFIX_FLOW_REPLY */
|
||||
OFPTYPE_CT_FLUSH_ZONE, /* OFPRAW_NXT_CT_FLUSH_ZONE. */
|
||||
OFPTYPE_CT_FLUSH, /* OFPRAW_NXT_CT_FLUSH. */
|
||||
|
||||
/* Flow monitor extension. */
|
||||
OFPTYPE_FLOW_MONITOR_CANCEL, /* OFPRAW_NXT_FLOW_MONITOR_CANCEL.
|
||||
|
@ -292,6 +292,7 @@ ofputil_is_bundlable(enum ofptype type)
|
||||
case OFPTYPE_IPFIX_FLOW_STATS_REQUEST:
|
||||
case OFPTYPE_IPFIX_FLOW_STATS_REPLY:
|
||||
case OFPTYPE_CT_FLUSH_ZONE:
|
||||
case OFPTYPE_CT_FLUSH:
|
||||
break;
|
||||
}
|
||||
|
||||
|
196
lib/ofp-ct.c
196
lib/ofp-ct.c
@ -23,8 +23,12 @@
|
||||
|
||||
#include "ct-dpif.h"
|
||||
#include "openvswitch/ofp-ct.h"
|
||||
#include "openflow/nicira-ext.h"
|
||||
#include "openvswitch/dynamic-string.h"
|
||||
#include "openvswitch/ofp-msgs.h"
|
||||
#include "openvswitch/ofp-parse.h"
|
||||
#include "openvswitch/ofp-errors.h"
|
||||
#include "openvswitch/ofp-prop.h"
|
||||
#include "openvswitch/ofp-util.h"
|
||||
#include "openvswitch/packets.h"
|
||||
|
||||
@ -211,3 +215,195 @@ error:
|
||||
free(copy);
|
||||
return false;
|
||||
}
|
||||
|
||||
static enum ofperr
|
||||
ofpprop_pull_ipv6(struct ofpbuf *property, struct in6_addr *addr,
|
||||
uint16_t *l3_type)
|
||||
{
|
||||
if (ofpbuf_msgsize(property) < sizeof *addr) {
|
||||
return OFPERR_OFPBPC_BAD_LEN;
|
||||
}
|
||||
|
||||
memcpy(addr, property->msg, sizeof *addr);
|
||||
|
||||
uint16_t l3 = 0;
|
||||
if (!ipv6_is_zero(addr)) {
|
||||
l3 = IN6_IS_ADDR_V4MAPPED(addr) ? AF_INET : AF_INET6;
|
||||
}
|
||||
|
||||
if (*l3_type && l3 && *l3_type != l3) {
|
||||
return OFPERR_OFPBPC_BAD_VALUE;
|
||||
}
|
||||
|
||||
*l3_type = l3;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum ofperr
|
||||
ofp_ct_tuple_decode_nested(struct ofpbuf *property, struct ofp_ct_tuple *tuple,
|
||||
uint16_t *l3_type)
|
||||
{
|
||||
struct ofpbuf nested;
|
||||
enum ofperr error = ofpprop_parse_nested(property, &nested);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
while (nested.size) {
|
||||
struct ofpbuf inner;
|
||||
uint64_t type;
|
||||
|
||||
error = ofpprop_pull(&nested, &inner, &type);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
switch (type) {
|
||||
case NXT_CT_TUPLE_SRC:
|
||||
error = ofpprop_pull_ipv6(&inner, &tuple->src, l3_type);
|
||||
break;
|
||||
|
||||
case NXT_CT_TUPLE_DST:
|
||||
error = ofpprop_pull_ipv6(&inner, &tuple->dst, l3_type);
|
||||
break;
|
||||
|
||||
case NXT_CT_TUPLE_SRC_PORT:
|
||||
error = ofpprop_parse_be16(&inner, &tuple->src_port);
|
||||
break;
|
||||
|
||||
case NXT_CT_TUPLE_DST_PORT:
|
||||
error = ofpprop_parse_be16(&inner, &tuple->dst_port);
|
||||
break;
|
||||
|
||||
case NXT_CT_TUPLE_ICMP_ID:
|
||||
error = ofpprop_parse_be16(&inner, &tuple->icmp_id);
|
||||
break;
|
||||
|
||||
case NXT_CT_TUPLE_ICMP_TYPE:
|
||||
error = ofpprop_parse_u8(&inner, &tuple->icmp_type);
|
||||
break;
|
||||
|
||||
case NXT_CT_TUPLE_ICMP_CODE:
|
||||
error = ofpprop_parse_u8(&inner, &tuple->icmp_code);
|
||||
break;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
ofp_ct_tuple_encode(const struct ofp_ct_tuple *tuple, struct ofpbuf *buf,
|
||||
enum nx_ct_flush_tlv_type type, uint8_t ip_proto)
|
||||
{
|
||||
/* 128 B is enough to hold the whole tuple. */
|
||||
uint8_t stub[128];
|
||||
struct ofpbuf nested = OFPBUF_STUB_INITIALIZER(stub);
|
||||
|
||||
if (!ipv6_is_zero(&tuple->src)) {
|
||||
ofpprop_put(&nested, NXT_CT_TUPLE_SRC, &tuple->src, sizeof tuple->src);
|
||||
}
|
||||
|
||||
if (!ipv6_is_zero(&tuple->dst)) {
|
||||
ofpprop_put(&nested, NXT_CT_TUPLE_DST, &tuple->dst, sizeof tuple->dst);
|
||||
}
|
||||
|
||||
if (ip_proto == IPPROTO_ICMP || ip_proto == IPPROTO_ICMPV6) {
|
||||
ofpprop_put_be16(&nested, NXT_CT_TUPLE_ICMP_ID, tuple->icmp_id);
|
||||
ofpprop_put_u8(&nested, NXT_CT_TUPLE_ICMP_TYPE, tuple->icmp_type);
|
||||
ofpprop_put_u8(&nested, NXT_CT_TUPLE_ICMP_CODE, tuple->icmp_code);
|
||||
} else {
|
||||
if (tuple->src_port) {
|
||||
ofpprop_put_be16(&nested, NXT_CT_TUPLE_SRC_PORT, tuple->src_port);
|
||||
}
|
||||
|
||||
if (tuple->dst_port) {
|
||||
ofpprop_put_be16(&nested, NXT_CT_TUPLE_DST_PORT, tuple->dst_port);
|
||||
}
|
||||
}
|
||||
|
||||
if (nested.size) {
|
||||
ofpprop_put_nested(buf, type, &nested);
|
||||
}
|
||||
|
||||
ofpbuf_uninit(&nested);
|
||||
}
|
||||
|
||||
enum ofperr
|
||||
ofp_ct_match_decode(struct ofp_ct_match *match, bool *with_zone,
|
||||
uint16_t *zone_id, const struct ofp_header *oh)
|
||||
{
|
||||
struct ofpbuf msg = ofpbuf_const_initializer(oh, ntohs(oh->length));
|
||||
ofpraw_pull_assert(&msg);
|
||||
|
||||
const struct nx_ct_flush *nx_flush = ofpbuf_pull(&msg, sizeof *nx_flush);
|
||||
|
||||
if (!is_all_zeros(nx_flush->pad, sizeof nx_flush->pad)) {
|
||||
return OFPERR_NXBRC_MUST_BE_ZERO;
|
||||
}
|
||||
|
||||
match->ip_proto = nx_flush->ip_proto;
|
||||
|
||||
struct ofp_ct_tuple *orig = &match->tuple_orig;
|
||||
struct ofp_ct_tuple *reply = &match->tuple_reply;
|
||||
|
||||
while (msg.size) {
|
||||
struct ofpbuf property;
|
||||
uint64_t type;
|
||||
|
||||
enum ofperr error = ofpprop_pull(&msg, &property, &type);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case NXT_CT_ORIG_TUPLE:
|
||||
error = ofp_ct_tuple_decode_nested(&property, orig,
|
||||
&match->l3_type);
|
||||
break;
|
||||
|
||||
case NXT_CT_REPLY_TUPLE:
|
||||
error = ofp_ct_tuple_decode_nested(&property, reply,
|
||||
&match->l3_type);
|
||||
break;
|
||||
|
||||
case NXT_CT_ZONE_ID:
|
||||
if (with_zone) {
|
||||
*with_zone = true;
|
||||
}
|
||||
error = ofpprop_parse_u16(&property, zone_id);
|
||||
break;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct ofpbuf *
|
||||
ofp_ct_match_encode(const struct ofp_ct_match *match, uint16_t *zone_id,
|
||||
enum ofp_version version)
|
||||
{
|
||||
struct ofpbuf *msg = ofpraw_alloc(OFPRAW_NXT_CT_FLUSH, version, 0);
|
||||
struct nx_ct_flush *nx_flush = ofpbuf_put_zeros(msg, sizeof *nx_flush);
|
||||
const struct ofp_ct_tuple *orig = &match->tuple_orig;
|
||||
const struct ofp_ct_tuple *reply = &match->tuple_reply;
|
||||
|
||||
nx_flush->ip_proto = match->ip_proto;
|
||||
|
||||
ofp_ct_tuple_encode(orig, msg, NXT_CT_ORIG_TUPLE,match->ip_proto);
|
||||
ofp_ct_tuple_encode(reply, msg, NXT_CT_REPLY_TUPLE, match->ip_proto);
|
||||
|
||||
if (zone_id) {
|
||||
ofpprop_put_u16(msg, NXT_CT_ZONE_ID, *zone_id);
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "openvswitch/ofp-actions.h"
|
||||
#include "openvswitch/ofp-bundle.h"
|
||||
#include "openvswitch/ofp-connection.h"
|
||||
#include "openvswitch/ofp-ct.h"
|
||||
#include "openvswitch/ofp-errors.h"
|
||||
#include "openvswitch/ofp-group.h"
|
||||
#include "openvswitch/ofp-ipfix.h"
|
||||
@ -949,6 +950,23 @@ ofp_print_nxt_ct_flush_zone(struct ds *string, const struct nx_zone_id *nzi)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum ofperr
|
||||
ofp_print_nxt_ct_flush(struct ds *string, const struct ofp_header *oh)
|
||||
{
|
||||
uint16_t zone_id = 0;
|
||||
struct ofp_ct_match match = {0};
|
||||
|
||||
enum ofperr error = ofp_ct_match_decode(&match, NULL, &zone_id, oh);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
ds_put_format(string, " zone=%"PRIu16" ", zone_id);
|
||||
ofp_ct_match_format(string, &match);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum ofperr
|
||||
ofp_to_string__(const struct ofp_header *oh,
|
||||
const struct ofputil_port_map *port_map,
|
||||
@ -1184,6 +1202,8 @@ ofp_to_string__(const struct ofp_header *oh,
|
||||
|
||||
case OFPTYPE_CT_FLUSH_ZONE:
|
||||
return ofp_print_nxt_ct_flush_zone(string, ofpmsg_body(oh));
|
||||
case OFPTYPE_CT_FLUSH:
|
||||
return ofp_print_nxt_ct_flush(string, oh);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1426,6 +1426,7 @@ is_admitted_msg(const struct ofpbuf *b)
|
||||
case OFPTYPE_IPFIX_FLOW_STATS_REQUEST:
|
||||
case OFPTYPE_IPFIX_FLOW_STATS_REPLY:
|
||||
case OFPTYPE_CT_FLUSH_ZONE:
|
||||
case OFPTYPE_CT_FLUSH:
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
@ -5358,11 +5358,12 @@ type_set_config(const char *type, const struct smap *other_config)
|
||||
}
|
||||
|
||||
static void
|
||||
ct_flush(const struct ofproto *ofproto_, const uint16_t *zone)
|
||||
ct_flush(const struct ofproto *ofproto_, const uint16_t *zone,
|
||||
const struct ofp_ct_match *match)
|
||||
{
|
||||
struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
|
||||
|
||||
ct_dpif_flush(ofproto->backer->dpif, zone, NULL);
|
||||
ct_dpif_flush(ofproto->backer->dpif, zone, match);
|
||||
}
|
||||
|
||||
static struct ct_timeout_policy *
|
||||
@ -5674,6 +5675,10 @@ get_datapath_cap(const char *datapath_type, struct smap *cap)
|
||||
smap_add(cap, "lb_output_action", s.lb_output_action ? "true" : "false");
|
||||
smap_add(cap, "ct_zero_snat", s.ct_zero_snat ? "true" : "false");
|
||||
smap_add(cap, "add_mpls", s.add_mpls ? "true" : "false");
|
||||
|
||||
/* The ct_tuple_flush is implemented on dpif level, so it is supported
|
||||
* for all backers. */
|
||||
smap_add(cap, "ct_flush", "true");
|
||||
}
|
||||
|
||||
/* Gets timeout policy name in 'backer' based on 'zone', 'dl_type' and
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "ofproto/ofproto.h"
|
||||
#include "openvswitch/list.h"
|
||||
#include "openvswitch/ofp-actions.h"
|
||||
#include "openvswitch/ofp-ct.h"
|
||||
#include "openvswitch/ofp-errors.h"
|
||||
#include "openvswitch/ofp-flow.h"
|
||||
#include "openvswitch/ofp-group.h"
|
||||
@ -1902,8 +1903,10 @@ struct ofproto_class {
|
||||
/* ## Connection tracking ## */
|
||||
/* ## ------------------- ## */
|
||||
/* Flushes the connection tracking tables. If 'zone' is not NULL,
|
||||
* only deletes connections in '*zone'. */
|
||||
void (*ct_flush)(const struct ofproto *, const uint16_t *zone);
|
||||
* only deletes connections in '*zone'. If 'match' is not NULL,
|
||||
* deletes connections specified by the match. */
|
||||
void (*ct_flush)(const struct ofproto *, const uint16_t *zone,
|
||||
const struct ofp_ct_match *match);
|
||||
|
||||
/* Sets conntrack timeout policy specified by 'timeout_policy' to 'zone'
|
||||
* in datapath type 'dp_type'. */
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "openvswitch/meta-flow.h"
|
||||
#include "openvswitch/ofp-actions.h"
|
||||
#include "openvswitch/ofp-bundle.h"
|
||||
#include "openvswitch/ofp-ct.h"
|
||||
#include "openvswitch/ofp-errors.h"
|
||||
#include "openvswitch/ofp-match.h"
|
||||
#include "openvswitch/ofp-msgs.h"
|
||||
@ -934,7 +935,30 @@ handle_nxt_ct_flush_zone(struct ofconn *ofconn, const struct ofp_header *oh)
|
||||
|
||||
uint16_t zone = ntohs(nzi->zone_id);
|
||||
if (ofproto->ofproto_class->ct_flush) {
|
||||
ofproto->ofproto_class->ct_flush(ofproto, &zone);
|
||||
ofproto->ofproto_class->ct_flush(ofproto, &zone, NULL);
|
||||
} else {
|
||||
return EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum ofperr
|
||||
handle_nxt_ct_flush(struct ofconn *ofconn, const struct ofp_header *oh)
|
||||
{
|
||||
struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
|
||||
struct ofp_ct_match match = {0};
|
||||
bool with_zone = false;
|
||||
uint16_t zone_id = 0;
|
||||
|
||||
enum ofperr error = ofp_ct_match_decode(&match, &with_zone, &zone_id, oh);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
if (ofproto->ofproto_class->ct_flush) {
|
||||
ofproto->ofproto_class->ct_flush(ofproto, with_zone ? &zone_id : NULL,
|
||||
&match);
|
||||
} else {
|
||||
return EOPNOTSUPP;
|
||||
}
|
||||
@ -8787,6 +8811,9 @@ handle_single_part_openflow(struct ofconn *ofconn, const struct ofp_header *oh,
|
||||
case OFPTYPE_CT_FLUSH_ZONE:
|
||||
return handle_nxt_ct_flush_zone(ofconn, oh);
|
||||
|
||||
case OFPTYPE_CT_FLUSH:
|
||||
return handle_nxt_ct_flush(ofconn, oh);
|
||||
|
||||
case OFPTYPE_HELLO:
|
||||
case OFPTYPE_ERROR:
|
||||
case OFPTYPE_FEATURES_REPLY:
|
||||
|
@ -4073,3 +4073,111 @@ AT_CHECK([ovs-ofctl ofp-print "\
|
||||
NXT_CT_FLUSH_ZONE (xid=0x3): zone_id=13
|
||||
])
|
||||
AT_CLEANUP
|
||||
|
||||
AT_SETUP([NXT_CT_FLUSH])
|
||||
AT_KEYWORDS([ofp-print])
|
||||
AT_CHECK([ovs-ofctl ofp-print "\
|
||||
01 04 00 18 00 00 00 03 00 00 23 20 00 00 00 20 \
|
||||
06 \
|
||||
00 00 00 00 00 00 00 \
|
||||
"], [0], [dnl
|
||||
NXT_CT_FLUSH (xid=0x3): zone=0 'ct_ipv6_src=::,ct_ipv6_dst=::,ct_tp_src=0,ct_tp_dst=0,ct_nw_proto=6' 'ct_ipv6_src=::,ct_ipv6_dst=::,ct_tp_src=0,ct_tp_dst=0'
|
||||
])
|
||||
|
||||
AT_CHECK([ovs-ofctl ofp-print "\
|
||||
01 04 00 20 00 00 00 03 00 00 23 20 00 00 00 20 \
|
||||
06 \
|
||||
00 00 00 00 00 00 00 \
|
||||
00 02 00 08 00 0d 00 00 \
|
||||
"], [0], [dnl
|
||||
NXT_CT_FLUSH (xid=0x3): zone=13 'ct_ipv6_src=::,ct_ipv6_dst=::,ct_tp_src=0,ct_tp_dst=0,ct_nw_proto=6' 'ct_ipv6_src=::,ct_ipv6_dst=::,ct_tp_src=0,ct_tp_dst=0'
|
||||
])
|
||||
|
||||
AT_CHECK([ovs-ofctl ofp-print "\
|
||||
01 04 00 68 00 00 00 03 00 00 23 20 00 00 00 20 \
|
||||
06 \
|
||||
00 00 00 00 00 00 00 \
|
||||
00 02 00 08 00 0d 00 00 \
|
||||
00 00 00 48 00 00 00 00 \
|
||||
00 00 00 14 00 00 00 00 00 00 00 00 00 00 ff ff 0a 0a 00 01 00 00 00 00 \
|
||||
00 01 00 14 00 00 00 00 00 00 00 00 00 00 ff ff 0a 0a 00 02 00 00 00 00 \
|
||||
00 02 00 08 00 50 00 00 \
|
||||
00 03 00 08 1f 90 00 00 \
|
||||
"], [0], [dnl
|
||||
NXT_CT_FLUSH (xid=0x3): zone=13 'ct_nw_src=10.10.0.1,ct_nw_dst=10.10.0.2,ct_tp_src=80,ct_tp_dst=8080,ct_nw_proto=6' 'ct_nw_src=::,ct_nw_dst=::,ct_tp_src=0,ct_tp_dst=0'
|
||||
])
|
||||
|
||||
AT_CHECK([ovs-ofctl ofp-print "\
|
||||
01 04 00 68 00 00 00 03 00 00 23 20 00 00 00 20 \
|
||||
06 \
|
||||
00 00 00 00 00 00 00 \
|
||||
00 02 00 08 00 0d 00 00 \
|
||||
00 01 00 48 00 00 00 00 \
|
||||
00 01 00 14 00 00 00 00 00 00 00 00 00 00 ff ff 0a 0a 00 01 00 00 00 00 \
|
||||
00 00 00 14 00 00 00 00 00 00 00 00 00 00 ff ff 0a 0a 00 02 00 00 00 00 \
|
||||
00 03 00 08 00 50 00 00 \
|
||||
00 02 00 08 1f 90 00 00 \
|
||||
"], [0], [dnl
|
||||
NXT_CT_FLUSH (xid=0x3): zone=13 'ct_nw_src=::,ct_nw_dst=::,ct_tp_src=0,ct_tp_dst=0,ct_nw_proto=6' 'ct_nw_src=10.10.0.2,ct_nw_dst=10.10.0.1,ct_tp_src=8080,ct_tp_dst=80'
|
||||
])
|
||||
|
||||
AT_CHECK([ovs-ofctl ofp-print "\
|
||||
01 04 00 b0 00 00 00 03 00 00 23 20 00 00 00 20 \
|
||||
06 \
|
||||
00 00 00 00 00 00 00 \
|
||||
00 02 00 08 00 0d 00 00 \
|
||||
00 00 00 48 00 00 00 00 \
|
||||
00 00 00 14 00 00 00 00 00 00 00 00 00 00 ff ff 0a 0a 00 01 00 00 00 00 \
|
||||
00 01 00 14 00 00 00 00 00 00 00 00 00 00 ff ff 0a 0a 00 02 00 00 00 00 \
|
||||
00 02 00 08 00 50 00 00 \
|
||||
00 03 00 08 1f 90 00 00 \
|
||||
00 01 00 48 00 00 00 00 \
|
||||
00 01 00 14 00 00 00 00 00 00 00 00 00 00 ff ff 0a 0a 00 01 00 00 00 00 \
|
||||
00 00 00 14 00 00 00 00 00 00 00 00 00 00 ff ff 0a 0a 00 02 00 00 00 00 \
|
||||
00 03 00 08 00 50 00 00 \
|
||||
00 02 00 08 1f 90 00 00 \
|
||||
"], [0], [dnl
|
||||
NXT_CT_FLUSH (xid=0x3): zone=13 'ct_nw_src=10.10.0.1,ct_nw_dst=10.10.0.2,ct_tp_src=80,ct_tp_dst=8080,ct_nw_proto=6' 'ct_nw_src=10.10.0.2,ct_nw_dst=10.10.0.1,ct_tp_src=8080,ct_tp_dst=80'
|
||||
])
|
||||
|
||||
AT_CHECK([ovs-ofctl ofp-print "\
|
||||
01 04 00 b8 00 00 00 03 00 00 23 20 00 00 00 20 \
|
||||
01 \
|
||||
00 00 00 00 00 00 00 \
|
||||
00 00 00 50 00 00 00 00 \
|
||||
00 00 00 14 fd 18 00 00 00 00 00 00 00 00 ff ff ab cd 00 01 00 00 00 00 \
|
||||
00 01 00 14 fd 18 00 00 00 00 00 00 00 00 ff ff ab cd 00 02 00 00 00 00 \
|
||||
00 04 00 08 00 0a 00 00 \
|
||||
00 05 00 05 01 00 00 00 \
|
||||
00 06 00 05 02 00 00 00 \
|
||||
00 01 00 50 00 00 00 00 \
|
||||
00 01 00 14 fd 18 00 00 00 00 00 00 00 00 ff ff ab cd 00 02 00 00 00 00 \
|
||||
00 00 00 14 fd 18 00 00 00 00 00 00 00 00 ff ff ab cd 00 01 00 00 00 00 \
|
||||
00 04 00 08 00 0a 00 00 \
|
||||
00 05 00 05 03 00 00 00 \
|
||||
00 06 00 05 04 00 00 00 \
|
||||
"], [0], [dnl
|
||||
NXT_CT_FLUSH (xid=0x3): zone=0 'ct_ipv6_src=fd18::ffff:abcd:1,ct_ipv6_dst=fd18::ffff:abcd:2,icmp_id=10,icmp_type=1,icmp_code=2,ct_nw_proto=1' 'ct_ipv6_src=fd18::ffff:abcd:1,ct_ipv6_dst=fd18::ffff:abcd:2,icmp_id=10,icmp_type=3,icmp_code=4'
|
||||
])
|
||||
|
||||
AT_CHECK([ovs-ofctl ofp-print "\
|
||||
01 04 00 58 00 00 00 03 00 00 23 20 00 00 00 20 \
|
||||
06 \
|
||||
00 00 00 00 00 00 00 \
|
||||
00 02 00 08 00 0d 00 00 \
|
||||
00 00 00 38 00 00 00 00 \
|
||||
00 00 00 14 00 0a 00 00 00 00 00 00 00 00 ff ff 0a 0a 00 01 00 00 00 00 \
|
||||
00 01 00 14 00 00 00 00 00 00 00 00 00 00 ff ff 0a 0a 00 02 00 00 00 00 \
|
||||
" | grep -q OFPBPC_BAD_VALUE], [0])
|
||||
|
||||
AT_CHECK([ovs-ofctl ofp-print "\
|
||||
01 04 00 60 00 00 00 03 00 00 23 20 00 00 00 20 \
|
||||
06 \
|
||||
00 00 00 00 00 00 00 \
|
||||
00 02 00 08 00 0d 00 00 \
|
||||
00 00 00 20 00 00 00 00 \
|
||||
00 00 00 14 00 0a 00 00 00 00 00 00 00 00 ff ff 0a 0a 00 01 00 00 00 00 \
|
||||
00 01 00 20 00 00 00 00 \
|
||||
00 00 00 14 00 00 00 00 00 00 00 00 00 00 ff ff 0a 0a 00 02 00 00 00 00 \
|
||||
" | grep -q OFPBPC_BAD_VALUE], [0])
|
||||
AT_CLEANUP
|
||||
|
@ -3271,3 +3271,41 @@ AT_CHECK([ovs-ofctl -O OpenFlow15 dump-flows br0 | ofctl_strip | sed '/OFPST_FLO
|
||||
|
||||
OVS_VSWITCHD_STOP(["/Flow exceeded the maximum flow statistics reply size and was excluded from the response set/d"])
|
||||
AT_CLEANUP
|
||||
|
||||
AT_SETUP([ovs-ofctl ct-flush])
|
||||
OVS_VSWITCHD_START
|
||||
|
||||
AT_CHECK([ovs-appctl vlog/set ct_dpif:dbg])
|
||||
|
||||
# Check flush conntrack with both zone and tuple
|
||||
AT_CHECK([ovs-ofctl ct-flush br0 zone=5 'ct_nw_src=10.1.1.1,ct_nw_dst=10.1.1.2,ct_nw_proto=17,ct_tp_src=1'])
|
||||
|
||||
OVS_WAIT_UNTIL([test $(grep -c "|ct_dpif|DBG|.*ct_flush" ovs-vswitchd.log) -eq 1])
|
||||
AT_CHECK([grep -q "ct_dpif|DBG|.*ct_flush: zone=5 'ct_nw_src=10.1.1.1,ct_nw_dst=10.1.1.2,ct_tp_src=1,ct_tp_dst=0,ct_nw_proto=17' 'ct_nw_src=::,ct_nw_dst=::,ct_tp_src=0,ct_tp_dst=0'" ovs-vswitchd.log])
|
||||
|
||||
# Check flush-conntrack just with tuple
|
||||
AT_CHECK([ovs-ofctl ct-flush br0 'ct_nw_src=10.1.1.3,ct_nw_dst=10.1.1.4,ct_nw_proto=17,ct_tp_src=1'])
|
||||
|
||||
OVS_WAIT_UNTIL([test $(grep -c "|ct_dpif|DBG|.*ct_flush" ovs-vswitchd.log) -eq 2])
|
||||
AT_CHECK([grep -q "ct_dpif|DBG|.*ct_flush: zone=0 'ct_nw_src=10.1.1.3,ct_nw_dst=10.1.1.4,ct_tp_src=1,ct_tp_dst=0,ct_nw_proto=17' 'ct_nw_src=::,ct_nw_dst=::,ct_tp_src=0,ct_tp_dst=0'" ovs-vswitchd.log])
|
||||
|
||||
# Check flush-conntrack with reply tuple
|
||||
AT_CHECK([ovs-ofctl ct-flush br0 '' 'ct_nw_src=10.1.1.3,ct_nw_dst=10.1.1.4,ct_nw_proto=17,ct_tp_src=1'])
|
||||
|
||||
OVS_WAIT_UNTIL([test $(grep -c "|ct_dpif|DBG|.*ct_flush" ovs-vswitchd.log) -eq 3])
|
||||
AT_CHECK([grep -q "ct_dpif|DBG|.*ct_flush: zone=0 'ct_nw_src=::,ct_nw_dst=::,ct_tp_src=0,ct_tp_dst=0,ct_nw_proto=17' 'ct_nw_src=10.1.1.3,ct_nw_dst=10.1.1.4,ct_tp_src=1,ct_tp_dst=0'" ovs-vswitchd.log])
|
||||
|
||||
# Check flush-conntrack with zone and reply tuple
|
||||
AT_CHECK([ovs-ofctl ct-flush br0 zone=5 '' 'ct_nw_src=10.1.1.3,ct_nw_dst=10.1.1.4,ct_nw_proto=17,ct_tp_src=1'])
|
||||
|
||||
OVS_WAIT_UNTIL([test $(grep -c "|ct_dpif|DBG|.*ct_flush" ovs-vswitchd.log) -eq 4])
|
||||
AT_CHECK([grep -q "ct_dpif|DBG|.*ct_flush: zone=5 'ct_nw_src=::,ct_nw_dst=::,ct_tp_src=0,ct_tp_dst=0,ct_nw_proto=17' 'ct_nw_src=10.1.1.3,ct_nw_dst=10.1.1.4,ct_tp_src=1,ct_tp_dst=0'" ovs-vswitchd.log])
|
||||
|
||||
# Check flush-conntrack without any tuple and zone
|
||||
AT_CHECK([ovs-ofctl ct-flush br0])
|
||||
|
||||
OVS_WAIT_UNTIL([test $(grep -c "|ct_dpif|DBG|.*ct_flush" ovs-vswitchd.log) -eq 5])
|
||||
AT_CHECK([grep -q "ct_dpif|DBG|.*ct_flush: <all>" ovs-vswitchd.log])
|
||||
|
||||
OVS_VSWITCHD_STOP
|
||||
AT_CLEANUP
|
||||
|
@ -2298,6 +2298,10 @@ priority=100,in_port=2,icmp,action=ct(zone=5,commit),1
|
||||
|
||||
AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt])
|
||||
|
||||
m4_foreach([FLUSH_CMD], [[ovs-appctl dpctl/flush-conntrack],
|
||||
[ovs-ofctl ct-flush br0]], [
|
||||
AS_BOX([Testing with FLUSH_CMD])
|
||||
|
||||
dnl Test UDP from port 1
|
||||
AT_CHECK([ovs-ofctl -O OpenFlow13 packet-out br0 "in_port=1 packet=50540000000a50540000000908004500001c000000000011a4cd0a0101010a0101020001000200080000 actions=resubmit(,0)"])
|
||||
|
||||
@ -2305,10 +2309,10 @@ AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "orig=.src=10\.1\.1\.1,"], [],
|
||||
udp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=1,dport=2),reply=(src=10.1.1.2,dst=10.1.1.1,sport=2,dport=1)
|
||||
])
|
||||
|
||||
AT_CHECK([ovs-appctl dpctl/flush-conntrack 'ct_nw_src=10.1.1.2,ct_nw_dst=10.1.1.1,ct_nw_proto=17,ct_tp_src=2,ct_tp_dst=1'])
|
||||
AT_CHECK([FLUSH_CMD 'ct_nw_src=10.1.1.2,ct_nw_dst=10.1.1.1,ct_nw_proto=17,ct_tp_src=2,ct_tp_dst=1'])
|
||||
|
||||
AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "orig=.src=10\.1\.1\.1,"], [1])
|
||||
|
||||
AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "orig=.src=10\.1\.1\.1,"], [1], [dnl
|
||||
])
|
||||
|
||||
dnl Test UDP from port 2
|
||||
AT_CHECK([ovs-ofctl -O OpenFlow13 packet-out br0 "in_port=2 packet=50540000000a50540000000908004500001c000000000011a4cd0a0101020a0101010002000100080000 actions=resubmit(,0)"])
|
||||
@ -2317,10 +2321,9 @@ AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "orig=.src=10\.1\.1\.2,"], [0],
|
||||
udp,orig=(src=10.1.1.2,dst=10.1.1.1,sport=2,dport=1),reply=(src=10.1.1.1,dst=10.1.1.2,sport=1,dport=2),zone=5
|
||||
])
|
||||
|
||||
AT_CHECK([ovs-appctl dpctl/flush-conntrack zone=5 'ct_nw_src=10.1.1.1,ct_nw_dst=10.1.1.2,ct_nw_proto=17,ct_tp_src=1,ct_tp_dst=2'])
|
||||
AT_CHECK([FLUSH_CMD zone=5 'ct_nw_src=10.1.1.1,ct_nw_dst=10.1.1.2,ct_nw_proto=17,ct_tp_src=1,ct_tp_dst=2'])
|
||||
|
||||
AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1.2)], [0], [dnl
|
||||
])
|
||||
AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1.2)], [0])
|
||||
|
||||
dnl Test ICMP traffic
|
||||
NS_CHECK_EXEC([at_ns1], [ping -q -c 3 -i 0.3 -w 2 10.1.1.1 | FORMAT_PING], [0], [dnl
|
||||
@ -2334,7 +2337,7 @@ icmp,orig=(src=10.1.1.2,dst=10.1.1.1,id=<cleared>,type=8,code=0),reply=(src=10.1
|
||||
|
||||
ICMP_ID=`cat stdout | cut -d ',' -f4 | cut -d '=' -f2`
|
||||
ICMP_TUPLE=ct_nw_src=10.1.1.2,ct_nw_dst=10.1.1.1,ct_nw_proto=1,icmp_id=$ICMP_ID,icmp_type=8,icmp_code=0
|
||||
AT_CHECK([ovs-appctl dpctl/flush-conntrack zone=5 $ICMP_TUPLE])
|
||||
AT_CHECK([FLUSH_CMD zone=5 $ICMP_TUPLE])
|
||||
|
||||
AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "orig=.src=10\.1\.1\.2,"], [1], [dnl
|
||||
])
|
||||
@ -2349,13 +2352,13 @@ udp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=1,dport=2),reply=(src=10.1.1.2,dst=10.
|
||||
udp,orig=(src=10.1.1.2,dst=10.1.1.1,sport=2,dport=1),reply=(src=10.1.1.1,dst=10.1.1.2,sport=1,dport=2),zone=5
|
||||
])
|
||||
|
||||
AT_CHECK([ovs-appctl dpctl/flush-conntrack 'ct_nw_proto=17,ct_tp_src=1'])
|
||||
AT_CHECK([FLUSH_CMD 'ct_nw_proto=17,ct_tp_src=1'])
|
||||
|
||||
AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "10\.1\.1\.1"], [0], [dnl
|
||||
udp,orig=(src=10.1.1.2,dst=10.1.1.1,sport=2,dport=1),reply=(src=10.1.1.1,dst=10.1.1.2,sport=1,dport=2),zone=5
|
||||
])
|
||||
|
||||
AT_CHECK([ovs-appctl dpctl/flush-conntrack 'ct_nw_proto=17,ct_tp_src=2'])
|
||||
AT_CHECK([FLUSH_CMD 'ct_nw_proto=17,ct_tp_src=2'])
|
||||
|
||||
AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "10\.1\.1\.1"], [1])
|
||||
|
||||
@ -2369,13 +2372,13 @@ udp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=1,dport=2),reply=(src=10.1.1.2,dst=10.
|
||||
udp,orig=(src=10.1.1.2,dst=10.1.1.1,sport=2,dport=1),reply=(src=10.1.1.1,dst=10.1.1.2,sport=1,dport=2),zone=5
|
||||
])
|
||||
|
||||
AT_CHECK([ovs-appctl dpctl/flush-conntrack 'ct_nw_proto=17,ct_tp_dst=2'])
|
||||
AT_CHECK([FLUSH_CMD 'ct_nw_proto=17,ct_tp_dst=2'])
|
||||
|
||||
AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "10\.1\.1\.1"], [0], [dnl
|
||||
udp,orig=(src=10.1.1.2,dst=10.1.1.1,sport=2,dport=1),reply=(src=10.1.1.1,dst=10.1.1.2,sport=1,dport=2),zone=5
|
||||
])
|
||||
|
||||
AT_CHECK([ovs-appctl dpctl/flush-conntrack 'ct_nw_proto=17,ct_tp_dst=1'])
|
||||
AT_CHECK([FLUSH_CMD 'ct_nw_proto=17,ct_tp_dst=1'])
|
||||
|
||||
AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "10\.1\.1\.1"], [1])
|
||||
|
||||
@ -2389,13 +2392,13 @@ udp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=1,dport=2),reply=(src=10.1.1.2,dst=10.
|
||||
udp,orig=(src=10.1.1.2,dst=10.1.1.1,sport=2,dport=1),reply=(src=10.1.1.1,dst=10.1.1.2,sport=1,dport=2),zone=5
|
||||
])
|
||||
|
||||
AT_CHECK([ovs-appctl dpctl/flush-conntrack 'ct_nw_src=10.1.1.1'])
|
||||
AT_CHECK([FLUSH_CMD 'ct_nw_src=10.1.1.1'])
|
||||
|
||||
AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "10\.1\.1\.1"], [0], [dnl
|
||||
udp,orig=(src=10.1.1.2,dst=10.1.1.1,sport=2,dport=1),reply=(src=10.1.1.1,dst=10.1.1.2,sport=1,dport=2),zone=5
|
||||
])
|
||||
|
||||
AT_CHECK([ovs-appctl dpctl/flush-conntrack 'ct_nw_src=10.1.1.2'])
|
||||
AT_CHECK([FLUSH_CMD 'ct_nw_src=10.1.1.2'])
|
||||
|
||||
AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "10\.1\.1\.1"], [1])
|
||||
|
||||
@ -2409,13 +2412,13 @@ udp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=1,dport=2),reply=(src=10.1.1.2,dst=10.
|
||||
udp,orig=(src=10.1.1.2,dst=10.1.1.1,sport=2,dport=1),reply=(src=10.1.1.1,dst=10.1.1.2,sport=1,dport=2),zone=5
|
||||
])
|
||||
|
||||
AT_CHECK([ovs-appctl dpctl/flush-conntrack 'ct_nw_dst=10.1.1.2'])
|
||||
AT_CHECK([FLUSH_CMD 'ct_nw_dst=10.1.1.2'])
|
||||
|
||||
AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "10\.1\.1\.1"], [0], [dnl
|
||||
udp,orig=(src=10.1.1.2,dst=10.1.1.1,sport=2,dport=1),reply=(src=10.1.1.1,dst=10.1.1.2,sport=1,dport=2),zone=5
|
||||
])
|
||||
|
||||
AT_CHECK([ovs-appctl dpctl/flush-conntrack 'ct_nw_dst=10.1.1.1'])
|
||||
AT_CHECK([FLUSH_CMD 'ct_nw_dst=10.1.1.1'])
|
||||
|
||||
AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "10\.1\.1\.1"], [1])
|
||||
|
||||
@ -2429,15 +2432,16 @@ udp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=1,dport=2),reply=(src=10.1.1.2,dst=10.
|
||||
udp,orig=(src=10.1.1.2,dst=10.1.1.1,sport=2,dport=1),reply=(src=10.1.1.1,dst=10.1.1.2,sport=1,dport=2),zone=5
|
||||
])
|
||||
|
||||
AT_CHECK([ovs-appctl dpctl/flush-conntrack '' 'ct_nw_src=10.1.1.2'])
|
||||
AT_CHECK([FLUSH_CMD '' 'ct_nw_src=10.1.1.2'])
|
||||
|
||||
AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "10\.1\.1\.1"], [0], [dnl
|
||||
udp,orig=(src=10.1.1.2,dst=10.1.1.1,sport=2,dport=1),reply=(src=10.1.1.1,dst=10.1.1.2,sport=1,dport=2),zone=5
|
||||
])
|
||||
|
||||
AT_CHECK([ovs-appctl dpctl/flush-conntrack zone=5 '' 'ct_nw_src=10.1.1.1'])
|
||||
AT_CHECK([FLUSH_CMD zone=5 '' 'ct_nw_src=10.1.1.1'])
|
||||
|
||||
AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "10\.1\.1\.1"], [1])
|
||||
])
|
||||
|
||||
OVS_TRAFFIC_VSWITCHD_STOP
|
||||
AT_CLEANUP
|
||||
|
@ -296,6 +296,37 @@ Flushes the connection tracking entries in \fIzone\fR on \fIswitch\fR.
|
||||
This command uses an Open vSwitch extension that is only in Open
|
||||
vSwitch 2.6 and later.
|
||||
.
|
||||
.IP "\fBct\-flush \fIswitch [zone=N] [ct-orig-tuple [ct-reply-tuple]]\fR
|
||||
Flushes the connection entries on \fIswitch\fR based on \fIzone\fR and
|
||||
connection tracking tuples \fIct-[orig|reply]-tuple\fR.
|
||||
.IP
|
||||
If \fIct-[orig|reply]-tuple\fR is not provided, flushes all the connection
|
||||
entries. If \fIzone\fR is specified, only flushes the connections in
|
||||
\fIzone\fR.
|
||||
.IP
|
||||
If \fIct-[orig|reply]-tuple\fR is provided, flushes the connection entry
|
||||
specified by \fIct-[orig|reply]-tuple\fR in \fIzone\fR. The zone defaults
|
||||
to 0 if it is not provided. The userspace connection tracker requires flushing
|
||||
with the original pre-NATed tuple and a warning log will be otherwise
|
||||
generated. The tuple can be partial and will remove all connections that are
|
||||
matching on the specified fields. In order to specify only
|
||||
\fIct-reply-tuple\fR, provide empty string as \fIct-orig-tuple\fR.
|
||||
.IP
|
||||
Note: Currently there is limitation for matching on ICMP, in order to partially
|
||||
match on ICMP parameters the \fIct-[orig|reply]-tuple\fR has to include
|
||||
either source or destination IP.
|
||||
.IP
|
||||
An example of an IPv4 ICMP \fIct-[orig|reply]-tuple\fR:
|
||||
.IP
|
||||
"ct_nw_src=10.1.1.1,ct_nw_dst=10.1.1.2,ct_nw_proto=1,icmp_type=8,icmp_code=0,icmp_id=10"
|
||||
.IP
|
||||
An example of an IPv6 TCP \fIct-[orig|reply]-tuple\fR:
|
||||
.IP
|
||||
"ct_ipv6_src=fc00::1,ct_ipv6_dst=fc00::2,ct_nw_proto=6,ct_tp_src=1,ct_tp_dst=2"
|
||||
.IP
|
||||
This command uses an Open vSwitch extension that is only in Open vSwitch 3.1
|
||||
and later.
|
||||
.
|
||||
.SS "OpenFlow Switch Flow Table Commands"
|
||||
.
|
||||
These commands manage the flow table in an OpenFlow switch. In each
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include "openvswitch/meta-flow.h"
|
||||
#include "openvswitch/ofp-actions.h"
|
||||
#include "openvswitch/ofp-bundle.h"
|
||||
#include "openvswitch/ofp-ct.h"
|
||||
#include "openvswitch/ofp-errors.h"
|
||||
#include "openvswitch/ofp-group.h"
|
||||
#include "openvswitch/ofp-match.h"
|
||||
@ -485,6 +486,9 @@ usage(void)
|
||||
" dump-ipfix-bridge SWITCH print ipfix stats of bridge\n"
|
||||
" dump-ipfix-flow SWITCH print flow ipfix of a bridge\n"
|
||||
" ct-flush-zone SWITCH ZONE flush conntrack entries in ZONE\n"
|
||||
" ct-flush SWITCH [ZONE] [CT_ORIG_TUPLE [CT_REPLY_TUPLE]]\n"
|
||||
" flush conntrack entries specified\n"
|
||||
" by CT_ORIG/REPLY_TUPLE and ZONE\n"
|
||||
"\nFor OpenFlow switches and controllers:\n"
|
||||
" probe TARGET probe whether TARGET is up\n"
|
||||
" ping TARGET [N] latency of N-byte echos\n"
|
||||
@ -3050,6 +3054,50 @@ ofctl_ct_flush_zone(struct ovs_cmdl_context *ctx)
|
||||
vconn_close(vconn);
|
||||
}
|
||||
|
||||
static void
|
||||
ofctl_ct_flush(struct ovs_cmdl_context *ctx)
|
||||
{
|
||||
struct vconn *vconn;
|
||||
struct ofp_ct_match match = {0};
|
||||
struct ds ds = DS_EMPTY_INITIALIZER;
|
||||
uint16_t zone, *pzone = NULL;
|
||||
int args = ctx->argc - 2;
|
||||
|
||||
/* Parse zone. */
|
||||
if (args && !strncmp(ctx->argv[2], "zone=", 5)) {
|
||||
if (!ovs_scan(ctx->argv[2], "zone=%"SCNu16, &zone)) {
|
||||
ovs_fatal(0, "Failed to parse zone");
|
||||
}
|
||||
pzone = &zone;
|
||||
args--;
|
||||
}
|
||||
|
||||
/* Parse ct tuples. */
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (!args) {
|
||||
break;
|
||||
}
|
||||
|
||||
struct ofp_ct_tuple *tuple =
|
||||
i ? &match.tuple_reply : &match.tuple_orig;
|
||||
const char *arg = ctx->argv[ctx->argc - args];
|
||||
|
||||
if (arg[0] && !ofp_ct_tuple_parse(tuple, arg, &ds, &match.ip_proto,
|
||||
&match.l3_type)) {
|
||||
ovs_fatal(0, "Failed to parse ct-tuple: %s", ds_cstr(&ds));
|
||||
}
|
||||
args--;
|
||||
}
|
||||
|
||||
open_vconn(ctx->argv[1], &vconn);
|
||||
enum ofp_version version = vconn_get_version(vconn);
|
||||
struct ofpbuf *msg = ofp_ct_match_encode(&match, pzone, version);
|
||||
|
||||
ds_destroy(&ds);
|
||||
transact_noreply(vconn, msg);
|
||||
vconn_close(vconn);
|
||||
}
|
||||
|
||||
static void
|
||||
ofctl_dump_ipfix_flow(struct ovs_cmdl_context *ctx)
|
||||
{
|
||||
@ -5063,6 +5111,9 @@ static const struct ovs_cmdl_command all_commands[] = {
|
||||
{ "ct-flush-zone", "switch zone",
|
||||
2, 2, ofctl_ct_flush_zone, OVS_RO },
|
||||
|
||||
{ "ct-flush", "switch [zone=N] [ct-orig-tuple [ct-reply-tuple]]",
|
||||
1, 4, ofctl_ct_flush, OVS_RO },
|
||||
|
||||
{ "ofp-parse", "file",
|
||||
1, 1, ofctl_ofp_parse, OVS_RW },
|
||||
{ "ofp-parse-pcap", "pcap",
|
||||
|
Loading…
x
Reference in New Issue
Block a user