Skip to content
Snippets Groups Projects
Verified Commit f36fb0b7 authored by Louis Abel's avatar Louis Abel :tv:
Browse files

import

parent 1ab38673
No related branches found
No related tags found
No related merge requests found
Source diff could not be displayed: it is too large. Options to address this: view the blob.
diff --git a/NEWS b/NEWS
index 559a51ba3f..f2497d5cec 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,6 @@
+v2.16.1 - xx xxx xxxx
+---------------------
+
v2.16.0 - 16 Aug 2021
---------------------
- Removed support for 1024-bit Diffie-Hellman key exchange, which is now
diff --git a/configure.ac b/configure.ac
index 16b32be965..4def2ebd0a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -13,7 +13,7 @@
# limitations under the License.
AC_PREREQ(2.63)
-AC_INIT(openvswitch, 2.16.0, bugs@openvswitch.org)
+AC_INIT(openvswitch, 2.16.1, bugs@openvswitch.org)
AC_CONFIG_SRCDIR([datapath/datapath.c])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_AUX_DIR([build-aux])
diff --git a/debian/changelog b/debian/changelog
index 239d210b96..0f521be4d8 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+openvswitch (2.16.1-1) unstable; urgency=low
+ [ Open vSwitch team ]
+ * New upstream version
+
+ -- Open vSwitch team <dev@openvswitch.org> Mon, 16 Aug 2021 22:08:13 +0200
+
openvswitch (2.16.0-1) unstable; urgency=low
* New upstream version
diff --git a/include/openvswitch/json.h b/include/openvswitch/json.h
index 73b562e03d..0831a9cee1 100644
--- a/include/openvswitch/json.h
+++ b/include/openvswitch/json.h
@@ -50,7 +50,9 @@ enum json_type {
JSON_INTEGER, /* 123. */
JSON_REAL, /* 123.456. */
JSON_STRING, /* "..." */
- JSON_N_TYPES
+ JSON_N_TYPES,
+ JSON_SERIALIZED_OBJECT, /* Internal type to hold serialized version of
+ * data of other types. */
};
const char *json_type_to_string(enum json_type);
@@ -70,7 +72,7 @@ struct json {
struct json_array array;
long long int integer;
double real;
- char *string;
+ char *string; /* JSON_STRING or JSON_SERIALIZED_OBJECT. */
};
};
@@ -78,6 +80,7 @@ struct json *json_null_create(void);
struct json *json_boolean_create(bool);
struct json *json_string_create(const char *);
struct json *json_string_create_nocopy(char *);
+struct json *json_serialized_object_create(const struct json *);
struct json *json_integer_create(long long int);
struct json *json_real_create(double);
@@ -99,6 +102,7 @@ void json_object_put_format(struct json *,
OVS_PRINTF_FORMAT(3, 4);
const char *json_string(const struct json *);
+const char *json_serialized_object(const struct json *);
struct json_array *json_array(const struct json *);
struct shash *json_object(const struct json *);
bool json_boolean(const struct json *);
@@ -125,6 +129,7 @@ struct json *json_parser_finish(struct json_parser *);
void json_parser_abort(struct json_parser *);
struct json *json_from_string(const char *string);
+struct json *json_from_serialized_object(const struct json *);
struct json *json_from_file(const char *file_name);
struct json *json_from_stream(FILE *stream);
diff --git a/lib/dp-packet.h b/lib/dp-packet.h
index 08d93c2779..3dc582fbfd 100644
--- a/lib/dp-packet.h
+++ b/lib/dp-packet.h
@@ -199,6 +199,7 @@ struct dp_packet *dp_packet_clone_data_with_headroom(const void *, size_t,
void dp_packet_resize(struct dp_packet *b, size_t new_headroom,
size_t new_tailroom);
static inline void dp_packet_delete(struct dp_packet *);
+static inline void dp_packet_swap(struct dp_packet *, struct dp_packet *);
static inline void *dp_packet_at(const struct dp_packet *, size_t offset,
size_t size);
@@ -256,6 +257,18 @@ dp_packet_delete(struct dp_packet *b)
}
}
+/* Swaps content of two packets. */
+static inline void
+dp_packet_swap(struct dp_packet *a, struct dp_packet *b)
+{
+ ovs_assert(a->source == DPBUF_MALLOC || a->source == DPBUF_STUB);
+ ovs_assert(b->source == DPBUF_MALLOC || b->source == DPBUF_STUB);
+ struct dp_packet c = *a;
+
+ *a = *b;
+ *b = c;
+}
+
/* If 'b' contains at least 'offset + size' bytes of data, returns a pointer to
* byte 'offset'. Otherwise, returns a null pointer. */
static inline void *
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index bddce75b63..f9782b596f 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -4061,7 +4061,10 @@ dpif_netdev_execute(struct dpif *dpif, struct dpif_execute *execute)
flow_hash_5tuple(execute->flow, 0));
}
- dp_packet_batch_init_packet(&pp, execute->packet);
+ /* Making a copy because the packet might be stolen during the execution
+ * and caller might still need it. */
+ struct dp_packet *packet_clone = dp_packet_clone(execute->packet);
+ dp_packet_batch_init_packet(&pp, packet_clone);
dp_netdev_execute_actions(pmd, &pp, false, execute->flow,
execute->actions, execute->actions_len);
dp_netdev_pmd_flush_output_packets(pmd, true);
@@ -4071,6 +4074,14 @@ dpif_netdev_execute(struct dpif *dpif, struct dpif_execute *execute)
dp_netdev_pmd_unref(pmd);
}
+ if (dp_packet_batch_size(&pp)) {
+ /* Packet wasn't dropped during the execution. Swapping content with
+ * the original packet, because the caller might expect actions to
+ * modify it. */
+ dp_packet_swap(execute->packet, packet_clone);
+ dp_packet_delete_batch(&pp, true);
+ }
+
return 0;
}
diff --git a/lib/ipf.c b/lib/ipf.c
index d9f781147a..665f40fefe 100644
--- a/lib/ipf.c
+++ b/lib/ipf.c
@@ -1152,52 +1152,56 @@ ipf_post_execute_reass_pkts(struct ipf *ipf,
* NETDEV_MAX_BURST. */
DP_PACKET_BATCH_REFILL_FOR_EACH (pb_idx, pb_cnt, pkt, pb) {
if (rp && pkt == rp->list->reass_execute_ctx) {
+ const struct ipf_frag *frag_0 = &rp->list->frag_list[0];
+ void *l4_frag = dp_packet_l4(frag_0->pkt);
+ void *l4_reass = dp_packet_l4(pkt);
+ memcpy(l4_frag, l4_reass, dp_packet_l4_size(frag_0->pkt));
+
for (int i = 0; i <= rp->list->last_inuse_idx; i++) {
- rp->list->frag_list[i].pkt->md.ct_label = pkt->md.ct_label;
- rp->list->frag_list[i].pkt->md.ct_mark = pkt->md.ct_mark;
- rp->list->frag_list[i].pkt->md.ct_state = pkt->md.ct_state;
- rp->list->frag_list[i].pkt->md.ct_zone = pkt->md.ct_zone;
- rp->list->frag_list[i].pkt->md.ct_orig_tuple_ipv6 =
+ const struct ipf_frag *frag_i = &rp->list->frag_list[i];
+
+ frag_i->pkt->md.ct_label = pkt->md.ct_label;
+ frag_i->pkt->md.ct_mark = pkt->md.ct_mark;
+ frag_i->pkt->md.ct_state = pkt->md.ct_state;
+ frag_i->pkt->md.ct_zone = pkt->md.ct_zone;
+ frag_i->pkt->md.ct_orig_tuple_ipv6 =
pkt->md.ct_orig_tuple_ipv6;
if (pkt->md.ct_orig_tuple_ipv6) {
- rp->list->frag_list[i].pkt->md.ct_orig_tuple.ipv6 =
+ frag_i->pkt->md.ct_orig_tuple.ipv6 =
pkt->md.ct_orig_tuple.ipv6;
} else {
- rp->list->frag_list[i].pkt->md.ct_orig_tuple.ipv4 =
+ frag_i->pkt->md.ct_orig_tuple.ipv4 =
pkt->md.ct_orig_tuple.ipv4;
}
- }
-
- const struct ipf_frag *frag_0 = &rp->list->frag_list[0];
- void *l4_frag = dp_packet_l4(frag_0->pkt);
- void *l4_reass = dp_packet_l4(pkt);
- memcpy(l4_frag, l4_reass, dp_packet_l4_size(frag_0->pkt));
-
- if (v6) {
- struct ovs_16aligned_ip6_hdr *l3_frag
- = dp_packet_l3(frag_0->pkt);
- struct ovs_16aligned_ip6_hdr *l3_reass = dp_packet_l3(pkt);
- l3_frag->ip6_src = l3_reass->ip6_src;
- l3_frag->ip6_dst = l3_reass->ip6_dst;
- } else {
- struct ip_header *l3_frag = dp_packet_l3(frag_0->pkt);
- struct ip_header *l3_reass = dp_packet_l3(pkt);
- if (!dp_packet_hwol_is_ipv4(frag_0->pkt)) {
- ovs_be32 reass_ip =
- get_16aligned_be32(&l3_reass->ip_src);
- ovs_be32 frag_ip =
- get_16aligned_be32(&l3_frag->ip_src);
-
- l3_frag->ip_csum = recalc_csum32(l3_frag->ip_csum,
- frag_ip, reass_ip);
- reass_ip = get_16aligned_be32(&l3_reass->ip_dst);
- frag_ip = get_16aligned_be32(&l3_frag->ip_dst);
- l3_frag->ip_csum = recalc_csum32(l3_frag->ip_csum,
- frag_ip, reass_ip);
+ if (v6) {
+ struct ovs_16aligned_ip6_hdr *l3_frag
+ = dp_packet_l3(frag_i->pkt);
+ struct ovs_16aligned_ip6_hdr *l3_reass
+ = dp_packet_l3(pkt);
+ l3_frag->ip6_src = l3_reass->ip6_src;
+ l3_frag->ip6_dst = l3_reass->ip6_dst;
+ } else {
+ struct ip_header *l3_frag = dp_packet_l3(frag_i->pkt);
+ struct ip_header *l3_reass = dp_packet_l3(pkt);
+ if (!dp_packet_hwol_is_ipv4(frag_i->pkt)) {
+ ovs_be32 reass_ip =
+ get_16aligned_be32(&l3_reass->ip_src);
+ ovs_be32 frag_ip =
+ get_16aligned_be32(&l3_frag->ip_src);
+
+ l3_frag->ip_csum = recalc_csum32(l3_frag->ip_csum,
+ frag_ip,
+ reass_ip);
+ reass_ip = get_16aligned_be32(&l3_reass->ip_dst);
+ frag_ip = get_16aligned_be32(&l3_frag->ip_dst);
+ l3_frag->ip_csum = recalc_csum32(l3_frag->ip_csum,
+ frag_ip,
+ reass_ip);
+ }
+
+ l3_frag->ip_src = l3_reass->ip_src;
+ l3_frag->ip_dst = l3_reass->ip_dst;
}
-
- l3_frag->ip_src = l3_reass->ip_src;
- l3_frag->ip_dst = l3_reass->ip_dst;
}
ipf_completed_list_add(&ipf->frag_complete_list, rp->list);
diff --git a/lib/json.c b/lib/json.c
index 32d25003b8..0baf7c622c 100644
--- a/lib/json.c
+++ b/lib/json.c
@@ -146,6 +146,7 @@ json_type_to_string(enum json_type type)
case JSON_STRING:
return "string";
+ case JSON_SERIALIZED_OBJECT:
case JSON_N_TYPES:
default:
return "<invalid>";
@@ -180,6 +181,14 @@ json_string_create(const char *s)
return json_string_create_nocopy(xstrdup(s));
}
+struct json *
+json_serialized_object_create(const struct json *src)
+{
+ struct json *json = json_create(JSON_SERIALIZED_OBJECT);
+ json->string = json_to_string(src, JSSF_SORT);
+ return json;
+}
+
struct json *
json_array_create_empty(void)
{
@@ -309,6 +318,13 @@ json_string(const struct json *json)
return json->string;
}
+const char *
+json_serialized_object(const struct json *json)
+{
+ ovs_assert(json->type == JSON_SERIALIZED_OBJECT);
+ return json->string;
+}
+
struct json_array *
json_array(const struct json *json)
{
@@ -362,6 +378,7 @@ json_destroy(struct json *json)
break;
case JSON_STRING:
+ case JSON_SERIALIZED_OBJECT:
free(json->string);
break;
@@ -422,6 +439,9 @@ json_deep_clone(const struct json *json)
case JSON_STRING:
return json_string_create(json->string);
+ case JSON_SERIALIZED_OBJECT:
+ return json_serialized_object_create(json);
+
case JSON_NULL:
case JSON_FALSE:
case JSON_TRUE:
@@ -521,6 +541,7 @@ json_hash(const struct json *json, size_t basis)
return json_hash_array(&json->array, basis);
case JSON_STRING:
+ case JSON_SERIALIZED_OBJECT:
return hash_string(json->string, basis);
case JSON_NULL:
@@ -596,6 +617,7 @@ json_equal(const struct json *a, const struct json *b)
return json_equal_array(&a->array, &b->array);
case JSON_STRING:
+ case JSON_SERIALIZED_OBJECT:
return !strcmp(a->string, b->string);
case JSON_NULL:
@@ -1072,6 +1094,14 @@ json_from_string(const char *string)
return json_parser_finish(p);
}
+/* Parses data of JSON_SERIALIZED_OBJECT to the real JSON. */
+struct json *
+json_from_serialized_object(const struct json *json)
+{
+ ovs_assert(json->type == JSON_SERIALIZED_OBJECT);
+ return json_from_string(json->string);
+}
+
/* Reads the file named 'file_name', parses its contents as a JSON object or
* array, and returns a newly allocated 'struct json'. The caller must free
* the returned structure with json_destroy() when it is no longer needed.
@@ -1563,6 +1593,10 @@ json_serialize(const struct json *json, struct json_serializer *s)
json_serialize_string(json->string, ds);
break;
+ case JSON_SERIALIZED_OBJECT:
+ ds_put_cstr(ds, json->string);
+ break;
+
case JSON_N_TYPES:
default:
OVS_NOT_REACHED();
@@ -1696,14 +1730,30 @@ json_serialize_string(const char *string, struct ds *ds)
{
uint8_t c;
uint8_t c2;
+ size_t count;
const char *escape;
+ const char *start;
ds_put_char(ds, '"');
+ count = 0;
+ start = string;
while ((c = *string++) != '\0') {
- escape = chars_escaping[c];
- while ((c2 = *escape++) != '\0') {
- ds_put_char(ds, c2);
+ if (c >= ' ' && c != '"' && c != '\\') {
+ count++;
+ } else {
+ if (count) {
+ ds_put_buffer(ds, start, count);
+ count = 0;
+ }
+ start = string;
+ escape = chars_escaping[c];
+ while ((c2 = *escape++) != '\0') {
+ ds_put_char(ds, c2);
+ }
}
}
+ if (count) {
+ ds_put_buffer(ds, start, count);
+ }
ds_put_char(ds, '"');
}
diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c
index 45a96b9be2..ca92c947a2 100644
--- a/lib/netdev-dpdk.c
+++ b/lib/netdev-dpdk.c
@@ -961,14 +961,6 @@ dpdk_eth_dev_port_config(struct netdev_dpdk *dev, int n_rxq, int n_txq)
rte_eth_dev_info_get(dev->port_id, &info);
- /* As of DPDK 19.11, it is not allowed to set a mq_mode for
- * virtio PMD driver. */
- if (!strcmp(info.driver_name, "net_virtio")) {
- conf.rxmode.mq_mode = ETH_MQ_RX_NONE;
- } else {
- conf.rxmode.mq_mode = ETH_MQ_RX_RSS;
- }
-
/* As of DPDK 17.11.1 a few PMDs require to explicitly enable
* scatter to support jumbo RX.
* Setting scatter for the device is done after checking for
@@ -1000,6 +992,11 @@ dpdk_eth_dev_port_config(struct netdev_dpdk *dev, int n_rxq, int n_txq)
/* Limit configured rss hash functions to only those supported
* by the eth device. */
conf.rx_adv_conf.rss_conf.rss_hf &= info.flow_type_rss_offloads;
+ if (conf.rx_adv_conf.rss_conf.rss_hf == 0) {
+ conf.rxmode.mq_mode = ETH_MQ_RX_NONE;
+ } else {
+ conf.rxmode.mq_mode = ETH_MQ_RX_RSS;
+ }
/* A device may report more queues than it makes available (this has
* been observed for Intel xl710, which reserves some of them for
diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c
index 60dd138914..97bd21be4a 100644
--- a/lib/netdev-linux.c
+++ b/lib/netdev-linux.c
@@ -627,6 +627,7 @@ netdev_linux_notify_sock(void)
if (!error) {
size_t i;
+ nl_sock_listen_all_nsid(sock, true);
for (i = 0; i < ARRAY_SIZE(mcgroups); i++) {
error = nl_sock_join_mcgroup(sock, mcgroups[i]);
if (error) {
@@ -636,7 +637,6 @@ netdev_linux_notify_sock(void)
}
}
}
- nl_sock_listen_all_nsid(sock, true);
ovsthread_once_done(&once);
}
diff --git a/lib/odp-util.c b/lib/odp-util.c
index 7729a90608..fbdfc7ad83 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -2941,7 +2941,7 @@ odp_nsh_key_from_attr__(const struct nlattr *attr, bool is_mask,
const struct ovs_nsh_key_md1 *md1 = nl_attr_get(a);
has_md1 = true;
memcpy(nsh->context, md1->context, sizeof md1->context);
- if (len == 2 * sizeof(*md1)) {
+ if (nsh_mask && (len == 2 * sizeof *md1)) {
const struct ovs_nsh_key_md1 *md1_mask = md1 + 1;
memcpy(nsh_mask->context, md1_mask->context,
sizeof(*md1_mask));
@@ -4618,7 +4618,7 @@ odp_flow_format(const struct nlattr *key, size_t key_len,
}
ds_put_char(ds, ')');
}
- if (!has_ethtype_key) {
+ if (!has_ethtype_key && mask) {
const struct nlattr *ma = nl_attr_find__(mask, mask_len,
OVS_KEY_ATTR_ETHERTYPE);
if (ma) {
diff --git a/lib/pcap-file.c b/lib/pcap-file.c
index b30a11c24b..41835f6f4d 100644
--- a/lib/pcap-file.c
+++ b/lib/pcap-file.c
@@ -89,6 +89,7 @@ ovs_pcap_open(const char *file_name, const char *mode)
: mode[0] == 'w' ? "writing"
: "appending"),
ovs_strerror(errno));
+ free(p_file);
return NULL;
}
diff --git a/ovsdb/monitor.c b/ovsdb/monitor.c
index 532dedcb64..ab814cf20e 100644
--- a/ovsdb/monitor.c
+++ b/ovsdb/monitor.c
@@ -1231,6 +1231,15 @@ ovsdb_monitor_get_update(
condition,
ovsdb_monitor_compose_row_update2);
if (!condition || !condition->conditional) {
+ if (json) {
+ struct json *json_serialized;
+
+ /* Pre-serializing the object to avoid doing this
+ * for every client. */
+ json_serialized = json_serialized_object_create(json);
+ json_destroy(json);
+ json = json_serialized;
+ }
ovsdb_monitor_json_cache_insert(dbmon, version, mcs,
json);
}
diff --git a/ovsdb/ovsdb-tool.c b/ovsdb/ovsdb-tool.c
index 05a0223e71..d4a9e34cc4 100644
--- a/ovsdb/ovsdb-tool.c
+++ b/ovsdb/ovsdb-tool.c
@@ -919,7 +919,8 @@ print_raft_header(const struct raft_header *h,
if (!uuid_is_zero(&h->snap.eid)) {
printf(" prev_eid: %04x\n", uuid_prefix(&h->snap.eid, 4));
}
- print_data("prev_", h->snap.data, schemap, names);
+ print_data("prev_", raft_entry_get_parsed_data(&h->snap),
+ schemap, names);
}
}
@@ -973,11 +974,13 @@ raft_header_to_standalone_log(const struct raft_header *h,
struct ovsdb_log *db_log_data)
{
if (h->snap_index) {
- if (!h->snap.data || json_array(h->snap.data)->n != 2) {
+ const struct json *data = raft_entry_get_parsed_data(&h->snap);
+
+ if (!data || json_array(data)->n != 2) {
ovs_fatal(0, "Incorrect raft header data array length");
}
- struct json_array *pa = json_array(h->snap.data);
+ struct json_array *pa = json_array(data);
struct json *schema_json = pa->elems[0];
struct ovsdb_error *error = NULL;
@@ -1373,7 +1376,7 @@ do_check_cluster(struct ovs_cmdl_context *ctx)
}
struct raft_entry *e = &s->entries[log_idx];
e->term = r->term;
- e->data = r->entry.data;
+ raft_entry_set_parsed_data_nocopy(e, r->entry.data);
e->eid = r->entry.eid;
e->servers = r->entry.servers;
break;
diff --git a/ovsdb/raft-private.c b/ovsdb/raft-private.c
index 26d39a087f..30760233ee 100644
--- a/ovsdb/raft-private.c
+++ b/ovsdb/raft-private.c
@@ -18,11 +18,14 @@
#include "raft-private.h"
+#include "coverage.h"
#include "openvswitch/dynamic-string.h"
#include "ovsdb-error.h"
#include "ovsdb-parser.h"
#include "socket-util.h"
#include "sset.h"
+
+COVERAGE_DEFINE(raft_entry_serialize);
/* Addresses of Raft servers. */
@@ -281,7 +284,8 @@ void
raft_entry_clone(struct raft_entry *dst, const struct raft_entry *src)
{
dst->term = src->term;
- dst->data = json_nullable_clone(src->data);
+ dst->data.full_json = json_nullable_clone(src->data.full_json);
+ dst->data.serialized = json_nullable_clone(src->data.serialized);
dst->eid = src->eid;
dst->servers = json_nullable_clone(src->servers);
dst->election_timer = src->election_timer;
@@ -291,7 +295,8 @@ void
raft_entry_uninit(struct raft_entry *e)
{
if (e) {
- json_destroy(e->data);
+ json_destroy(e->data.full_json);
+ json_destroy(e->data.serialized);
json_destroy(e->servers);
}
}
@@ -301,8 +306,9 @@ raft_entry_to_json(const struct raft_entry *e)
{
struct json *json = json_object_create();
raft_put_uint64(json, "term", e->term);
- if (e->data) {
- json_object_put(json, "data", json_clone(e->data));
+ if (raft_entry_has_data(e)) {
+ json_object_put(json, "data",
+ json_clone(raft_entry_get_serialized_data(e)));
json_object_put_format(json, "eid", UUID_FMT, UUID_ARGS(&e->eid));
}
if (e->servers) {
@@ -323,9 +329,10 @@ raft_entry_from_json(struct json *json, struct raft_entry *e)
struct ovsdb_parser p;
ovsdb_parser_init(&p, json, "raft log entry");
e->term = raft_parse_required_uint64(&p, "term");
- e->data = json_nullable_clone(
+ raft_entry_set_parsed_data(e,
ovsdb_parser_member(&p, "data", OP_OBJECT | OP_ARRAY | OP_OPTIONAL));
- e->eid = e->data ? raft_parse_required_uuid(&p, "eid") : UUID_ZERO;
+ e->eid = raft_entry_has_data(e)
+ ? raft_parse_required_uuid(&p, "eid") : UUID_ZERO;
e->servers = json_nullable_clone(
ovsdb_parser_member(&p, "servers", OP_OBJECT | OP_OPTIONAL));
if (e->servers) {
@@ -344,9 +351,72 @@ bool
raft_entry_equals(const struct raft_entry *a, const struct raft_entry *b)
{
return (a->term == b->term
- && json_equal(a->data, b->data)
&& uuid_equals(&a->eid, &b->eid)
- && json_equal(a->servers, b->servers));
+ && json_equal(a->servers, b->servers)
+ && json_equal(raft_entry_get_parsed_data(a),
+ raft_entry_get_parsed_data(b)));
+}
+
+bool
+raft_entry_has_data(const struct raft_entry *e)
+{
+ return e->data.full_json || e->data.serialized;
+}
+
+static void
+raft_entry_data_serialize(struct raft_entry *e)
+{
+ if (!raft_entry_has_data(e) || e->data.serialized) {
+ return;
+ }
+ COVERAGE_INC(raft_entry_serialize);
+ e->data.serialized = json_serialized_object_create(e->data.full_json);
+}
+
+void
+raft_entry_set_parsed_data_nocopy(struct raft_entry *e, struct json *json)
+{
+ ovs_assert(!json || json->type != JSON_SERIALIZED_OBJECT);
+ e->data.full_json = json;
+ e->data.serialized = NULL;
+}
+
+void
+raft_entry_set_parsed_data(struct raft_entry *e, const struct json *json)
+{
+ raft_entry_set_parsed_data_nocopy(e, json_nullable_clone(json));
+}
+
+/* Returns a pointer to the fully parsed json object of the data.
+ * Caller takes the ownership of the result.
+ *
+ * Entry will no longer contain a fully parsed json object.
+ * Subsequent calls for the same raft entry will return NULL. */
+struct json * OVS_WARN_UNUSED_RESULT
+raft_entry_steal_parsed_data(struct raft_entry *e)
+{
+ /* Ensure that serialized version exists. */
+ raft_entry_data_serialize(e);
+
+ struct json *json = e->data.full_json;
+ e->data.full_json = NULL;
+
+ return json;
+}
+
+/* Returns a pointer to the fully parsed json object of the data, if any. */
+const struct json *
+raft_entry_get_parsed_data(const struct raft_entry *e)
+{
+ return e->data.full_json;
+}
+
+/* Returns a pointer to the JSON_SERIALIZED_OBJECT of the data. */
+const struct json *
+raft_entry_get_serialized_data(const struct raft_entry *e)
+{
+ raft_entry_data_serialize(CONST_CAST(struct raft_entry *, e));
+ return e->data.serialized;
}
void
@@ -402,8 +472,8 @@ raft_header_from_json__(struct raft_header *h, struct ovsdb_parser *p)
* present, all of them must be. */
h->snap_index = raft_parse_optional_uint64(p, "prev_index");
if (h->snap_index) {
- h->snap.data = json_nullable_clone(
- ovsdb_parser_member(p, "prev_data", OP_ANY));
+ raft_entry_set_parsed_data(
+ &h->snap, ovsdb_parser_member(p, "prev_data", OP_ANY));
h->snap.eid = raft_parse_required_uuid(p, "prev_eid");
h->snap.term = raft_parse_required_uint64(p, "prev_term");
h->snap.election_timer = raft_parse_optional_uint64(
@@ -455,8 +525,9 @@ raft_header_to_json(const struct raft_header *h)
if (h->snap_index) {
raft_put_uint64(json, "prev_index", h->snap_index);
raft_put_uint64(json, "prev_term", h->snap.term);
- if (h->snap.data) {
- json_object_put(json, "prev_data", json_clone(h->snap.data));
+ if (raft_entry_has_data(&h->snap)) {
+ json_object_put(json, "prev_data",
+ json_clone(raft_entry_get_serialized_data(&h->snap)));
}
json_object_put_format(json, "prev_eid",
UUID_FMT, UUID_ARGS(&h->snap.eid));
diff --git a/ovsdb/raft-private.h b/ovsdb/raft-private.h
index a69e37e5c2..48c6df511f 100644
--- a/ovsdb/raft-private.h
+++ b/ovsdb/raft-private.h
@@ -118,7 +118,10 @@ void raft_servers_format(const struct hmap *servers, struct ds *ds);
* entry. */
struct raft_entry {
uint64_t term;
- struct json *data;
+ struct {
+ struct json *full_json; /* Fully parsed JSON object. */
+ struct json *serialized; /* JSON_SERIALIZED_OBJECT version of data. */
+ } data;
struct uuid eid;
struct json *servers;
uint64_t election_timer;
@@ -130,6 +133,13 @@ struct json *raft_entry_to_json(const struct raft_entry *);
struct ovsdb_error *raft_entry_from_json(struct json *, struct raft_entry *)
OVS_WARN_UNUSED_RESULT;
bool raft_entry_equals(const struct raft_entry *, const struct raft_entry *);
+bool raft_entry_has_data(const struct raft_entry *);
+void raft_entry_set_parsed_data(struct raft_entry *, const struct json *);
+void raft_entry_set_parsed_data_nocopy(struct raft_entry *, struct json *);
+struct json *raft_entry_steal_parsed_data(struct raft_entry *)
+ OVS_WARN_UNUSED_RESULT;
+const struct json *raft_entry_get_parsed_data(const struct raft_entry *);
+const struct json *raft_entry_get_serialized_data(const struct raft_entry *);
/* On disk data serialization and deserialization. */
diff --git a/ovsdb/raft.c b/ovsdb/raft.c
index 2fb5156519..ce40c5bc07 100644
--- a/ovsdb/raft.c
+++ b/ovsdb/raft.c
@@ -494,11 +494,11 @@ raft_create_cluster(const char *file_name, const char *name,
.snap_index = index++,
.snap = {
.term = term,
- .data = json_nullable_clone(data),
.eid = uuid_random(),
.servers = json_object_create(),
},
};
+ raft_entry_set_parsed_data(&h.snap, data);
shash_add_nocopy(json_object(h.snap.servers),
xasprintf(UUID_FMT, UUID_ARGS(&h.sid)),
json_string_create(local_address));
@@ -727,10 +727,10 @@ raft_add_entry(struct raft *raft,
uint64_t index = raft->log_end++;
struct raft_entry *entry = &raft->entries[index - raft->log_start];
entry->term = term;
- entry->data = data;
entry->eid = eid ? *eid : UUID_ZERO;
entry->servers = servers;
entry->election_timer = election_timer;
+ raft_entry_set_parsed_data_nocopy(entry, data);
return index;
}
@@ -741,13 +741,16 @@ raft_write_entry(struct raft *raft, uint64_t term, struct json *data,
const struct uuid *eid, struct json *servers,
uint64_t election_timer)
{
+ uint64_t index = raft_add_entry(raft, term, data, eid, servers,
+ election_timer);
+ const struct json *entry_data = raft_entry_get_serialized_data(
+ &raft->entries[index - raft->log_start]);
struct raft_record r = {
.type = RAFT_REC_ENTRY,
.term = term,
.entry = {
- .index = raft_add_entry(raft, term, data, eid, servers,
- election_timer),
- .data = data,
+ .index = index,
+ .data = CONST_CAST(struct json *, entry_data),
.servers = servers,
.election_timer = election_timer,
.eid = eid ? *eid : UUID_ZERO,
@@ -2161,7 +2164,7 @@ raft_get_eid(const struct raft *raft, uint64_t index)
{
for (; index >= raft->log_start; index--) {
const struct raft_entry *e = raft_get_entry(raft, index);
- if (e->data) {
+ if (raft_entry_has_data(e)) {
return &e->eid;
}
}
@@ -2826,8 +2829,8 @@ raft_truncate(struct raft *raft, uint64_t new_end)
return servers_changed;
}
-static const struct json *
-raft_peek_next_entry(struct raft *raft, struct uuid *eid)
+static const struct raft_entry *
+raft_peek_next_entry(struct raft *raft)
{
/* Invariant: log_start - 2 <= last_applied <= commit_index < log_end. */
ovs_assert(raft->log_start <= raft->last_applied + 2);
@@ -2839,32 +2842,20 @@ raft_peek_next_entry(struct raft *raft, struct uuid *eid)
}
if (raft->log_start == raft->last_applied + 2) {
- *eid = raft->snap.eid;
- return raft->snap.data;
+ return &raft->snap;
}
while (raft->last_applied < raft->commit_index) {
const struct raft_entry *e = raft_get_entry(raft,
raft->last_applied + 1);
- if (e->data) {
- *eid = e->eid;
- return e->data;
+ if (raft_entry_has_data(e)) {
+ return e;
}
raft->last_applied++;
}
return NULL;
}
-static const struct json *
-raft_get_next_entry(struct raft *raft, struct uuid *eid)
-{
- const struct json *data = raft_peek_next_entry(raft, eid);
- if (data) {
- raft->last_applied++;
- }
- return data;
-}
-
/* Updates commit index in raft log. If commit index is already up-to-date
* it does nothing and return false, otherwise, returns true. */
static bool
@@ -2878,7 +2869,7 @@ raft_update_commit_index(struct raft *raft, uint64_t new_commit_index)
while (raft->commit_index < new_commit_index) {
uint64_t index = ++raft->commit_index;
const struct raft_entry *e = raft_get_entry(raft, index);
- if (e->data) {
+ if (raft_entry_has_data(e)) {
struct raft_command *cmd
= raft_find_command_by_eid(raft, &e->eid);
if (cmd) {
@@ -3059,7 +3050,9 @@ raft_handle_append_entries(struct raft *raft,
for (; i < n_entries; i++) {
const struct raft_entry *e = &entries[i];
error = raft_write_entry(raft, e->term,
- json_nullable_clone(e->data), &e->eid,
+ json_nullable_clone(
+ raft_entry_get_parsed_data(e)),
+ &e->eid,
json_nullable_clone(e->servers),
e->election_timer);
if (error) {
@@ -3314,20 +3307,29 @@ bool
raft_has_next_entry(const struct raft *raft_)
{
struct raft *raft = CONST_CAST(struct raft *, raft_);
- struct uuid eid;
- return raft_peek_next_entry(raft, &eid) != NULL;
+ return raft_peek_next_entry(raft) != NULL;
}
/* Returns the next log entry or snapshot from 'raft', or NULL if there are
- * none left to read. Stores the entry ID of the log entry in '*eid'. Stores
- * true in '*is_snapshot' if the returned data is a snapshot, false if it is a
- * log entry. */
-const struct json *
-raft_next_entry(struct raft *raft, struct uuid *eid, bool *is_snapshot)
+ * none left to read. Stores the entry ID of the log entry in '*eid'.
+ *
+ * The caller takes ownership of the result. */
+struct json * OVS_WARN_UNUSED_RESULT
+raft_next_entry(struct raft *raft, struct uuid *eid)
{
- const struct json *data = raft_get_next_entry(raft, eid);
- *is_snapshot = data == raft->snap.data;
- return data;
+ const struct raft_entry *e = raft_peek_next_entry(raft);
+
+ if (!e) {
+ return NULL;
+ }
+
+ raft->last_applied++;
+ *eid = e->eid;
+
+ /* DB will only read each entry once, so we don't need to store the fully
+ * parsed json object any longer. The serialized version is sufficient
+ * for sending to other cluster members or writing to the log. */
+ return raft_entry_steal_parsed_data(CONST_CAST(struct raft_entry *, e));
}
/* Returns the log index of the last-read snapshot or log entry. */
@@ -3420,6 +3422,7 @@ raft_send_install_snapshot_request(struct raft *raft,
const struct raft_server *s,
const char *comment)
{
+ const struct json *data = raft_entry_get_serialized_data(&raft->snap);
union raft_rpc rpc = {
.install_snapshot_request = {
.common = {
@@ -3432,7 +3435,7 @@ raft_send_install_snapshot_request(struct raft *raft,
.last_term = raft->snap.term,
.last_servers = raft->snap.servers,
.last_eid = raft->snap.eid,
- .data = raft->snap.data,
+ .data = CONST_CAST(struct json *, data),
.election_timer = raft->election_timer, /* use latest value */
}
};
@@ -3980,6 +3983,10 @@ raft_write_snapshot(struct raft *raft, struct ovsdb_log *log,
uint64_t new_log_start,
const struct raft_entry *new_snapshot)
{
+ /* Ensure that new snapshot contains serialized data object, so it will
+ * not be allocated while serializing the on-stack raft header object. */
+ ovs_assert(raft_entry_get_serialized_data(new_snapshot));
+
struct raft_header h = {
.sid = raft->sid,
.cid = raft->cid,
@@ -3998,12 +4005,13 @@ raft_write_snapshot(struct raft *raft, struct ovsdb_log *log,
/* Write log records. */
for (uint64_t index = new_log_start; index < raft->log_end; index++) {
const struct raft_entry *e = &raft->entries[index - raft->log_start];
+ const struct json *log_data = raft_entry_get_serialized_data(e);
struct raft_record r = {
.type = RAFT_REC_ENTRY,
.term = e->term,
.entry = {
.index = index,
- .data = e->data,
+ .data = CONST_CAST(struct json *, log_data),
.servers = e->servers,
.election_timer = e->election_timer,
.eid = e->eid,
@@ -4093,19 +4101,21 @@ raft_handle_install_snapshot_request__(
/* Case 3: The new snapshot starts past the end of our current log, so
* discard all of our current log. */
- const struct raft_entry new_snapshot = {
+ struct raft_entry new_snapshot = {
.term = rq->last_term,
- .data = rq->data,
.eid = rq->last_eid,
- .servers = rq->last_servers,
+ .servers = json_clone(rq->last_servers),
.election_timer = rq->election_timer,
};
+ raft_entry_set_parsed_data(&new_snapshot, rq->data);
+
struct ovsdb_error *error = raft_save_snapshot(raft, new_log_start,
&new_snapshot);
if (error) {
char *error_s = ovsdb_error_to_string_free(error);
VLOG_WARN("could not save snapshot: %s", error_s);
free(error_s);
+ raft_entry_uninit(&new_snapshot);
return false;
}
@@ -4120,7 +4130,7 @@ raft_handle_install_snapshot_request__(
}
raft_entry_uninit(&raft->snap);
- raft_entry_clone(&raft->snap, &new_snapshot);
+ raft->snap = new_snapshot;
raft_get_servers_from_log(raft, VLL_INFO);
raft_get_election_timer_from_log(raft);
@@ -4265,11 +4275,12 @@ raft_store_snapshot(struct raft *raft, const struct json *new_snapshot_data)
uint64_t new_log_start = raft->last_applied + 1;
struct raft_entry new_snapshot = {
.term = raft_get_term(raft, new_log_start - 1),
- .data = json_clone(new_snapshot_data),
.eid = *raft_get_eid(raft, new_log_start - 1),
.servers = json_clone(raft_servers_for_index(raft, new_log_start - 1)),
.election_timer = raft->election_timer,
};
+ raft_entry_set_parsed_data(&new_snapshot, new_snapshot_data);
+
struct ovsdb_error *error = raft_save_snapshot(raft, new_log_start,
&new_snapshot);
if (error) {
@@ -4286,6 +4297,9 @@ raft_store_snapshot(struct raft *raft, const struct json *new_snapshot_data)
memmove(&raft->entries[0], &raft->entries[new_log_start - raft->log_start],
(raft->log_end - new_log_start) * sizeof *raft->entries);
raft->log_start = new_log_start;
+ /* It's a snapshot of the current database state, ovsdb-server will not
+ * read it back. Destroying the parsed json object to not waste memory. */
+ json_destroy(raft_entry_steal_parsed_data(&raft->snap));
return NULL;
}
diff --git a/ovsdb/raft.h b/ovsdb/raft.h
index 3545c41c2c..599bc0ae86 100644
--- a/ovsdb/raft.h
+++ b/ovsdb/raft.h
@@ -132,8 +132,8 @@ bool raft_left(const struct raft *);
bool raft_failed(const struct raft *);
/* Reading snapshots and log entries. */
-const struct json *raft_next_entry(struct raft *, struct uuid *eid,
- bool *is_snapshot);
+struct json *raft_next_entry(struct raft *, struct uuid *eid)
+ OVS_WARN_UNUSED_RESULT;
bool raft_has_next_entry(const struct raft *);
uint64_t raft_get_applied_index(const struct raft *);
diff --git a/ovsdb/storage.c b/ovsdb/storage.c
index d727b1eacd..9e32efe582 100644
--- a/ovsdb/storage.c
+++ b/ovsdb/storage.c
@@ -268,9 +268,7 @@ ovsdb_storage_read(struct ovsdb_storage *storage,
struct json *schema_json = NULL;
struct json *txn_json = NULL;
if (storage->raft) {
- bool is_snapshot;
- json = json_nullable_clone(
- raft_next_entry(storage->raft, txnid, &is_snapshot));
+ json = raft_next_entry(storage->raft, txnid);
if (!json) {
return NULL;
} else if (json->type != JSON_ARRAY || json->array.n != 2) {
diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
index 956a69e1fa..1dad6f62c6 100644
--- a/tests/ofproto-dpif.at
+++ b/tests/ofproto-dpif.at
@@ -9695,6 +9695,26 @@ OFPST_TABLE reply (OF1.3) (xid=0x2):
OVS_VSWITCHD_STOP
AT_CLEANUP
+AT_SETUP([ofproto-dpif packet-out table meter drop])
+OVS_VSWITCHD_START
+add_of_ports br0 1 2
+
+AT_CHECK([ovs-ofctl -O OpenFlow13 add-meter br0 'meter=1 pktps bands=type=drop rate=1'])
+AT_CHECK([ovs-ofctl -O OpenFlow13 add-flow br0 'in_port=1 action=meter:1,output:2'])
+
+ovs-ofctl -O OpenFlow13 packet-out br0 "in_port=1 packet=50540000000a50540000000908004500001c000000000011a4cd0a0101010a0101020001000400080000 actions=resubmit(,0)"
+ovs-ofctl -O OpenFlow13 packet-out br0 "in_port=1 packet=50540000000a50540000000908004500001c000000000011a4cd0a0101010a0101020001000400080000 actions=resubmit(,0)"
+
+# Check that vswitchd hasn't crashed by dumping the meter added above
+AT_CHECK([ovs-ofctl -O OpenFlow13 dump-meters br0 | ofctl_strip], [0], [dnl
+OFPST_METER_CONFIG reply (OF1.3):
+meter=1 pktps bands=
+type=drop rate=1
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
AT_SETUP([ofproto-dpif - ICMPv6])
OVS_VSWITCHD_START
add_of_ports br0 1
diff --git a/tests/system-traffic.at b/tests/system-traffic.at
index f400cfabc9..c4442c183f 100644
--- a/tests/system-traffic.at
+++ b/tests/system-traffic.at
@@ -3305,6 +3305,46 @@ NS_CHECK_EXEC([at_ns0], [ping6 -s 3200 -q -c 3 -i 0.3 -w 2 fc00::2 | FORMAT_PING
OVS_TRAFFIC_VSWITCHD_STOP
AT_CLEANUP
+AT_SETUP([conntrack - IPv4 Fragmentation + NAT])
+AT_SKIP_IF([test $HAVE_TCPDUMP = no])
+CHECK_CONNTRACK()
+
+OVS_TRAFFIC_VSWITCHD_START(
+ [set-fail-mode br0 secure -- ])
+
+ADD_NAMESPACES(at_ns0, at_ns1)
+
+ADD_VETH(p0, at_ns0, br0, "10.2.1.1/24")
+ADD_VETH(p1, at_ns1, br0, "10.2.1.2/24")
+
+dnl Create a dummy route for NAT
+NS_CHECK_EXEC([at_ns1], [ip addr add 10.1.1.2/32 dev lo])
+NS_CHECK_EXEC([at_ns0], [ip route add 10.1.1.0/24 via 10.2.1.2])
+NS_CHECK_EXEC([at_ns1], [ip route add 10.1.1.0/24 via 10.2.1.1])
+
+dnl Solely for debugging when things go wrong
+NS_EXEC([at_ns0], [tcpdump -l -n -xx -U -i p0 -w p0.pcap >tcpdump.out 2>/dev/null &])
+NS_EXEC([at_ns1], [tcpdump -l -n -xx -U -i p1 -w p1.pcap >tcpdump.out 2>/dev/null &])
+
+AT_DATA([flows.txt], [dnl
+table=0,arp,actions=normal
+table=0,ct_state=-trk,ip,in_port=ovs-p0, actions=ct(table=1, nat)
+table=0,ct_state=-trk,ip,in_port=ovs-p1, actions=ct(table=1, nat)
+table=1,ct_state=+trk+new,ip,in_port=ovs-p0, actions=ct(commit, nat(src=10.1.1.1)),ovs-p1
+table=1,ct_state=+trk+est,ip,in_port=ovs-p0, actions=ovs-p1
+table=1,ct_state=+trk+est,ip,in_port=ovs-p1, actions=ovs-p0
+])
+
+AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
+
+dnl Check connectivity
+NS_CHECK_EXEC([at_ns0], [ping -c 1 10.1.1.2 -M dont -s 4500 | FORMAT_PING], [0], [dnl
+1 packets transmitted, 1 received, 0% packet loss, time 0ms
+])
+
+OVS_TRAFFIC_VSWITCHD_STOP
+AT_CLEANUP
+
AT_SETUP([conntrack - resubmit to ct multiple times])
CHECK_CONNTRACK()
diff --git a/tests/test-json.c b/tests/test-json.c
index a7ee595e0b..072a537252 100644
--- a/tests/test-json.c
+++ b/tests/test-json.c
@@ -22,6 +22,8 @@
#include <getopt.h>
#include <stdio.h>
#include "ovstest.h"
+#include "random.h"
+#include "timeval.h"
#include "util.h"
/* --pretty: If set, the JSON output is pretty-printed, instead of printed as
@@ -157,3 +159,69 @@ test_json_main(int argc, char *argv[])
}
OVSTEST_REGISTER("test-json", test_json_main);
+
+static void
+json_string_benchmark_main(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
+{
+ struct {
+ int n;
+ int quote_probablility;
+ int special_probability;
+ int iter;
+ } configs[] = {
+ { 100000, 0, 0, 1000, },
+ { 100000, 2, 1, 1000, },
+ { 100000, 10, 1, 1000, },
+ { 10000000, 0, 0, 100, },
+ { 10000000, 2, 1, 100, },
+ { 10000000, 10, 1, 100, },
+ { 100000000, 0, 0, 10. },
+ { 100000000, 2, 1, 10, },
+ { 100000000, 10, 1, 10, },
+ };
+
+ printf(" SIZE Q S TIME\n");
+ printf("--------------------------------------\n");
+
+ for (int i = 0; i < ARRAY_SIZE(configs); i++) {
+ int iter = configs[i].iter;
+ int n = configs[i].n;
+ char *str = xzalloc(n);
+
+ for (int j = 0; j < n - 1; j++) {
+ int r = random_range(100);
+
+ if (r < configs[i].special_probability) {
+ str[j] = random_range(' ' - 1) + 1;
+ } else if (r < (configs[i].special_probability
+ + configs[i].quote_probablility)) {
+ str[j] = '"';
+ } else {
+ str[j] = random_range(256 - ' ') + ' ';
+ }
+ }
+
+ printf("%-11d %-2d %-2d: ", n, configs[i].quote_probablility,
+ configs[i].special_probability);
+ fflush(stdout);
+
+ struct json *json = json_string_create_nocopy(str);
+ uint64_t start = time_msec();
+
+ char **res = xzalloc(iter * sizeof *res);
+ for (int j = 0; j < iter; j++) {
+ res[j] = json_to_string(json, 0);
+ }
+
+ printf("%16.3lf ms\n", (double) (time_msec() - start) / iter);
+ json_destroy(json);
+ for (int j = 0; j < iter; j++) {
+ free(res[j]);
+ }
+ free(res);
+ }
+
+ exit(0);
+}
+
+OVSTEST_REGISTER("json-string-benchmark", json_string_benchmark_main);
diff --git a/tests/tunnel-push-pop.at b/tests/tunnel-push-pop.at
index 48c5de9d19..12fc1ef910 100644
--- a/tests/tunnel-push-pop.at
+++ b/tests/tunnel-push-pop.at
@@ -595,6 +595,62 @@ OVS_WAIT_UNTIL([test `ovs-pcap p0.pcap | grep 50540000000a5054000000091235 | wc
OVS_VSWITCHD_STOP
AT_CLEANUP
+AT_SETUP([tunnel_push_pop - packet_out debug_slow])
+
+OVS_VSWITCHD_START(
+ [add-port br0 p0 dnl
+ -- set Interface p0 type=dummy ofport_request=1 dnl
+ other-config:hwaddr=aa:55:aa:55:00:00])
+AT_CHECK([ovs-appctl vlog/set dpif_netdev:dbg])
+AT_CHECK([ovs-vsctl add-br int-br -- set bridge int-br datapath_type=dummy])
+AT_CHECK([ovs-vsctl add-port int-br t2 dnl
+ -- set Interface t2 type=geneve options:remote_ip=1.1.2.92 dnl
+ options:key=123 ofport_request=2])
+
+dnl First setup dummy interface IP address, then add the route
+dnl so that tnl-port table can get valid IP address for the device.
+AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 1.1.2.88/24], [0], [OK
+])
+AT_CHECK([ovs-appctl ovs/route/add 1.1.2.92/24 br0], [0], [OK
+])
+AT_CHECK([ovs-ofctl add-flow br0 action=normal])
+
+dnl This ARP reply from p0 has two effects:
+dnl 1. The ARP cache will learn that 1.1.2.92 is at f8:bc:12:44:34:b6.
+dnl 2. The br0 mac learning will learn that f8:bc:12:44:34:b6 is on p0.
+AT_CHECK([
+ ovs-appctl netdev-dummy/receive p0 dnl
+ 'recirc_id(0),in_port(2),dnl
+ eth(src=f8:bc:12:44:34:b6,dst=ff:ff:ff:ff:ff:ff),eth_type(0x0806),dnl
+ arp(sip=1.1.2.92,tip=1.1.2.88,op=2,sha=f8:bc:12:44:34:b6,tha=00:00:00:00:00:00)'
+])
+
+AT_CHECK([ovs-vsctl -- set Interface p0 options:tx_pcap=p0.pcap])
+
+packet=50540000000a505400000009123
+encap=f8bc124434b6aa55aa5500000800450000320000400040113406010102580101025c83a917c1001e00000000655800007b00
+
+dnl Output to tunnel from a int-br internal port.
+dnl Checking that the packet arrived and it was correctly encapsulated.
+AT_CHECK([ovs-ofctl add-flow int-br "in_port=LOCAL,actions=debug_slow,output:2"])
+AT_CHECK([ovs-appctl netdev-dummy/receive int-br "${packet}4"])
+OVS_WAIT_UNTIL([test `ovs-pcap p0.pcap | grep "${encap}${packet}4" | wc -l` -ge 1])
+dnl Sending again to exercise the non-miss upcall path.
+AT_CHECK([ovs-appctl netdev-dummy/receive int-br "${packet}4"])
+OVS_WAIT_UNTIL([test `ovs-pcap p0.pcap | grep "${encap}${packet}4" | wc -l` -ge 2])
+
+dnl Output to tunnel from the controller.
+AT_CHECK([ovs-ofctl -O OpenFlow13 packet-out int-br CONTROLLER "debug_slow,output:2" "${packet}5"])
+OVS_WAIT_UNTIL([test `ovs-pcap p0.pcap | grep "${encap}${packet}5" | wc -l` -ge 1])
+
+dnl Datapath actions should not have tunnel push action.
+AT_CHECK([ovs-appctl dpctl/dump-flows | grep -q tnl_push], [1])
+dnl There should be slow_path action instead.
+AT_CHECK([ovs-appctl dpctl/dump-flows | grep -q 'slow_path(action)'], [0])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
AT_SETUP([tunnel_push_pop - underlay bridge match])
OVS_VSWITCHD_START([add-port br0 p0 -- set Interface p0 type=dummy ofport_request=1 other-config:hwaddr=aa:55:aa:55:00:00])
......@@ -11,7 +11,7 @@
# This defines the base package name's version.
%define pkgname openvswitch2.15
%define pkgname openvswitch2.16
%if 0%{?commit:1}
......@@ -56,15 +56,15 @@ Name: %{pkgname}
Summary: Open vSwitch
Group: System Environment/Daemons daemon/database/utilities
URL: http://www.openvswitch.org/
Version: 2.15.0
Release: 47%{?dist}
Version: 2.16.0
Release: 8%{?dist}
# Nearly all of openvswitch is ASL 2.0. The bugtool is LGPLv2+, and the
# lib/sflow*.[ch] files are SISSL
# datapath/ is GPLv2 (although not built into any of the binary packages)
License: ASL 2.0 and LGPLv2+ and SISSL
%define dpdkver 20.11
%define dpdkver 20.11.1
%define dpdkdir dpdk
%define dpdksver %(echo %{dpdkver} | cut -d. -f-2)
# NOTE: DPDK does not currently build for s390x
......@@ -98,13 +98,14 @@ ExclusiveArch: x86_64 aarch64 ppc64le s390x
# Do not enable this otherwise YUM will break on any upgrade.
# Provides: openvswitch
Conflicts: openvswitch < 2.15
Conflicts: openvswitch-dpdk < 2.15
Conflicts: openvswitch < 2.16
Conflicts: openvswitch-dpdk < 2.16
Conflicts: openvswitch2.10
Conflicts: openvswitch2.11
Conflicts: openvswitch2.12
Conflicts: openvswitch2.13
Conflicts: openvswitch2.14
Conflicts: openvswitch2.15
# FIXME Sphinx is used to generate some manpages, unfortunately, on RHEL, it's
# in the -optional repository and so we can't require it directly since RHV
......@@ -675,11 +676,9 @@ exit 0
%doc LICENSE NOTICE README.rst NEWS rhel/README.RHEL.rst
%ifarch %{dpdkarches}
%doc %{dpdkdir}/README.DPDK-PMDS
%attr(750,openvswitch,hugetlbfs) %verify(not owner group) /var/log/openvswitch
%else
%attr(750,openvswitch,openvswitch) %verify(not owner group) /var/log/openvswitch
%endif
/var/lib/openvswitch
%attr(750,openvswitch,openvswitch) %verify(not owner group) /var/log/openvswitch
%ghost %attr(755,root,root) %verify(not owner group) %{_rundir}/openvswitch
%{_datadir}/openvswitch/bugtool-plugins/
%{_datadir}/openvswitch/scripts/ovs-bugtool-*
......@@ -699,370 +698,223 @@ exit 0
%endif
%changelog
* Tue Oct 19 2021 Open vSwitch CI <ovs-ci@redhat.com> - 2.15.0-47
- Merging upstream branch-2.15 [RH git: 01110b9088]
Commit list:
b7d9c491ec datapath-windows: add layers when adding the deferred actions
* Thu Oct 14 2021 Open vSwitch CI <ovs-ci@redhat.com> - 2.15.0-46
- Merging upstream branch-2.15 [RH git: f8619036c9]
Commit list:
3f718857e7 ofproto-dpif-xlate: Fix zone set from non-frozen-metadata fields.
* Wed Oct 13 2021 Open vSwitch CI <ovs-ci@redhat.com> - 2.15.0-45
- Merging upstream branch-2.15 [RH git: e273e307d1]
* Thu Sep 16 2021 Open vSwitch CI <ovs-ci@redhat.com> - 2.16.0-8
- Merging upstream branch-2.16 [RH git: 7332b410fc]
Commit list:
ea2ca0af16 dpif-netdev: Fix use-after-free on PACKET_OUT of IP fragments.
9f964354e3 tunnel-push-pop.at: Mask source port in tunnel header.
facaf5bc71 netdev-linux: Fix a null pointer dereference in netdev_linux_notify_sock().
6e203d4873 pcap-file: Fix memory leak in ovs_pcap_open().
f50da0b267 odp-util: Fix a null pointer dereference in odp_flow_format().
7da752e43f odp-util: Fix a null pointer dereference in odp_nsh_key_from_attr__().
bc22b01459 netdev-dpdk: Fix RSS configuration for virtio.
81706c5d43 ipf: Fix only nat the first fragment in the reass process.
* Tue Oct 12 2021 Open vSwitch CI <ovs-ci@redhat.com> - 2.15.0-44
- Merging upstream branch-2.15 [RH git: 3050e5222d]
* Wed Sep 08 2021 Open vSwitch CI <ovs-ci@redhat.com> - 2.16.0-7
- Merging upstream branch-2.16 [RH git: e71f31dfd6]
Commit list:
58397f222b dpdk-stub: Change the ERR log to DBG.
2a963fc314 python: idl: Avoid sending transactions when the DB is not synced up.
242c280f0e dpif-netdev: Fix crash when PACKET_OUT is metered.
* Tue Oct 12 2021 Open vSwitch CI <ovs-ci@redhat.com> - 2.15.0-43
- Merging upstream branch-2.15 [RH git: 09e3ab3630]
Commit list:
9efa2ea619 ipf: release unhandled packets from the batch
* Thu Sep 30 2021 Open vSwitch CI <ovs-ci@redhat.com> - 2.15.0-42
- Merging upstream branch-2.15 [RH git: 2a86017f3f]
Commit list:
f8274b78c3 datapath-windows:adjust Offset when processing packet in POP_VLAN action
* Mon Sep 27 2021 Open vSwitch CI <ovs-ci@redhat.com> - 2.15.0-41
- Merging upstream branch-2.15 [RH git: 8f2e30f011]
Commit list:
a2f860aa2e cirrus: Reduce memory requirements for FreeBSD VMs.
* Thu Sep 23 2021 Timothy Redaelli <tredaelli@redhat.com> - 2.15.0-40
- redhat: use hugetlbfs group for /var/log/openvswitch when dpdk is enabled [RH git: 5ccf239b51] (#2007290)
Resolves: #2007290
* Thu Sep 16 2021 Open vSwitch CI <ovs-ci@redhat.com> - 2.15.0-39
- Merging upstream branch-2.15 [RH git: c6bdfa8cc1]
Commit list:
7788f15798 netdev-linux: Fix a null pointer dereference in netdev_linux_notify_sock().
dd32deba6e pcap-file: Fix memory leak in ovs_pcap_open().
9f2f66c8ea odp-util: Fix a null pointer dereference in odp_flow_format().
02b0c265c4 odp-util: Fix a null pointer dereference in odp_nsh_key_from_attr__().
031eff4563 netdev-dpdk: Fix RSS configuration for virtio.
09cd9570d2 ipf: Fix only nat the first fragment in the reass process.
* Wed Sep 15 2021 Timothy Redaelli <tredaelli@redhat.com> - 2.15.0-38
- ofproto-dpif-xlate: Avoid successive ct_clear datapath actions. [RH git: f9a9ac7608] (#1941027)
Due to flow lookup optimizations, especially in the resubmit/clone cases,
we might end up with multiple ct_clear actions, which are not necessary.
* Tue Aug 31 2021 Ilya Maximets <i.maximets@redhat.com> - 2.16.0-6
- ovsdb: monitor: Store serialized json in a json cache. [RH git: bc20330c85] (#1996152)
commit 43e66fc27659af2a5c976bdd27fe747b442b5554
Author: Ilya Maximets <i.maximets@ovn.org>
Date: Tue Aug 24 21:00:39 2021 +0200
This patch only adds the ct_clear action to the datapath if any ct state
is tracked.
Same json from a json cache is typically sent to all the clients,
e.g., in case of OVN deployment with ovn-monitor-all=true.
Resolves: #1941027
There could be hundreds or thousands connected clients and ovsdb
will serialize the same json object for each of them before sending.
Signed-off-by: Eelco Chaudron <echaudro@redhat.com>
Acked-by: Timothy Redaelli <tredaelli@redhat.com>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
(cherry picked from commit 355fef6f2ccbcf78797b938421cb4cef9b59af13)
* Wed Sep 08 2021 Open vSwitch CI <ovs-ci@redhat.com> - 2.15.0-37
- Merging upstream branch-2.15 [RH git: b36eb7e529]
Commit list:
ef8ca3e190 dpif-netdev: Fix crash when PACKET_OUT is metered.
* Tue Aug 17 2021 Michael Santana <msantana@redhat.com> - 2.15.0-36
- Migrate openvswitch to gitlab [RH git: 93147e2cda]
Signed-off-by: Michael Santana <msantana@redhat.com>
* Mon Aug 16 2021 Open vSwitch CI <ovs-ci@redhat.com> - 2.15.0-35
- Merging upstream branch-2.15 [RH git: 11bcf52d03]
Commit list:
d3ff41d609 tc: Set action flags for tunnel_key release.
079a4de723 netlink-socket: Replace error with txn->error when logging nacked transactions.
f8cc5aa35c dynamic-string: Fix a crash in ds_clone().
* Mon Aug 16 2021 Michael Santana <msantana@redhat.com> - 2.15.0-34
- pkgtool: Swap bugzilla id and RH git [RH git: c2e6243d60]
Having the bugzilla ID not at the end of the line breakes another script
that parses for said ID. This patch fixes that by putting the ID next to
the new line
Serializing it once before storing into json cache to speed up
processing.
Fixes: f6b2db4dd33e ("Make changelog in spec file more informative")
Signed-off-by: Michael Santana <msantana@redhat.com>
* Mon Aug 16 2021 Open vSwitch CI <ovs-ci@redhat.com> - 2.15.0-33
- Merging upstream branch-2.15 [RH git: 08b4ccb1c4]
Commit list:
64d1bba919 dpif-netdev: fix memory leak in dpcls subtable set command
* Tue Aug 03 2021 Open vSwitch CI <ovs-ci@redhat.com> - 2.15.0-32
- Merging upstream branch-2.15 [RH git: 2cc833ce5b]
Commit list:
90b219275d dpif-netdev: Do not flush PMD offloads on reload.
* Mon Aug 02 2021 Open vSwitch CI <ovs-ci@redhat.com> - 2.15.0-31
- Merging upstream branch-2.15 [RH git: 88fb0bba8a]
Commit list:
b29b04f85f dpif-netdev: Fix offloads of modified flows.
1d0b89ea7b dpif-netdev: Fix flow modification after failure.
* Mon Jul 26 2021 Open vSwitch CI <ovs-ci@redhat.com> - 2.15.0-30
- Merging upstream branch-2.15 [RH git: a76a4dfca6]
Commit list:
8d84a4b166 netdev-offload-dpdk: Fix IPv6 rewrite cast-align warning.
f3f7849cbb daemon-unix: Fix leak of a fork error message.
* Fri Jul 23 2021 Open vSwitch CI <ovs-ci@redhat.com> - 2.15.0-29
- Merging upstream branch-2.15 [RH git: 60c8b2a15b]
Commit list:
8aa0f03747 ovsdb-cs: Perform forced reconnects without a backoff.
* Wed Jul 21 2021 Open vSwitch CI <ovs-ci@redhat.com> - 2.15.0-28
- Merging upstream branch-2.15 [RH git: 48a90081e8]
Commit list:
ee4e034dc9 datapath-windows:Correct checksum for DNAT action
* Sat Jul 17 2021 Open vSwitch CI <ovs-ci@redhat.com> - 2.15.0-27
- Merging upstream branch-2.15 [RH git: abdd952536]
Commit list:
72132a9403 bond: Fix broken rebalancing after link state changes.
aa84cfe25d dpif-netlink: Fix report_loss() message.
aec05f7cd1 ovsdb-server: Fix memleak when failing to read storage.
05bdf11fc3 conntrack: Init hash basis first at creation.
94e3b9d9ce netdev-linux: Ignore TSO packets when TSO is not enabled for userspace.
842bfb899f conntrack: Handle already natted packets.
ab873c1afe conntrack: Document all-zero IP SNAT behavior and add a test case.
86d6a9ee14 python: Fix Idl.run change_seqno update.
1ba0c83655 bridge: Use correct (legacy) role names in database.
7e5293ea5a Prepare for 2.15.2.
b855bbc326 Set release date for 2.15.1.
007a4f48fe dpif-netdev: Apply subtable-lookup-prio-set on any datapath.
c93358a563 netlink: removed incorrect optimization
31626579fa ovs-actions.xml: Add missing bracket.
30596ec278 netdev-offload-tc: Use nl_msg_put_flag for OVS_TUNNEL_KEY_ATTR_CSUM.
728980291a conntrack: Increment coverage counter for all bad checksum cases.
* Wed Jun 30 2021 Timothy Redaelli <tredaelli@redhat.com> - 2.15.0-26
- Use 10 characters of hash to generate the changelog [RH git: d89d9cd0f1]
This is needed to avoid that the history changes since the default
changes from time to time
* Wed Jun 30 2021 Timothy Redaelli <tredaelli@redhat.com> - 2.15.0-25
- Merging 881d71ea22e datapath-windows: Specify external include .. [RH git: 8ad5538601]
Commit list:
881d71ea22e datapath-windows: Specify external include paths
934668c295e Remove Python 2 leftovers.
aaa59670556 ipf: Fix a use-after-free error, and remove the 'do_not_steal' flag.
* Fri Jun 11 2021 Open vSwitch CI <ovs-ci@redhat.com> - 2.15.0-24
- Merging upstream branch-2.15 [RH git: 78ba3622d9]
Commit list:
bc0aa785a8 ovsdb-idl: Fix the database update signaling if it has never been connected.
559426d2b0 ofproto: Fix potential NULL dereference in ofproto_ct_*_zone_timeout_policy().
f31070e27e ofproto: Fix potential NULL dereference in ofproto_get_datapath_cap().
* Thu May 27 2021 Open vSwitch CI <ovs-ci@redhat.com> - 2.15.0-23
- Merging upstream branch-2.15 [RH git: ba3ba16d42]
Commit list:
8995d53112 dpif-netlink: Fix send of uninitialized memory in ct limit requests.
0c056891c2 ofproto-dpif: Fix use of uninitialized attributes of timeout policy.
121a67cad3 netdev-linux: Fix use of uninitialized LAG master name.
5f27ff1cfa ofp_actions: Fix set_mpls_tc formatting.
* Wed May 19 2021 Open vSwitch CI <ovs-ci@redhat.com> - 2.15.0-22
- Merging upstream branch-2.15 [RH git: 8b6b82c2ed]
Commit list:
e87adce83c dpif-netdev: Remove meter rate from the bucket size calculation.
* Sat May 15 2021 Open vSwitch CI <ovs-ci@redhat.com> - 2.15.0-21
- Merging upstream branch-2.15 [RH git: c7b9daa243]
Commit list:
a3ee3258e2 ovs-ofctl: Fix coredump when using "add-groups" command.
* Fri May 14 2021 Open vSwitch CI <ovs-ci@redhat.com> - 2.15.0-20
- Merging upstream branch-2.15 [RH git: 69559c9283]
Commit list:
c5d2a62750 raft: Transfer leadership before creating snapshots.
* Fri May 14 2021 Open vSwitch CI <ovs-ci@redhat.com> - 2.15.0-19
- Merging upstream branch-2.15 [RH git: 6aa50cbb89]
Commit list:
553d523929 ovsdb-cs: Consider all tables when computing expected cond seqno.
8d0aebcc49 dpdk: Use DPDK 20.11.1 release.
* Wed May 12 2021 Timothy Redaelli <tredaelli@redhat.com> - 2.15.0-18
- Merge tag 'b6167fabb202faa025946348f514e369dba5853b' into fast-datapath-rhel-8 [RH git: 1cdc5555f9]
dpdk-20.11.1
* Tue May 11 2021 Open vSwitch CI <ovs-ci@redhat.com> - 2.15.0-17
- Merging upstream branch-2.15 [RH git: 120e2a5d87]
Commit list:
21452722b7 github: Fix up malformed /etc/hosts.
90d1984b99 doc: automake: Add support for sphinx 4.0.
38a8bed703 cirrus: Look up existing versions of python dependencies.
* Mon May 10 2021 Open vSwitch CI <ovs-team@redhat.com> - 2.15.0-16
- Merging upstream branch-2.15 [RH git: dbd5501f48]
Commit list:
255c38c745 ofp-group: Use big-enough buffer in ofputil_format_group().
* Wed Apr 21 2021 Open vSwitch CI <ovs-team@redhat.com> - 2.15.0-15
- Merging upstream branch-2.15 [RH git: 85f5aecb83]
Commit list:
f2c0744d2f ofproto/ofproto-dpif-sflow: Check sflow agent in case of race
* Tue Apr 20 2021 Aaron Conole <aconole@redhat.com> - 2.15.0-14
- Merging ct_state_fix [RH git: f847e4fac1]
Commit list:
09a2081067 netdev-offload-tc: Add support for ct_state flag rel.
423048a34f netdev-offload-tc: Add support for ct_state flags inv and rpl
* Tue Apr 20 2021 Aaron Conole <aconole@redhat.com> - 2.15.0-13
- ab157ef34d dpif: Fix use of uninitialized execute hash. b1fded0208 odp-util: Fix use of uninitialized erspan metadata. f473ee5689 dpif-netlink: Fix using uninitialized info.tc_modify_flow_deleted in out label. 2721606bd4 netdev-offload-tc: Probe for support for any of the ct_state flags. 091bc48d9c compat: Add ct_state flags definitions. [RH git: e4336ed96c]
* Tue Apr 20 2021 Timothy Redaelli <tredaelli@redhat.com> - 2.15.0-12
- Fix typo in rh-mock-srpm [RH git: 85631264db]
Thanks fbl for reporting
* Wed Apr 14 2021 Open vSwitch CI <ovs-team@redhat.com> - 2.15.0-11
- Merging upstream branch-2.15 [RH git: 71c33052b9]
Commit list:
1307e90e3f Add test cases for ingress_policing parameters
d184c6ce67 netdev-linux: correct unit of burst parameter
* Wed Apr 07 2021 Michael Santana <msantana@redhat.com> - 2.15.0-10
- Make changelog in spec file more informative [RH git: f6b2db4dd3]
This is done by adding the body of the commit message to the changelong.
The body is indented and has extra spacing separating each entry in the
changelog to make each one more discernible since now they could be
longer
This change allows to save a lot of CPU cycles and a bit of memory
since we need to store in memory only a string and not the full json
object.
Signed-off-by: Michael Santana <msantana@redhat.com>
* Thu Apr 01 2021 Open vSwitch CI <ovs-team@redhat.com> - 2.15.0-9
- Merging upstream branch-2.15 [RH git: 504b67ec8d]
Commit list:
cab998e500 ipsec: Fix IPv6 default route support for Libreswan.
* Thu Apr 01 2021 Open vSwitch CI <ovs-team@redhat.com> - 2.15.0-8
- Merging upstream branch-2.15 [RH git: 147a0970be]
Commit list:
b9ab7827ec ovsdb-idl: Mark arc sources as updated when destination is deleted.
c82d2e3fbc ovsdb-idl: Preserve references for deleted rows.
9a24ecbc2a ovsdb-idl.at: Make test outputs more predictable.
Testing with ovn-heater on 120 nodes using density-heavy scenario
shows reduction of the total CPU time used by Southbound DB processes
from 256 minutes to 147. Duration of unreasonably long poll intervals
also reduced dramatically from 7 to 2 seconds:
Count Min Max Median Mean 95 percentile
-------------------------------------------------------------
Before 1934 1012 7480 4302.5 4875.3 7034.3
After 1909 1004 2730 1453.0 1532.5 2053.6
Acked-by: Dumitru Ceara <dceara@redhat.com>
Acked-by: Han Zhou <hzhou@ovn.org>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1996152
Signed-off-by: Ilya Maximets <i.maximets@redhat.com>
* Wed Mar 31 2021 Open vSwitch CI <ovs-team@redhat.com> - 2.15.0-7
- Merging upstream branch-2.15 [RH git: cbb083630e]
Commit list:
8d71feb1b8 ovs-ofctl: Fix segfault due to bad meter n_bands.
* Tue Aug 31 2021 Ilya Maximets <i.maximets@redhat.com> - 2.16.0-5
- raft: Don't keep full json objects in memory if no longer needed. [RH git: 4606423e8b] (#1990058)
commit 0de882954032aa37dc943bafd72c33324aa0c95a
Author: Ilya Maximets <i.maximets@ovn.org>
Date: Tue Aug 24 21:00:38 2021 +0200
raft: Don't keep full json objects in memory if no longer needed.
Raft log entries (and raft database snapshot) contains json objects
of the data. Follower receives append requests with data that gets
parsed and added to the raft log. Leader receives execution requests,
parses data out of them and adds to the log. In both cases, later
ovsdb-server reads the log with ovsdb_storage_read(), constructs
transaction and updates the database. On followers these json objects
in common case are never used again. Leader may use them to send
append requests or snapshot installation requests to followers.
However, all these operations (except for ovsdb_storage_read()) are
just serializing the json in order to send it over the network.
Json objects are significantly larger than their serialized string
representation. For example, the snapshot of the database from one of
the ovn-heater scale tests takes 270 MB as a string, but 1.6 GB as
a json object from the total 3.8 GB consumed by ovsdb-server process.
ovsdb_storage_read() for a given raft entry happens only once in a
lifetime, so after this call, we can serialize the json object, store
the string representation and free the actual json object that ovsdb
will never need again. This can save a lot of memory and can also
save serialization time, because each raft entry for append requests
and snapshot installation requests serialized only once instead of
doing that every time such request needs to be sent.
JSON_SERIALIZED_OBJECT can be used in order to seamlessly integrate
pre-serialized data into raft_header and similar json objects.
One major special case is creation of a database snapshot.
Snapshot installation request received over the network will be parsed
and read by ovsdb-server just like any other raft log entry. However,
snapshots created locally with raft_store_snapshot() will never be
read back, because they reflect the current state of the database,
hence already applied. For this case we can free the json object
right after writing snapshot on disk.
Tests performed with ovn-heater on 60 node density-light scenario,
where on-disk database goes up to 97 MB, shows average memory
consumption of ovsdb-server Southbound DB processes decreased by 58%
(from 602 MB to 256 MB per process) and peak memory consumption
decreased by 40% (from 1288 MB to 771 MB).
Test with 120 nodes on density-heavy scenario with 270 MB on-disk
database shows 1.5 GB memory consumption decrease as expected.
Also, total CPU time consumed by the Southbound DB process reduced
from 296 to 256 minutes. Number of unreasonably long poll intervals
reduced from 2896 down to 1934.
Deserialization is also implemented just in case. I didn't see this
function being invoked in practice.
Acked-by: Dumitru Ceara <dceara@redhat.com>
Acked-by: Han Zhou <hzhou@ovn.org>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1990058
Signed-off-by: Ilya Maximets <i.maximets@redhat.com>
* Wed Mar 31 2021 Open vSwitch CI <ovs-team@redhat.com> - 2.15.0-6
- Merging upstream branch-2.15 [RH git: 221cf613d7]
Commit list:
3a716b1d9c dpif-netdev: Refactor and fix the buckets calculation.
73ece9c87b dpif-netdev: Fix the meter buckets overflow.
* Tue Aug 31 2021 Ilya Maximets <i.maximets@redhat.com> - 2.16.0-4
- json: Add support for partially serialized json objects. [RH git: 885e5ce1b5] (#1990058)
commit b0bca6f27aae845c3ca8b48d66a7dbd3d978162a
Author: Ilya Maximets <i.maximets@ovn.org>
Date: Tue Aug 24 21:00:37 2021 +0200
json: Add support for partially serialized json objects.
Introducing a new json type JSON_SERIALIZED_OBJECT. It's not an
actual type that can be seen in a json message on a wire, but
internal type that is intended to hold a serialized version of
some other json object. For this reason it's defined after the
JSON_N_TYPES to not confuse parsers and other parts of the code
that relies on compliance with RFC 4627.
With this JSON type internal users may construct large JSON objects,
parts of which are already serialized. This way, while serializing
the larger object, data from JSON_SERIALIZED_OBJECT can be added
directly to the result, without additional processing.
This will be used by next commits to add pre-serialized JSON data
to the raft_header structure, that can be converted to a JSON
before writing the file transaction on disk or sending to other
servers. Same technique can also be used to pre-serialize json_cache
for ovsdb monitors, this should allow to not perform serialization
for every client and will save some more memory.
Since serialized JSON is just a string, reusing the 'json->string'
pointer for it.
Acked-by: Dumitru Ceara <dceara@redhat.com>
Acked-by: Han Zhou <hzhou@ovn.org>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1990058
Signed-off-by: Ilya Maximets <i.maximets@redhat.com>
* Mon Mar 22 2021 Kevin Traynor <ktraynor@redhat.com> - 2.15.0-5
- dpif-netdev: Allow PMD auto load balance with cross-numa. [RH git: 47e2824210] (#1941673)
commit ec68a877db5bbfba49ddeb9929479c033420ea6b
Author: Kevin Traynor <ktraynor@redhat.com>
Date: Thu Mar 18 11:34:04 2021 +0000
* Tue Aug 31 2021 Ilya Maximets <i.maximets@redhat.com> - 2.16.0-3
- json: Optimize string serialization. [RH git: bb1654da63] (#1990069)
commit 748010ff304b7cd2c43f4eb98a554433f0df07f9
Author: Ilya Maximets <i.maximets@ovn.org>
Date: Tue Aug 24 23:07:22 2021 +0200
json: Optimize string serialization.
Current string serialization code puts all characters one by one.
This is slow because dynamic string needs to perform length checks
on every ds_put_char() and it's also doesn't allow compiler to use
better memory copy operations, i.e. doesn't allow copying few bytes
at once.
dpif-netdev: Allow PMD auto load balance with cross-numa.
Special symbols are rare in a typical database. Quotes are frequent,
but not too frequent. In databases created by ovn-kubernetes, for
example, usually there are at least 10 to 50 chars between quotes.
So, it's better to count characters that doesn't require escaping
and use fast data copy for the whole sequential block.
Previously auto load balance did not trigger a reassignment when
there was any cross-numa polling as an rxq could be polled from a
different numa after reassign and it could impact estimates.
Testing with a synthetic benchmark (included) on my laptop shows
following performance improvement:
In the case where there is only one numa with pmds available, the
same numa will always poll before and after reassignment, so estimates
are valid. Allow PMD auto load balance to trigger a reassignment in
this case.
Size Q S Before After Diff
-----------------------------------------------------
100000 0 0 : 0.227 ms 0.142 ms -37.4 %
100000 2 1 : 0.277 ms 0.186 ms -32.8 %
100000 10 1 : 0.361 ms 0.309 ms -14.4 %
10000000 0 0 : 22.720 ms 12.160 ms -46.4 %
10000000 2 1 : 27.470 ms 19.300 ms -29.7 %
10000000 10 1 : 37.950 ms 31.250 ms -17.6 %
100000000 0 0 : 239.600 ms 126.700 ms -47.1 %
100000000 2 1 : 292.400 ms 188.600 ms -35.4 %
100000000 10 1 : 387.700 ms 321.200 ms -17.1 %
Here Q - probability (%) for a character to be a '\"' and
S - probability (%) to be a special character ( < 32).
Testing with a closer to real world scenario shows overall decrease
of the time needed for database compaction by ~5-10 %. And this
change also decreases CPU consumption in general, because string
serialization is used in many different places including ovsdb
monitors and raft.
Acked-by: Eelco Chaudron <echaudro@redhat.com>
Acked-by: David Marchand <david.marchand@redhat.com>
Tested-by: Sunil Pai G <sunil.pai.g@intel.com>
Acked-by: Flavio Leitner <fbl@sysclose.org>
Signed-off-by: Kevin Traynor <ktraynor@redhat.com>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
Acked-by: Numan Siddique <numans@ovn.org>
Acked-by: Dumitru Ceara <dceara@redhat.com>
Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1941673
Conflicts: Commit backported from upstream master branch. Commit not
present on upstream branch-2.15. Removed NEWS file update as could cause
future merge conflicts.
Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1990069
Signed-off-by: Ilya Maximets <i.maximets@redhat.com>
* Fri Mar 19 2021 Kevin Traynor <ktraynor@redhat.com> - 2.15.0-4
- redhat: Update docs for test builds [RH git: 7620c95a37]
* Fri Aug 20 2021 Open vSwitch CI <ovs-ci@redhat.com> - 2.16.0-2
- Merging upstream branch-2.16 [RH git: 7d7567e339]
Commit list:
0991ea8d19 Prepare for 2.16.1.
* Tue Mar 16 2021 Open vSwitch CI <ovs-team@redhat.com> - 2.15.0-3
- Merging upstream branch-2.15 [RH git: c4fc969d7e]
Commit list:
d5dc16670e python: Send notifications after the transaction ends.
556e65e179 ovs-ctl: Allow recording hostname separately.
3982aee455 dpif-netdev: Fix crash when add dp flow without in_port field.
02096f1b37 Documentation: Fix DPDK qos example.
8f1dda3164 raft: Report disconnected in cluster/status if candidate retries election.
79e9749daa raft: Reintroduce jsonrpc inactivity probes.
2e84a4adb1 ovsdb-cs: Fix use-after-free for the request id.
d2c311dce8 connmgr: Check nullptr inside ofmonitor_report().
7307af6908 ovsdb-client: Fix needs-conversion when SERVER is explicitly specified.
2a7a635718 windows, tests: Modify service test.
9b48549c68 netdev-linux: Fix indentation.
861a9f3b4d ofproto-dpif-upcall: Fix ukey leak on udpif destroy.
339044c3cc ci: Use parallel build for distcheck.
38744b1bcb ofp-actions: Fix use-after-free while decoding RAW_ENCAP.
33abe6c052 Prepare for 2.15.1.
* Tue Feb 16 2021 Timothy Redaelli <tredaelli@redhat.com> - 2.15.0-2
- build with ipsec support by default [RH git: 105482aee7]
* Mon Feb 15 2021 Timothy Redaelli <tredaelli@redhat.com> - 2.15.0-1
- Use official 2.15.0 tarball [RH git: 9e107c6359]
* Wed Aug 18 2021 Flavio Leitner <fbl@redhat.com> - 2.16.0-1
- redhat: First 2.16.0 release. [RH git: 0a1c4276cc]
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment