diff --git a/.ci/linux-build.sh b/.ci/linux-build.sh index 3e5136fd4e..dd29a4182d 100755 --- a/.ci/linux-build.sh +++ b/.ci/linux-build.sh @@ -235,7 +235,7 @@ if [ "$TESTSUITE" ]; then configure_ovs export DISTCHECK_CONFIGURE_FLAGS="$OPTS" - if ! make distcheck CFLAGS="${CFLAGS_FOR_OVS}" \ + if ! make distcheck -j4 CFLAGS="${CFLAGS_FOR_OVS}" \ TESTSUITEFLAGS=-j4 RECHECK=yes; then # testsuite.log is necessary for debugging. cat */_build/sub/tests/testsuite.log diff --git a/Documentation/topics/dpdk/pmd.rst b/Documentation/topics/dpdk/pmd.rst index caa7d97bef..e481e79414 100644 --- a/Documentation/topics/dpdk/pmd.rst +++ b/Documentation/topics/dpdk/pmd.rst @@ -239,7 +239,9 @@ If not set, the default variance improvement threshold is 25%. PMD Auto Load Balancing doesn't currently work if queues are assigned cross NUMA as actual processing load could get worse after assignment - as compared to what dry run predicts. + as compared to what dry run predicts. The only exception is when all + PMD threads are running on cores from a single NUMA node. In this case + Auto Load Balancing is still possible. The minimum time between 2 consecutive PMD auto load balancing iterations can also be configured by:: diff --git a/Documentation/topics/dpdk/qos.rst b/Documentation/topics/dpdk/qos.rst index 103495415a..a98ec672fc 100644 --- a/Documentation/topics/dpdk/qos.rst +++ b/Documentation/topics/dpdk/qos.rst @@ -69,22 +69,24 @@ to prioritize certain traffic over others at a port level. For example, the following configuration will limit the traffic rate at a port level to a maximum of 2000 packets a second (64 bytes IPv4 packets). -100pps as CIR (Committed Information Rate) and 1000pps as EIR (Excess -Information Rate). High priority traffic is routed to queue 10, which marks +1000pps as CIR (Committed Information Rate) and 1000pps as EIR (Excess +Information Rate). CIR and EIR are measured in bytes without Ethernet header. +As a result, 1000pps means (64-byte - 14-byte) * 1000 = 50,000 in the +configuration below. High priority traffic is routed to queue 10, which marks all traffic as CIR, i.e. Green. All low priority traffic, queue 20, is marked as EIR, i.e. Yellow:: $ ovs-vsctl --timeout=5 set port dpdk1 qos=@myqos -- \ --id=@myqos create qos type=trtcm-policer \ - other-config:cir=52000 other-config:cbs=2048 \ - other-config:eir=52000 other-config:ebs=2048 \ + other-config:cir=50000 other-config:cbs=2048 \ + other-config:eir=50000 other-config:ebs=2048 \ queues:10=@dpdk1Q10 queues:20=@dpdk1Q20 -- \ --id=@dpdk1Q10 create queue \ - other-config:cir=41600000 other-config:cbs=2048 \ + other-config:cir=100000 other-config:cbs=2048 \ other-config:eir=0 other-config:ebs=0 -- \ --id=@dpdk1Q20 create queue \ other-config:cir=0 other-config:cbs=0 \ - other-config:eir=41600000 other-config:ebs=2048 \ + other-config:eir=50000 other-config:ebs=2048 This configuration accomplishes that the high priority traffic has a guaranteed bandwidth egressing the ports at CIR (1000pps), but it can also diff --git a/NEWS b/NEWS index bc901efdb1..036d4032c4 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,11 @@ +v2.15.1 - xx xxx xxxx +--------------------- + - ovs-ctl: + * New option '--no-record-hostname' to disable hostname configuration + in ovsdb on startup. + * New command 'record-hostname-if-not-set' to update hostname in ovsdb. + + v2.15.0 - 15 Feb 2021 --------------------- - OVSDB: diff --git a/acinclude.m4 b/acinclude.m4 index 435685c93d..15a54d636f 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -209,10 +209,10 @@ dnl Configure Linux tc compat. AC_DEFUN([OVS_CHECK_LINUX_TC], [ AC_COMPILE_IFELSE([ AC_LANG_PROGRAM([#include ], [ - int x = TCA_ACT_FLAGS; + int x = TCA_FLOWER_KEY_CT_FLAGS_REPLY; ])], - [AC_DEFINE([HAVE_TCA_ACT_FLAGS], [1], - [Define to 1 if TCA_ACT_FLAGS is available.])]) + [AC_DEFINE([HAVE_TCA_FLOWER_KEY_CT_FLAGS_REPLY], [1], + [Define to 1 if TCA_FLOWER_KEY_CT_FLAGS_REPLY is available.])]) AC_CHECK_MEMBERS([struct tcf_t.firstuse], [], [], [#include ]) diff --git a/configure.ac b/configure.ac index fd82d7d270..9299342960 100644 --- a/configure.ac +++ b/configure.ac @@ -13,7 +13,7 @@ # limitations under the License. AC_PREREQ(2.63) -AC_INIT(openvswitch, 2.15.0, bugs@openvswitch.org) +AC_INIT(openvswitch, 2.15.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 1f2b7a3668..8b5d075840 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +openvswitch (2.15.1-1) unstable; urgency=low + [ Open vSwitch team ] + * New upstream version + + -- Open vSwitch team Mon, 15 Feb 2021 17:35:33 +0100 + openvswitch (2.15.0-1) unstable; urgency=low * New upstream version diff --git a/include/linux/pkt_cls.h b/include/linux/pkt_cls.h index b0a5ce8bec..bc51a5767f 100644 --- a/include/linux/pkt_cls.h +++ b/include/linux/pkt_cls.h @@ -1,7 +1,7 @@ #ifndef __LINUX_PKT_CLS_WRAPPER_H #define __LINUX_PKT_CLS_WRAPPER_H 1 -#if defined(__KERNEL__) || defined(HAVE_TCA_ACT_FLAGS) +#if defined(__KERNEL__) || defined(HAVE_TCA_FLOWER_KEY_CT_FLAGS_REPLY) #include_next #else @@ -255,6 +255,9 @@ enum { TCA_FLOWER_KEY_CT_FLAGS_ESTABLISHED = 1 << 1, /* Part of an existing connection. */ TCA_FLOWER_KEY_CT_FLAGS_RELATED = 1 << 2, /* Related to an established connection. */ TCA_FLOWER_KEY_CT_FLAGS_TRACKED = 1 << 3, /* Conntrack has occurred. */ + TCA_FLOWER_KEY_CT_FLAGS_INVALID = 1 << 4, /* Conntrack is invalid. */ + TCA_FLOWER_KEY_CT_FLAGS_REPLY = 1 << 5, /* Packet is in the reply direction. */ + __TCA_FLOWER_KEY_CT_FLAGS_MAX, }; enum { diff --git a/ipsec/ovs-monitor-ipsec.in b/ipsec/ovs-monitor-ipsec.in index 64111768b3..668507fd37 100755 --- a/ipsec/ovs-monitor-ipsec.in +++ b/ipsec/ovs-monitor-ipsec.in @@ -14,6 +14,7 @@ # limitations under the License. import argparse +import ipaddress import re import subprocess import sys @@ -413,6 +414,11 @@ conn prevent_unencrypted_vxlan leftprotoport=udp/4789 mark={0} +""" + + IPV6_CONN = """\ + hostaddrfamily=ipv6 + clientaddrfamily=ipv6 """ auth_tmpl = {"psk": Template("""\ @@ -520,6 +526,9 @@ conn prevent_unencrypted_vxlan else: auth_section = self.auth_tmpl["pki_ca"].substitute(tunnel.conf) + if tunnel.conf["address_family"] == "IPv6": + auth_section = self.IPV6_CONN + auth_section + vals = tunnel.conf.copy() vals["auth_section"] = auth_section vals["version"] = tunnel.version @@ -756,6 +765,7 @@ class IPsecTunnel(object): Tunnel Type: $tunnel_type Local IP: $local_ip Remote IP: $remote_ip + Address Family: $address_family SKB mark: $skb_mark Local cert: $certificate Local name: $local_name @@ -797,6 +807,9 @@ class IPsecTunnel(object): "tunnel_type": row.type, "local_ip": options.get("local_ip", "%defaultroute"), "remote_ip": options.get("remote_ip"), + "address_family": self._get_conn_address_family( + options.get("remote_ip"), + options.get("local_ip")), "skb_mark": monitor.conf["skb_mark"], "certificate": monitor.conf["pki"]["certificate"], "private_key": monitor.conf["pki"]["private_key"], @@ -865,6 +878,17 @@ class IPsecTunnel(object): return header + conf + status + spds + sas + cons + "\n" + def _get_conn_address_family(self, remote_ip, local_ip): + remote = address_family(remote_ip) + local = address_family(local_ip) + + if local is None: + return remote + elif local != remote: + return None + else: + return remote + def _is_valid_tunnel_conf(self): """This function verifies if IPsec tunnel has valid configuration set in 'conf'. If it is valid, then it returns True. Otherwise, @@ -1120,6 +1144,19 @@ class IPsecMonitor(object): return m.group(1) +def address_family(address): + try: + ip = ipaddress.ip_address(address) + ipstr = str(type(ip)) + # ipaddress has inconsistencies with what exceptions are raised: + # https://mail.openvswitch.org/pipermail/ovs-dev/2021-April/381696.html + except (ValueError, ipaddress.AddressValueError): + return None + if ipstr.find('v6') != -1: + return "IPv6" + return "IPv4" + + def unixctl_xfrm_policies(conn, unused_argv, unused_aux): global xfrm policies = xfrm.get_policies() diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index 4381c618f1..251788b049 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -279,8 +279,9 @@ static bool dpcls_lookup(struct dpcls *cls, ( 1 << OFPMBT13_DROP ) struct dp_meter_band { - struct ofputil_meter_band up; /* type, prec_level, pad, rate, burst_size */ - uint32_t bucket; /* In 1/1000 packets (for PKTPS), or in bits (for KBPS) */ + uint32_t rate; + uint32_t burst_size; + uint64_t bucket; /* In 1/1000 packets (for PKTPS), or in bits (for KBPS) */ uint64_t packet_count; uint64_t byte_count; }; @@ -3834,6 +3835,15 @@ dpif_netdev_flow_put(struct dpif *dpif, const struct dpif_flow_put *put) return error; } + if (match.wc.masks.in_port.odp_port != ODPP_NONE) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); + + VLOG_ERR_RL(&rl, "failed to put%s flow: in_port is not an exact match", + (put->flags & DPIF_FP_CREATE) ? "[create]" + : (put->flags & DPIF_FP_MODIFY) ? "[modify]" : "[zero]"); + return EINVAL; + } + if (put->ufid) { ufid = *put->ufid; } else { @@ -4878,6 +4888,12 @@ struct rr_numa { bool idx_inc; }; +static size_t +rr_numa_list_count(struct rr_numa_list *rr) +{ + return hmap_count(&rr->numas); +} + static struct rr_numa * rr_numa_list_lookup(struct rr_numa_list *rr, int numa_id) { @@ -5590,10 +5606,17 @@ get_dry_run_variance(struct dp_netdev *dp, uint32_t *core_list, for (int i = 0; i < n_rxqs; i++) { int numa_id = netdev_get_numa_id(rxqs[i]->port->netdev); numa = rr_numa_list_lookup(&rr, numa_id); + /* If there is no available pmd on the local numa but there is only one + * numa for cross-numa polling, we can estimate the dry run. */ + if (!numa && rr_numa_list_count(&rr) == 1) { + numa = rr_numa_list_next(&rr, NULL); + } if (!numa) { - /* Abort if cross NUMA polling. */ - VLOG_DBG("PMD auto lb dry run." - " Aborting due to cross-numa polling."); + VLOG_DBG("PMD auto lb dry run: " + "There's no available (non-isolated) PMD thread on NUMA " + "node %d for port '%s' and there are PMD threads on more " + "than one NUMA node available for cross-NUMA polling. " + "Aborting.", numa_id, netdev_rxq_get_name(rxqs[i]->rx)); goto cleanup; } @@ -6203,12 +6226,14 @@ dp_netdev_run_meter(struct dp_netdev *dp, struct dp_packet_batch *packets_, /* Update all bands and find the one hit with the highest rate for each * packet (if any). */ for (int m = 0; m < meter->n_bands; ++m) { - band = &meter->bands[m]; + uint64_t max_bucket_size; + band = &meter->bands[m]; + max_bucket_size = (band->rate + band->burst_size) * 1000ULL; /* Update band's bucket. */ - band->bucket += delta_t * band->up.rate; - if (band->bucket > band->up.burst_size) { - band->bucket = band->up.burst_size; + band->bucket += (uint64_t) delta_t * band->rate; + if (band->bucket > max_bucket_size) { + band->bucket = max_bucket_size; } /* Drain the bucket for all the packets, if possible. */ @@ -6226,8 +6251,8 @@ dp_netdev_run_meter(struct dp_netdev *dp, struct dp_packet_batch *packets_, * (Only one band will be fired by a packet, and that * can be different for each packet.) */ for (int i = band_exceeded_pkt; i < cnt; i++) { - if (band->up.rate > exceeded_rate[i]) { - exceeded_rate[i] = band->up.rate; + if (band->rate > exceeded_rate[i]) { + exceeded_rate[i] = band->rate; exceeded_band[i] = m; } } @@ -6246,8 +6271,8 @@ dp_netdev_run_meter(struct dp_netdev *dp, struct dp_packet_batch *packets_, /* Update the exceeding band for the exceeding packet. * (Only one band will be fired by a packet, and that * can be different for each packet.) */ - if (band->up.rate > exceeded_rate[i]) { - exceeded_rate[i] = band->up.rate; + if (band->rate > exceeded_rate[i]) { + exceeded_rate[i] = band->rate; exceeded_band[i] = m; } } @@ -6329,16 +6354,15 @@ dpif_netdev_meter_set(struct dpif *dpif, ofproto_meter_id meter_id, config->bands[i].burst_size = config->bands[i].rate; } - meter->bands[i].up = config->bands[i]; - /* Convert burst size to the bucket units: */ - /* pkts => 1/1000 packets, kilobits => bits. */ - meter->bands[i].up.burst_size *= 1000; - /* Initialize bucket to empty. */ - meter->bands[i].bucket = 0; + meter->bands[i].rate = config->bands[i].rate; + meter->bands[i].burst_size = config->bands[i].burst_size; + /* Start with a full bucket. */ + meter->bands[i].bucket = + (meter->bands[i].burst_size + meter->bands[i].rate) * 1000ULL; /* Figure out max delta_t that is enough to fill any bucket. */ band_max_delta_t - = meter->bands[i].up.burst_size / meter->bands[i].up.rate; + = meter->bands[i].bucket / meter->bands[i].rate; if (band_max_delta_t > meter->max_delta_t) { meter->max_delta_t = band_max_delta_t; } diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c index ceb56c6851..50520f8c06 100644 --- a/lib/dpif-netlink.c +++ b/lib/dpif-netlink.c @@ -2061,6 +2061,7 @@ parse_flow_put(struct dpif_netlink *dpif, struct dpif_flow_put *put) uint8_t csum_on = false; int err; + info.tc_modify_flow_deleted = false; if (put->flags & DPIF_FP_PROBE) { return EOPNOTSUPP; } @@ -2105,7 +2106,6 @@ parse_flow_put(struct dpif_netlink *dpif, struct dpif_flow_put *put) info.tunnel_csum_on = csum_on; info.recirc_id_shared_with_tc = (dpif->user_features & OVS_DP_F_TC_RECIRC_SHARING); - info.tc_modify_flow_deleted = false; err = netdev_flow_put(dev, &match, CONST_CAST(struct nlattr *, put->actions), put->actions_len, diff --git a/lib/dpif.c b/lib/dpif.c index 56d0b4a654..26e8bfb7db 100644 --- a/lib/dpif.c +++ b/lib/dpif.c @@ -1240,6 +1240,7 @@ dpif_execute_helper_cb(void *aux_, struct dp_packet_batch *packets_, execute.needs_help = false; execute.probe = false; execute.mtu = 0; + execute.hash = 0; aux->error = dpif_execute(aux->dpif, &execute); log_execute_message(aux->dpif, &this_module, &execute, true, aux->error); diff --git a/lib/dpif.h b/lib/dpif.h index ecda896c78..f9728e6739 100644 --- a/lib/dpif.h +++ b/lib/dpif.h @@ -727,7 +727,7 @@ struct dpif_execute { bool probe; /* Suppress error messages. */ unsigned int mtu; /* Maximum transmission unit to fragment. 0 if not a fragmented packet */ - uint64_t hash; + uint64_t hash; /* Packet flow hash. 0 if not specified. */ const struct flow *flow; /* Flow extracted from 'packet'. */ /* Input, but possibly modified as a side effect of execution. */ diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c index 6be23dbeed..f87a200756 100644 --- a/lib/netdev-linux.c +++ b/lib/netdev-linux.c @@ -1255,21 +1255,21 @@ netdev_linux_batch_rxq_recv_sock(struct netdev_rxq_linux *rx, int mtu, * aux_buf is allocated so that it can be prepended to TSO buffer. */ std_len = virtio_net_hdr_size + VLAN_ETH_HEADER_LEN + mtu; for (i = 0; i < NETDEV_MAX_BURST; i++) { - buffers[i] = dp_packet_new_with_headroom(std_len, DP_NETDEV_HEADROOM); - iovs[i][IOV_PACKET].iov_base = dp_packet_data(buffers[i]); - iovs[i][IOV_PACKET].iov_len = std_len; - if (iovlen == IOV_TSO_SIZE) { - iovs[i][IOV_AUXBUF].iov_base = dp_packet_data(rx->aux_bufs[i]); - iovs[i][IOV_AUXBUF].iov_len = dp_packet_tailroom(rx->aux_bufs[i]); - } + buffers[i] = dp_packet_new_with_headroom(std_len, DP_NETDEV_HEADROOM); + iovs[i][IOV_PACKET].iov_base = dp_packet_data(buffers[i]); + iovs[i][IOV_PACKET].iov_len = std_len; + if (iovlen == IOV_TSO_SIZE) { + iovs[i][IOV_AUXBUF].iov_base = dp_packet_data(rx->aux_bufs[i]); + iovs[i][IOV_AUXBUF].iov_len = dp_packet_tailroom(rx->aux_bufs[i]); + } - mmsgs[i].msg_hdr.msg_name = NULL; - mmsgs[i].msg_hdr.msg_namelen = 0; - mmsgs[i].msg_hdr.msg_iov = iovs[i]; - mmsgs[i].msg_hdr.msg_iovlen = iovlen; - mmsgs[i].msg_hdr.msg_control = &cmsg_buffers[i]; - mmsgs[i].msg_hdr.msg_controllen = sizeof cmsg_buffers[i]; - mmsgs[i].msg_hdr.msg_flags = 0; + mmsgs[i].msg_hdr.msg_name = NULL; + mmsgs[i].msg_hdr.msg_namelen = 0; + mmsgs[i].msg_hdr.msg_iov = iovs[i]; + mmsgs[i].msg_hdr.msg_iovlen = iovlen; + mmsgs[i].msg_hdr.msg_control = &cmsg_buffers[i]; + mmsgs[i].msg_hdr.msg_controllen = sizeof cmsg_buffers[i]; + mmsgs[i].msg_hdr.msg_flags = 0; } do { @@ -2572,7 +2572,7 @@ exit: static struct tc_police tc_matchall_fill_police(uint32_t kbits_rate, uint32_t kbits_burst) { - unsigned int bsize = MIN(UINT32_MAX / 1024, kbits_burst) * 1024 / 64; + unsigned int bsize = MIN(UINT32_MAX / 1024, kbits_burst) * 1024 / 8; unsigned int bps = ((uint64_t) kbits_rate * 1000) / 8; struct tc_police police; struct tc_ratespec rate; diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c index 72b7915052..7656427845 100644 --- a/lib/netdev-offload-tc.c +++ b/lib/netdev-offload-tc.c @@ -48,6 +48,7 @@ static struct hmap ufid_to_tc = HMAP_INITIALIZER(&ufid_to_tc); static struct hmap tc_to_ufid = HMAP_INITIALIZER(&tc_to_ufid); static bool multi_mask_per_prio = false; static bool block_support = false; +static uint16_t ct_state_support; struct netlink_field { int offset; @@ -676,6 +677,27 @@ parse_tc_flower_to_match(struct tc_flower *flower, ct_statem |= OVS_CS_F_TRACKED; } + if (mask->ct_state & TCA_FLOWER_KEY_CT_FLAGS_REPLY) { + if (key->ct_state & TCA_FLOWER_KEY_CT_FLAGS_REPLY) { + ct_statev |= OVS_CS_F_REPLY_DIR; + } + ct_statem |= OVS_CS_F_REPLY_DIR; + } + + if (mask->ct_state & TCA_FLOWER_KEY_CT_FLAGS_INVALID) { + if (key->ct_state & TCA_FLOWER_KEY_CT_FLAGS_INVALID) { + ct_statev |= OVS_CS_F_INVALID; + } + ct_statem |= OVS_CS_F_INVALID; + } + + if (mask->ct_state & TCA_FLOWER_KEY_CT_FLAGS_RELATED) { + if (key->ct_state & TCA_FLOWER_KEY_CT_FLAGS_RELATED) { + ct_statev |= OVS_CS_F_RELATED; + } + ct_statem |= OVS_CS_F_RELATED; + } + match_set_ct_state_masked(match, ct_statev, ct_statem); } @@ -1406,6 +1428,90 @@ flower_match_to_tun_opt(struct tc_flower *flower, const struct flow_tnl *tnl, flower->mask.tunnel.metadata.present.len = tnl->metadata.present.len; } +static void +parse_match_ct_state_to_flower(struct tc_flower *flower, struct match *match) +{ + const struct flow *key = &match->flow; + struct flow *mask = &match->wc.masks; + + if (!ct_state_support) { + return; + } + + if ((ct_state_support & mask->ct_state) == mask->ct_state) { + if (mask->ct_state & OVS_CS_F_NEW) { + if (key->ct_state & OVS_CS_F_NEW) { + flower->key.ct_state |= TCA_FLOWER_KEY_CT_FLAGS_NEW; + } + flower->mask.ct_state |= TCA_FLOWER_KEY_CT_FLAGS_NEW; + mask->ct_state &= ~OVS_CS_F_NEW; + } + + if (mask->ct_state & OVS_CS_F_ESTABLISHED) { + if (key->ct_state & OVS_CS_F_ESTABLISHED) { + flower->key.ct_state |= TCA_FLOWER_KEY_CT_FLAGS_ESTABLISHED; + } + flower->mask.ct_state |= TCA_FLOWER_KEY_CT_FLAGS_ESTABLISHED; + mask->ct_state &= ~OVS_CS_F_ESTABLISHED; + } + + if (mask->ct_state & OVS_CS_F_TRACKED) { + if (key->ct_state & OVS_CS_F_TRACKED) { + flower->key.ct_state |= TCA_FLOWER_KEY_CT_FLAGS_TRACKED; + } + flower->mask.ct_state |= TCA_FLOWER_KEY_CT_FLAGS_TRACKED; + mask->ct_state &= ~OVS_CS_F_TRACKED; + } + + if (mask->ct_state & OVS_CS_F_REPLY_DIR) { + if (key->ct_state & OVS_CS_F_REPLY_DIR) { + flower->key.ct_state |= TCA_FLOWER_KEY_CT_FLAGS_REPLY; + } + flower->mask.ct_state |= TCA_FLOWER_KEY_CT_FLAGS_REPLY; + mask->ct_state &= ~OVS_CS_F_REPLY_DIR; + } + + if (mask->ct_state & OVS_CS_F_INVALID) { + if (key->ct_state & OVS_CS_F_INVALID) { + flower->key.ct_state |= TCA_FLOWER_KEY_CT_FLAGS_INVALID; + } + flower->mask.ct_state |= TCA_FLOWER_KEY_CT_FLAGS_INVALID; + mask->ct_state &= ~OVS_CS_F_INVALID; + } + + if (mask->ct_state & OVS_CS_F_RELATED) { + if (key->ct_state & OVS_CS_F_RELATED) { + flower->key.ct_state |= TCA_FLOWER_KEY_CT_FLAGS_RELATED; + } + flower->mask.ct_state |= TCA_FLOWER_KEY_CT_FLAGS_RELATED; + mask->ct_state &= ~OVS_CS_F_RELATED; + } + + if (flower->key.ct_state & TCA_FLOWER_KEY_CT_FLAGS_ESTABLISHED) { + flower->key.ct_state &= ~(TCA_FLOWER_KEY_CT_FLAGS_NEW); + flower->mask.ct_state &= ~(TCA_FLOWER_KEY_CT_FLAGS_NEW); + } + } + + if (mask->ct_zone) { + flower->key.ct_zone = key->ct_zone; + flower->mask.ct_zone = mask->ct_zone; + mask->ct_zone = 0; + } + + if (mask->ct_mark) { + flower->key.ct_mark = key->ct_mark; + flower->mask.ct_mark = mask->ct_mark; + mask->ct_mark = 0; + } + + if (!ovs_u128_is_zero(mask->ct_label)) { + flower->key.ct_label = key->ct_label; + flower->mask.ct_label = mask->ct_label; + mask->ct_label = OVS_U128_ZERO; + } +} + static int netdev_tc_flow_put(struct netdev *netdev, struct match *match, struct nlattr *actions, size_t actions_len, @@ -1650,54 +1756,7 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match, } } - if (mask->ct_state) { - if (mask->ct_state & OVS_CS_F_NEW) { - if (key->ct_state & OVS_CS_F_NEW) { - flower.key.ct_state |= TCA_FLOWER_KEY_CT_FLAGS_NEW; - } - flower.mask.ct_state |= TCA_FLOWER_KEY_CT_FLAGS_NEW; - mask->ct_state &= ~OVS_CS_F_NEW; - } - - if (mask->ct_state & OVS_CS_F_ESTABLISHED) { - if (key->ct_state & OVS_CS_F_ESTABLISHED) { - flower.key.ct_state |= TCA_FLOWER_KEY_CT_FLAGS_ESTABLISHED; - } - flower.mask.ct_state |= TCA_FLOWER_KEY_CT_FLAGS_ESTABLISHED; - mask->ct_state &= ~OVS_CS_F_ESTABLISHED; - } - - if (mask->ct_state & OVS_CS_F_TRACKED) { - if (key->ct_state & OVS_CS_F_TRACKED) { - flower.key.ct_state |= TCA_FLOWER_KEY_CT_FLAGS_TRACKED; - } - flower.mask.ct_state |= TCA_FLOWER_KEY_CT_FLAGS_TRACKED; - mask->ct_state &= ~OVS_CS_F_TRACKED; - } - - if (flower.key.ct_state & TCA_FLOWER_KEY_CT_FLAGS_ESTABLISHED) { - flower.key.ct_state &= ~(TCA_FLOWER_KEY_CT_FLAGS_NEW); - flower.mask.ct_state &= ~(TCA_FLOWER_KEY_CT_FLAGS_NEW); - } - } - - if (mask->ct_zone) { - flower.key.ct_zone = key->ct_zone; - flower.mask.ct_zone = mask->ct_zone; - mask->ct_zone = 0; - } - - if (mask->ct_mark) { - flower.key.ct_mark = key->ct_mark; - flower.mask.ct_mark = mask->ct_mark; - mask->ct_mark = 0; - } - - if (!ovs_u128_is_zero(mask->ct_label)) { - flower.key.ct_label = key->ct_label; - flower.mask.ct_label = mask->ct_label; - mask->ct_label = OVS_U128_ZERO; - } + parse_match_ct_state_to_flower(&flower, match); /* ignore exact match on skb_mark of 0. */ if (mask->pkt_mark == UINT32_MAX && !key->pkt_mark) { @@ -1779,6 +1838,10 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match, const struct nlattr *ct = nl_attr_get(nla); const size_t ct_len = nl_attr_get_size(nla); + if (!ct_state_support) { + return -EOPNOTSUPP; + } + err = parse_put_flow_ct_action(&flower, action, ct, ct_len); if (err) { return err; @@ -1971,6 +2034,96 @@ out: tc_add_del_qdisc(ifindex, false, block_id, TC_INGRESS); } + +static int +probe_insert_ct_state_rule(int ifindex, uint16_t ct_state, struct tcf_id *id) +{ + int prio = TC_RESERVED_PRIORITY_MAX + 1; + struct tc_flower flower; + + memset(&flower, 0, sizeof flower); + flower.key.ct_state = ct_state; + flower.mask.ct_state = ct_state; + flower.tc_policy = TC_POLICY_SKIP_HW; + flower.key.eth_type = htons(ETH_P_IP); + flower.mask.eth_type = OVS_BE16_MAX; + + *id = tc_make_tcf_id(ifindex, 0, prio, TC_INGRESS); + return tc_replace_flower(id, &flower); +} + +static void +probe_ct_state_support(int ifindex) +{ + struct tc_flower flower; + uint16_t ct_state; + struct tcf_id id; + int error; + + error = tc_add_del_qdisc(ifindex, true, 0, TC_INGRESS); + if (error) { + return; + } + + /* Test for base ct_state match support */ + ct_state = TCA_FLOWER_KEY_CT_FLAGS_NEW | TCA_FLOWER_KEY_CT_FLAGS_TRACKED; + error = probe_insert_ct_state_rule(ifindex, ct_state, &id); + if (error) { + goto out; + } + + error = tc_get_flower(&id, &flower); + if (error || flower.mask.ct_state != ct_state) { + goto out_del; + } + + tc_del_filter(&id); + ct_state_support = OVS_CS_F_NEW | + OVS_CS_F_ESTABLISHED | + OVS_CS_F_TRACKED | + OVS_CS_F_RELATED; + + /* Test for reject, ct_state >= MAX */ + ct_state = ~0; + error = probe_insert_ct_state_rule(ifindex, ct_state, &id); + if (!error) { + /* No reject, can't continue probing other flags */ + goto out_del; + } + + tc_del_filter(&id); + + /* Test for ct_state INVALID support */ + memset(&flower, 0, sizeof flower); + ct_state = TCA_FLOWER_KEY_CT_FLAGS_TRACKED | + TCA_FLOWER_KEY_CT_FLAGS_INVALID; + error = probe_insert_ct_state_rule(ifindex, ct_state, &id); + if (error) { + goto out; + } + + tc_del_filter(&id); + ct_state_support |= OVS_CS_F_INVALID; + + /* Test for ct_state REPLY support */ + memset(&flower, 0, sizeof flower); + ct_state = TCA_FLOWER_KEY_CT_FLAGS_TRACKED | + TCA_FLOWER_KEY_CT_FLAGS_ESTABLISHED | + TCA_FLOWER_KEY_CT_FLAGS_REPLY; + error = probe_insert_ct_state_rule(ifindex, ct_state, &id); + if (error) { + goto out; + } + + ct_state_support |= OVS_CS_F_REPLY_DIR; + +out_del: + tc_del_filter(&id); +out: + tc_add_del_qdisc(ifindex, false, 0, TC_INGRESS); + VLOG_INFO("probe tc: supported ovs ct_state bits: 0x%x", ct_state_support); +} + static void probe_tc_block_support(int ifindex) { @@ -2038,6 +2191,7 @@ netdev_tc_init_flow_api(struct netdev *netdev) block_id = get_block_id_from_netdev(netdev); probe_multi_mask_per_prio(ifindex); + probe_ct_state_support(ifindex); ovsthread_once_done(&once); } diff --git a/lib/odp-util.c b/lib/odp-util.c index a8598d52af..e1199d1da6 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -3189,17 +3189,17 @@ tun_key_to_attr(struct ofpbuf *a, const struct flow_tnl *tun_key, if ((!tnl_type || !strcmp(tnl_type, "erspan") || !strcmp(tnl_type, "ip6erspan")) && (tun_key->erspan_ver == 1 || tun_key->erspan_ver == 2)) { - struct erspan_metadata opts; + struct erspan_metadata *opts; - opts.version = tun_key->erspan_ver; - if (opts.version == 1) { - opts.u.index = htonl(tun_key->erspan_idx); + opts = nl_msg_put_unspec_zero(a, OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS, + sizeof *opts); + opts->version = tun_key->erspan_ver; + if (opts->version == 1) { + opts->u.index = htonl(tun_key->erspan_idx); } else { - opts.u.md2.dir = tun_key->erspan_dir; - set_hwid(&opts.u.md2, tun_key->erspan_hwid); + opts->u.md2.dir = tun_key->erspan_dir; + set_hwid(&opts->u.md2, tun_key->erspan_hwid); } - nl_msg_put_unspec(a, OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS, - &opts, sizeof(opts)); } if ((!tnl_type || !strcmp(tnl_type, "gtpu")) && diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c index e2e829772a..0342a228b7 100644 --- a/lib/ofp-actions.c +++ b/lib/ofp-actions.c @@ -4431,6 +4431,7 @@ decode_NXAST_RAW_ENCAP(const struct nx_action_encap *nae, { struct ofpact_encap *encap; const struct ofp_ed_prop_header *ofp_prop; + const size_t encap_ofs = out->size; size_t props_len; uint16_t n_props = 0; int err; @@ -4458,6 +4459,7 @@ decode_NXAST_RAW_ENCAP(const struct nx_action_encap *nae, } n_props++; } + encap = ofpbuf_at_assert(out, encap_ofs, sizeof *encap); encap->n_props = n_props; out->header = &encap->ofpact; ofpact_finish_ENCAP(out, &encap); diff --git a/lib/ofp-group.c b/lib/ofp-group.c index bf0f8af544..737f48047b 100644 --- a/lib/ofp-group.c +++ b/lib/ofp-group.c @@ -64,7 +64,7 @@ ofputil_group_from_string(const char *s, uint32_t *group_idp) void ofputil_format_group(uint32_t group_id, struct ds *s) { - char name[MAX_GROUP_NAME_LEN]; + char name[MAX_GROUP_NAME_LEN + 1]; ofputil_group_to_string(group_id, name, sizeof name); ds_put_cstr(s, name); diff --git a/lib/ovsdb-cs.c b/lib/ovsdb-cs.c index ff8adaefb5..6f9f912ac4 100644 --- a/lib/ovsdb-cs.c +++ b/lib/ovsdb-cs.c @@ -1367,7 +1367,7 @@ ovsdb_cs_send_transaction(struct ovsdb_cs *cs, struct json *operations) sizeof *cs->txns); } cs->txns[cs->n_txns++] = request_id; - return request_id; + return json_clone(request_id); } /* Makes 'cs' drop its record of transaction 'request_id'. If a reply arrives @@ -1380,6 +1380,7 @@ ovsdb_cs_forget_transaction(struct ovsdb_cs *cs, const struct json *request_id) { for (size_t i = 0; i < cs->n_txns; i++) { if (json_equal(request_id, cs->txns[i])) { + json_destroy(cs->txns[i]); cs->txns[i] = cs->txns[--cs->n_txns]; return true; } diff --git a/lib/ovsdb-idl.c b/lib/ovsdb-idl.c index 2c8a0c9cfe..1d385ca2fe 100644 --- a/lib/ovsdb-idl.c +++ b/lib/ovsdb-idl.c @@ -92,6 +92,9 @@ struct ovsdb_idl { struct ovsdb_idl_txn *txn; struct hmap outstanding_txns; bool verify_write_only; + struct ovs_list deleted_untracked_rows; /* Stores rows deleted in the + * current run, that are not yet + * added to the track_list. */ }; static struct ovsdb_cs_ops ovsdb_idl_cs_ops; @@ -144,6 +147,7 @@ static bool ovsdb_idl_modify_row(struct ovsdb_idl_row *, const struct shash *values, bool xor); static void ovsdb_idl_parse_update(struct ovsdb_idl *, const struct ovsdb_cs_update_event *); +static void ovsdb_idl_reparse_deleted(struct ovsdb_idl *); static void ovsdb_idl_txn_process_reply(struct ovsdb_idl *, const struct jsonrpc_msg *); @@ -163,6 +167,10 @@ static void ovsdb_idl_row_unparse(struct ovsdb_idl_row *); static void ovsdb_idl_row_clear_old(struct ovsdb_idl_row *); static void ovsdb_idl_row_clear_new(struct ovsdb_idl_row *); static void ovsdb_idl_row_clear_arcs(struct ovsdb_idl_row *, bool destroy_dsts); +static void ovsdb_idl_row_reparse_backrefs(struct ovsdb_idl_row *); +static void ovsdb_idl_row_track_change(struct ovsdb_idl_row *, + enum ovsdb_idl_change); +static void ovsdb_idl_row_untrack_change(struct ovsdb_idl_row *); static void ovsdb_idl_txn_abort_all(struct ovsdb_idl *); static bool ovsdb_idl_txn_extract_mutations(struct ovsdb_idl_row *, @@ -182,7 +190,6 @@ ovsdb_idl_table_from_class(const struct ovsdb_idl *, static struct ovsdb_idl_table * ovsdb_idl_table_from_class(const struct ovsdb_idl *, const struct ovsdb_idl_table_class *); -static bool ovsdb_idl_track_is_set(struct ovsdb_idl_table *table); static void ovsdb_idl_track_clear__(struct ovsdb_idl *, bool flush_all); static void ovsdb_idl_destroy_indexes(struct ovsdb_idl_table *); @@ -191,6 +198,8 @@ static void ovsdb_idl_remove_from_indexes(const struct ovsdb_idl_row *); static int ovsdb_idl_try_commit_loop_txn(struct ovsdb_idl_loop *loop, bool *may_need_wakeup); +static void add_tracked_change_for_references(struct ovsdb_idl_row *); + /* Creates and returns a connection to database 'remote', which should be in a * form acceptable to jsonrpc_session_open(). The connection will maintain an * in-memory replica of the remote database whose schema is described by @@ -249,6 +258,8 @@ ovsdb_idl_create_unconnected(const struct ovsdb_idl_class *class, .txn = NULL, .outstanding_txns = HMAP_INITIALIZER(&idl->outstanding_txns), .verify_write_only = false, + .deleted_untracked_rows + = OVS_LIST_INITIALIZER(&idl->deleted_untracked_rows), }; uint8_t default_mode = (monitor_everything_by_default @@ -352,6 +363,14 @@ ovsdb_idl_set_leader_only(struct ovsdb_idl *idl, bool leader_only) static void ovsdb_idl_clear(struct ovsdb_idl *db) { + /* Process deleted rows, removing them from the 'deleted_untracked_rows' + * list and reparsing their backrefs. + */ + ovsdb_idl_reparse_deleted(db); + + /* Cleanup all rows; each row gets added to its own table's + * 'track_list'. + */ for (size_t i = 0; i < db->class_->n_tables; i++) { struct ovsdb_idl_table *table = &db->tables[i]; struct ovsdb_idl_row *row, *next_row; @@ -368,17 +387,26 @@ ovsdb_idl_clear(struct ovsdb_idl *db) ovsdb_idl_row_unparse(row); } LIST_FOR_EACH_SAFE (arc, next_arc, src_node, &row->src_arcs) { + ovs_list_remove(&arc->src_node); + ovs_list_remove(&arc->dst_node); + free(arc); + } + LIST_FOR_EACH_SAFE (arc, next_arc, dst_node, &row->dst_arcs) { + ovs_list_remove(&arc->src_node); + ovs_list_remove(&arc->dst_node); free(arc); } - /* No need to do anything with dst_arcs: some node has those arcs - * as forward arcs and will destroy them itself. */ ovsdb_idl_row_destroy(row); } } + + /* Free rows deleted from tables with change tracking disabled. */ ovsdb_idl_row_destroy_postprocess(db); + /* Free rows deleted from tables with change tracking enabled. */ ovsdb_idl_track_clear__(db, true); + ovs_assert(ovs_list_is_empty(&db->deleted_untracked_rows)); db->change_seqno++; } @@ -416,7 +444,7 @@ ovsdb_idl_run(struct ovsdb_idl *idl) } ovsdb_cs_event_destroy(event); } - + ovsdb_idl_reparse_deleted(idl); ovsdb_idl_row_destroy_postprocess(idl); } @@ -1140,7 +1168,7 @@ ovsdb_idl_track_add_all(struct ovsdb_idl *idl) } /* Returns true if 'table' has any tracked column. */ -static bool +bool ovsdb_idl_track_is_set(struct ovsdb_idl_table *table) { size_t i; @@ -1227,13 +1255,8 @@ ovsdb_idl_track_clear__(struct ovsdb_idl *idl, bool flush_all) free(row->updated); row->updated = NULL; } + ovsdb_idl_row_untrack_change(row); - row->change_seqno[OVSDB_IDL_CHANGE_INSERT] = - row->change_seqno[OVSDB_IDL_CHANGE_MODIFY] = - row->change_seqno[OVSDB_IDL_CHANGE_DELETE] = 0; - - ovs_list_remove(&row->track_node); - ovs_list_init(&row->track_node); if (ovsdb_idl_row_is_orphan(row)) { ovsdb_idl_row_unparse(row); if (row->tracked_old_datum) { @@ -1351,6 +1374,33 @@ ovsdb_idl_parse_update(struct ovsdb_idl *idl, } } +/* Reparses references to rows that have been deleted in the current IDL run. + * + * To ensure that reference sources that are deleted are not reparsed, + * this function must be called after all updates have been processed in + * the current IDL run, i.e., after all calls to ovsdb_idl_parse_update(). + */ +static void +ovsdb_idl_reparse_deleted(struct ovsdb_idl *db) +{ + struct ovsdb_idl_row *row, *next; + + LIST_FOR_EACH_SAFE (row, next, track_node, &db->deleted_untracked_rows) { + ovsdb_idl_row_untrack_change(row); + add_tracked_change_for_references(row); + ovsdb_idl_row_reparse_backrefs(row); + + /* Orphan rows that are still unreferenced or are part of tables that + * have change tracking enabled should be added to their table's + * 'track_list'. + */ + if (ovs_list_is_empty(&row->dst_arcs) + || ovsdb_idl_track_is_set(row->table)) { + ovsdb_idl_row_track_change(row, OVSDB_IDL_CHANGE_DELETE); + } + } +} + static struct ovsdb_idl_row * ovsdb_idl_get_row(struct ovsdb_idl_table *table, const struct uuid *uuid) { @@ -1404,6 +1454,7 @@ ovsdb_idl_process_update(struct ovsdb_idl_table *table, ovsdb_idl_insert_row(ovsdb_idl_row_create(table, uuid), ru->columns); } else if (ovsdb_idl_row_is_orphan(row)) { + ovsdb_idl_row_untrack_change(row); ovsdb_idl_insert_row(row, ru->columns); } else { VLOG_ERR_RL(&semantic_rl, "cannot add existing row "UUID_FMT" to " @@ -1451,13 +1502,8 @@ add_tracked_change_for_references(struct ovsdb_idl_row *row) if (ovs_list_is_empty(&ref->track_node) && ovsdb_idl_track_is_set(ref->table)) { - ovs_list_push_back(&ref->table->track_list, - &ref->track_node); - - ref->change_seqno[OVSDB_IDL_CHANGE_MODIFY] - = ref->table->change_seqno[OVSDB_IDL_CHANGE_MODIFY] - = ref->table->idl->change_seqno + 1; + ovsdb_idl_row_track_change(ref, OVSDB_IDL_CHANGE_MODIFY); add_tracked_change_for_references(ref); } } @@ -2023,6 +2069,32 @@ ovsdb_idl_row_reparse_backrefs(struct ovsdb_idl_row *row) } } +static void +ovsdb_idl_row_track_change(struct ovsdb_idl_row *row, + enum ovsdb_idl_change change) +{ + row->change_seqno[change] + = row->table->change_seqno[change] + = row->table->idl->change_seqno + 1; + if (ovs_list_is_empty(&row->track_node)) { + ovs_list_push_back(&row->table->track_list, &row->track_node); + } +} + +static void +ovsdb_idl_row_untrack_change(struct ovsdb_idl_row *row) +{ + if (ovs_list_is_empty(&row->track_node)) { + return; + } + + row->change_seqno[OVSDB_IDL_CHANGE_INSERT] = + row->change_seqno[OVSDB_IDL_CHANGE_MODIFY] = + row->change_seqno[OVSDB_IDL_CHANGE_DELETE] = 0; + ovs_list_remove(&row->track_node); + ovs_list_init(&row->track_node); +} + static struct ovsdb_idl_row * ovsdb_idl_row_create__(const struct ovsdb_idl_table_class *class) { @@ -2049,22 +2121,26 @@ ovsdb_idl_row_create(struct ovsdb_idl_table *table, const struct uuid *uuid) return row; } +/* If 'row' is not referenced anymore, removes 'row' from the table hmap, + * clears the old datum and adds 'row' to the table's track_list. + * + * If 'row' is still referenced, i.e., became "orphan", queues 'row' for + * reparsing after all updates have been processed by adding it to the + * 'deleted_untracked_rows' list. + */ static void ovsdb_idl_row_destroy(struct ovsdb_idl_row *row) { - if (row) { - ovsdb_idl_row_clear_old(row); + ovsdb_idl_row_clear_old(row); + if (ovs_list_is_empty(&row->dst_arcs)) { hmap_remove(&row->table->rows, &row->hmap_node); ovsdb_idl_destroy_all_map_op_lists(row); ovsdb_idl_destroy_all_set_op_lists(row); - if (ovsdb_idl_track_is_set(row->table)) { - row->change_seqno[OVSDB_IDL_CHANGE_DELETE] - = row->table->change_seqno[OVSDB_IDL_CHANGE_DELETE] - = row->table->idl->change_seqno + 1; - } - if (ovs_list_is_empty(&row->track_node)) { - ovs_list_push_back(&row->table->track_list, &row->track_node); - } + ovsdb_idl_row_track_change(row, OVSDB_IDL_CHANGE_DELETE); + } else { + ovsdb_idl_row_untrack_change(row); + ovs_list_push_back(&row->table->idl->deleted_untracked_rows, + &row->track_node); } } @@ -2154,12 +2230,7 @@ ovsdb_idl_delete_row(struct ovsdb_idl_row *row) { ovsdb_idl_remove_from_indexes(row); ovsdb_idl_row_clear_arcs(row, true); - ovsdb_idl_row_clear_old(row); - if (ovs_list_is_empty(&row->dst_arcs)) { - ovsdb_idl_row_destroy(row); - } else { - ovsdb_idl_row_reparse_backrefs(row); - } + ovsdb_idl_row_destroy(row); } /* Returns true if a column with mode OVSDB_IDL_MODE_RW changed, false diff --git a/lib/ovsdb-idl.h b/lib/ovsdb-idl.h index 05bb48d66c..d93483245e 100644 --- a/lib/ovsdb-idl.h +++ b/lib/ovsdb-idl.h @@ -53,6 +53,7 @@ struct ovsdb_datum; struct ovsdb_idl_class; struct ovsdb_idl_row; struct ovsdb_idl_column; +struct ovsdb_idl_table; struct ovsdb_idl_table_class; struct uuid; @@ -217,6 +218,7 @@ unsigned int ovsdb_idl_row_get_seqno( void ovsdb_idl_track_add_column(struct ovsdb_idl *idl, const struct ovsdb_idl_column *column); void ovsdb_idl_track_add_all(struct ovsdb_idl *idl); +bool ovsdb_idl_track_is_set(struct ovsdb_idl_table *table); const struct ovsdb_idl_row *ovsdb_idl_track_get_first( const struct ovsdb_idl *, const struct ovsdb_idl_table_class *); const struct ovsdb_idl_row *ovsdb_idl_track_get_next(const struct ovsdb_idl_row *); diff --git a/ofproto/connmgr.c b/ofproto/connmgr.c index 9c5c633b41..fa8f6cd0e8 100644 --- a/ofproto/connmgr.c +++ b/ofproto/connmgr.c @@ -2140,7 +2140,7 @@ ofmonitor_report(struct connmgr *mgr, struct rule *rule, const struct rule_actions *old_actions) OVS_REQUIRES(ofproto_mutex) { - if (rule_is_hidden(rule)) { + if (!mgr || rule_is_hidden(rule)) { return; } @@ -2244,6 +2244,10 @@ ofmonitor_flush(struct connmgr *mgr) { struct ofconn *ofconn; + if (!mgr) { + return; + } + LIST_FOR_EACH (ofconn, connmgr_node, &mgr->conns) { struct rconn_packet_counter *counter = ofconn->monitor_counter; diff --git a/ofproto/ofproto-dpif-sflow.c b/ofproto/ofproto-dpif-sflow.c index fdcb9eabbf..864c136b5d 100644 --- a/ofproto/ofproto-dpif-sflow.c +++ b/ofproto/ofproto-dpif-sflow.c @@ -1292,10 +1292,10 @@ dpif_sflow_received(struct dpif_sflow *ds, const struct dp_packet *packet, ovs_be16 vlan_tci; ovs_mutex_lock(&mutex); - sampler = ds->sflow_agent->samplers; - if (!sampler) { + if (!ds->sflow_agent || !ds->sflow_agent->samplers) { goto out; } + sampler = ds->sflow_agent->samplers; /* Build a flow sample. */ memset(&fs, 0, sizeof fs); diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c index 5fae46adfc..ccf97266c0 100644 --- a/ofproto/ofproto-dpif-upcall.c +++ b/ofproto/ofproto-dpif-upcall.c @@ -491,6 +491,11 @@ udpif_destroy(struct udpif *udpif) dpif_register_upcall_cb(udpif->dpif, NULL, udpif); for (int i = 0; i < N_UMAPS; i++) { + struct udpif_key *ukey; + + CMAP_FOR_EACH (ukey, cmap_node, &udpif->ukeys[i].cmap) { + ukey_delete__(ukey); + } cmap_destroy(&udpif->ukeys[i].cmap); ovs_mutex_destroy(&udpif->ukeys[i].mutex); } diff --git a/ovsdb/ovsdb-client.c b/ovsdb/ovsdb-client.c index 72756eb1f2..ba28e36d78 100644 --- a/ovsdb/ovsdb-client.c +++ b/ovsdb/ovsdb-client.c @@ -1664,14 +1664,15 @@ static void do_needs_conversion(struct jsonrpc *rpc, const char *database_ OVS_UNUSED, int argc OVS_UNUSED, char *argv[]) { + const char *schema_file_name = argv[argc - 1]; struct ovsdb_schema *schema1; - check_ovsdb_error(ovsdb_schema_from_file(argv[0], &schema1)); + check_ovsdb_error(ovsdb_schema_from_file(schema_file_name, &schema1)); char *database = schema1->name; open_rpc(1, NEED_DATABASE, argc, argv, &rpc, &database); if (is_database_clustered(rpc, database)) { - ovsdb_schema_persist_ephemeral_columns(schema1, argv[0]); + ovsdb_schema_persist_ephemeral_columns(schema1, schema_file_name); } struct ovsdb_schema *schema2 = fetch_schema(rpc, schema1->name); diff --git a/ovsdb/raft.c b/ovsdb/raft.c index ea91d1fdba..192f7f0a96 100644 --- a/ovsdb/raft.c +++ b/ovsdb/raft.c @@ -940,6 +940,34 @@ raft_reset_ping_timer(struct raft *raft) raft->ping_timeout = time_msec() + raft->election_timer / 3; } +static void +raft_conn_update_probe_interval(struct raft *raft, struct raft_conn *r_conn) +{ + /* Inactivity probe will be sent if connection will remain idle for the + * time of an election timeout. Connection will be dropped if inactivity + * will last twice that time. + * + * It's not enough to just have heartbeats if connection is still + * established, but no packets received from the other side. Without + * inactivity probe follower will just try to initiate election + * indefinitely staying in 'candidate' role. And the leader will continue + * to send heartbeats to the dead connection thinking that remote server + * is still part of the cluster. */ + int probe_interval = raft->election_timer + ELECTION_RANGE_MSEC; + + jsonrpc_session_set_probe_interval(r_conn->js, probe_interval); +} + +static void +raft_update_probe_intervals(struct raft *raft) +{ + struct raft_conn *r_conn; + + LIST_FOR_EACH (r_conn, list_node, &raft->conns) { + raft_conn_update_probe_interval(raft, r_conn); + } +} + static void raft_add_conn(struct raft *raft, struct jsonrpc_session *js, const struct uuid *sid, bool incoming) @@ -954,7 +982,7 @@ raft_add_conn(struct raft *raft, struct jsonrpc_session *js, &conn->sid); conn->incoming = incoming; conn->js_seqno = jsonrpc_session_get_seqno(conn->js); - jsonrpc_session_set_probe_interval(js, 0); + raft_conn_update_probe_interval(raft, conn); jsonrpc_session_set_backlog_threshold(js, raft->conn_backlog_max_n_msgs, raft->conn_backlog_max_n_bytes); } @@ -2804,6 +2832,7 @@ raft_update_commit_index(struct raft *raft, uint64_t new_commit_index) raft->election_timer, e->election_timer); raft->election_timer = e->election_timer; raft->election_timer_new = 0; + raft_update_probe_intervals(raft); } if (e->servers) { /* raft_run_reconfigure() can write a new Raft entry, which can @@ -2820,6 +2849,7 @@ raft_update_commit_index(struct raft *raft, uint64_t new_commit_index) VLOG_INFO("Election timer changed from %"PRIu64" to %"PRIu64, raft->election_timer, e->election_timer); raft->election_timer = e->election_timer; + raft_update_probe_intervals(raft); } } /* Check if any pending command can be completed, and complete it. @@ -4468,6 +4498,8 @@ raft_unixctl_status(struct unixctl_conn *conn, : raft->leaving ? "leaving cluster" : raft->left ? "left cluster" : raft->failed ? "failed" + : raft->candidate_retrying + ? "disconnected from the cluster (election timeout)" : "cluster member"); if (raft->joining) { ds_put_format(&s, "Remotes for joining:"); diff --git a/python/ovs/db/idl.py b/python/ovs/db/idl.py index 5850ac7abf..4226d1cb2f 100644 --- a/python/ovs/db/idl.py +++ b/python/ovs/db/idl.py @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import collections import functools import uuid @@ -39,6 +40,10 @@ OVSDB_UPDATE2 = 1 CLUSTERED = "clustered" +Notice = collections.namedtuple('Notice', ('event', 'row', 'updates')) +Notice.__new__.__defaults__ = (None,) # default updates=None + + class Idl(object): """Open vSwitch Database Interface Definition Language (OVSDB IDL). @@ -614,6 +619,7 @@ class Idl(object): raise error.Error(" is not an object", table_updates) + notices = [] for table_name, table_update in table_updates.items(): table = tables.get(table_name) if not table: @@ -639,7 +645,9 @@ class Idl(object): % (table_name, uuid_string)) if version == OVSDB_UPDATE2: - if self.__process_update2(table, uuid, row_update): + changes = self.__process_update2(table, uuid, row_update) + if changes: + notices.append(changes) self.change_seqno += 1 continue @@ -652,17 +660,20 @@ class Idl(object): raise error.Error(' missing "old" and ' '"new" members', row_update) - if self.__process_update(table, uuid, old, new): + changes = self.__process_update(table, uuid, old, new) + if changes: + notices.append(changes) self.change_seqno += 1 + for notice in notices: + self.notify(*notice) def __process_update2(self, table, uuid, row_update): + """Returns Notice if a column changed, False otherwise.""" row = table.rows.get(uuid) - changed = False if "delete" in row_update: if row: del table.rows[uuid] - self.notify(ROW_DELETE, row) - changed = True + return Notice(ROW_DELETE, row) else: # XXX rate-limit vlog.warn("cannot delete missing row %s from table" @@ -681,29 +692,27 @@ class Idl(object): changed = self.__row_update(table, row, row_update) table.rows[uuid] = row if changed: - self.notify(ROW_CREATE, row) + return Notice(ROW_CREATE, row) elif "modify" in row_update: if not row: raise error.Error('Modify non-existing row') old_row = self.__apply_diff(table, row, row_update['modify']) - self.notify(ROW_UPDATE, row, Row(self, table, uuid, old_row)) - changed = True + return Notice(ROW_UPDATE, row, Row(self, table, uuid, old_row)) else: raise error.Error(' unknown operation', row_update) - return changed + return False def __process_update(self, table, uuid, old, new): - """Returns True if a column changed, False otherwise.""" + """Returns Notice if a column changed, False otherwise.""" row = table.rows.get(uuid) changed = False if not new: # Delete row. if row: del table.rows[uuid] - changed = True - self.notify(ROW_DELETE, row) + return Notice(ROW_DELETE, row) else: # XXX rate-limit vlog.warn("cannot delete missing row %s from table %s" @@ -723,7 +732,7 @@ class Idl(object): if op == ROW_CREATE: table.rows[uuid] = row if changed: - self.notify(ROW_CREATE, row) + return Notice(ROW_CREATE, row) else: op = ROW_UPDATE if not row: @@ -737,8 +746,8 @@ class Idl(object): if op == ROW_CREATE: table.rows[uuid] = row if changed: - self.notify(op, row, Row.from_json(self, table, uuid, old)) - return changed + return Notice(op, row, Row.from_json(self, table, uuid, old)) + return False def __check_server_db(self): """Returns True if this is a valid server database, False otherwise.""" diff --git a/tests/atlocal.in b/tests/atlocal.in index 02e2dc57f2..cfca7e1926 100644 --- a/tests/atlocal.in +++ b/tests/atlocal.in @@ -175,6 +175,9 @@ find_command() # Set HAVE_NC find_command nc +# Set HAVE_TC +find_command tc + # Determine correct netcat option to quit on stdin EOF if nc --version 2>&1 | grep -q nmap.org; then # Nmap netcat diff --git a/tests/automake.mk b/tests/automake.mk index 677b99a6b4..fc80e027df 100644 --- a/tests/automake.mk +++ b/tests/automake.mk @@ -134,7 +134,8 @@ FUZZ_REGRESSION_TESTS = \ tests/fuzz-regression/ofp_print_fuzzer-5722747668791296 \ tests/fuzz-regression/ofp_print_fuzzer-6285128790704128 \ tests/fuzz-regression/ofp_print_fuzzer-6470117922701312 \ - tests/fuzz-regression/ofp_print_fuzzer-6502620041576448 + tests/fuzz-regression/ofp_print_fuzzer-6502620041576448 \ + tests/fuzz-regression/ofp_print_fuzzer-6540965472632832 $(srcdir)/tests/fuzz-regression-list.at: tests/automake.mk $(AM_V_GEN)for name in $(FUZZ_REGRESSION_TESTS); do \ basename=`echo $$name | sed 's,^.*/,,'`; \ diff --git a/tests/daemon.at b/tests/daemon.at index a7982de381..39d9aa391e 100644 --- a/tests/daemon.at +++ b/tests/daemon.at @@ -218,11 +218,11 @@ OVS_WAIT_UNTIL([test -s ovsdb-server.pid]) OVS_WAIT_UNTIL([sc query ovsdb-server | grep STATE | grep RUNNING > /dev/null 2>&1]) AT_CHECK([kill -0 `cat ovsdb-server.pid`], [0], [ignore]) AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-dbs], [0], -[Open_vSwitch +[_Server ]) AT_CHECK([sc stop ovsdb-server], [0], [ignore]) OVS_WAIT_UNTIL([test ! -s ovsdb-server.pid]) -AT_CHECK([sc query ovsdb-server | grep STATE | grep STOPPED], [0], [ignore]) +OVS_WAIT_UNTIL([sc query ovsdb-server | grep STATE | grep STOPPED > /dev/null 2>&1]) AT_CHECK([sc delete ovsdb-server], [0], [[[SC]] DeleteService SUCCESS ]) AT_CLEANUP diff --git a/tests/dpif-netdev.at b/tests/dpif-netdev.at index 2862a3c9b9..57cae383fe 100644 --- a/tests/dpif-netdev.at +++ b/tests/dpif-netdev.at @@ -299,59 +299,61 @@ type=drop rate=1 burst_size=2 ]) ovs-appctl time/warp 5000 -AT_CHECK([ovs-appctl netdev-dummy/receive p7 'in_port(7),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60]) -AT_CHECK([ovs-appctl netdev-dummy/receive p7 'in_port(7),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60]) -AT_CHECK([ovs-appctl netdev-dummy/receive p7 'in_port(7),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60]) -AT_CHECK([ovs-appctl netdev-dummy/receive p7 'in_port(7),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60]) -AT_CHECK([ovs-appctl netdev-dummy/receive p7 'in_port(7),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60]) -AT_CHECK([ovs-appctl netdev-dummy/receive p8 'in_port(8),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.3,dst=10.0.0.4,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60]) -AT_CHECK([ovs-appctl netdev-dummy/receive p8 'in_port(8),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.3,dst=10.0.0.4,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60]) -AT_CHECK([ovs-appctl netdev-dummy/receive p8 'in_port(8),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.3,dst=10.0.0.4,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60]) -AT_CHECK([ovs-appctl netdev-dummy/receive p8 'in_port(8),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.3,dst=10.0.0.4,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60]) -AT_CHECK([ovs-appctl netdev-dummy/receive p8 'in_port(8),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.3,dst=10.0.0.4,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60]) +for i in `seq 1 7`; do + AT_CHECK( + [ovs-appctl netdev-dummy/receive p7 \ + 'in_port(7),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60]) +done + +for i in `seq 1 5`; do + AT_CHECK( + [ovs-appctl netdev-dummy/receive p8 \ + 'in_port(8),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.3,dst=10.0.0.4,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60]) +done + sleep 1 # wait for forwarders process packets # Meter 1 is measuring packets, allowing one packet per second with -# bursts of one packet, so 4 out of 5 packets should hit the drop +# bursts of one packet, so 3 out of 5 packets should hit the drop # band. -# Meter 2 is measuring kbps, with burst size 2 (== 2000 bits). 4 packets -# (240 bytes == 1920 bits) pass, but the last packet should hit the drop band. +# Meter 2 is measuring kbps, with burst size 2 (== 3000 bits). 6 packets +# (360 bytes == 2880 bits) pass, but the last packet should hit the drop band. AT_CHECK([ovs-ofctl -O OpenFlow13 meter-stats br0 | strip_timers], [0], [dnl OFPST_METER reply (OF1.3) (xid=0x2): meter:1 flow_count:1 packet_in_count:5 byte_in_count:300 duration:0.0s bands: -0: packet_count:4 byte_count:240 +0: packet_count:3 byte_count:180 -meter:2 flow_count:1 packet_in_count:5 byte_in_count:300 duration:0.0s bands: +meter:2 flow_count:1 packet_in_count:7 byte_in_count:420 duration:0.0s bands: 0: packet_count:1 byte_count:60 ]) # Advance time by 1/2 second ovs-appctl time/warp 500 -AT_CHECK([ovs-appctl netdev-dummy/receive p7 'in_port(7),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60]) -AT_CHECK([ovs-appctl netdev-dummy/receive p7 'in_port(7),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60]) -AT_CHECK([ovs-appctl netdev-dummy/receive p7 'in_port(7),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60]) -AT_CHECK([ovs-appctl netdev-dummy/receive p7 'in_port(7),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60]) -AT_CHECK([ovs-appctl netdev-dummy/receive p7 'in_port(7),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60]) -AT_CHECK([ovs-appctl netdev-dummy/receive p8 'in_port(8),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.3,dst=10.0.0.4,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60]) -AT_CHECK([ovs-appctl netdev-dummy/receive p8 'in_port(8),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.3,dst=10.0.0.4,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60]) -AT_CHECK([ovs-appctl netdev-dummy/receive p8 'in_port(8),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.3,dst=10.0.0.4,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60]) -AT_CHECK([ovs-appctl netdev-dummy/receive p8 'in_port(8),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.3,dst=10.0.0.4,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60]) -AT_CHECK([ovs-appctl netdev-dummy/receive p8 'in_port(8),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.3,dst=10.0.0.4,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60]) +for i in `seq 1 5`; do + AT_CHECK( + [ovs-appctl netdev-dummy/receive p7 \ + 'in_port(7),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60]) + + AT_CHECK( + [ovs-appctl netdev-dummy/receive p8 \ + 'in_port(8),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.3,dst=10.0.0.4,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60]) +done + sleep 1 # wait for forwarders process packets # Meter 1 is measuring packets, allowing one packet per second with # bursts of one packet, so all 5 of the new packets should hit the drop # band. -# Meter 2 is measuring kbps, with burst size 2 (== 2000 bits). After 500ms -# there should be space for 80 + 500 bits, so one new 60 byte (480 bit) packet +# Meter 2 is measuring kbps, with burst size 2 (== 3000 bits). After 500ms +# there should be space for 120 + 500 bits, so one new 60 byte (480 bit) packet # should pass, remaining 4 should hit the drop band. AT_CHECK([ovs-ofctl -O OpenFlow13 meter-stats br0 | strip_timers], [0], [dnl OFPST_METER reply (OF1.3) (xid=0x2): meter:1 flow_count:1 packet_in_count:10 byte_in_count:600 duration:0.0s bands: -0: packet_count:9 byte_count:540 +0: packet_count:8 byte_count:480 -meter:2 flow_count:1 packet_in_count:10 byte_in_count:600 duration:0.0s bands: +meter:2 flow_count:1 packet_in_count:12 byte_in_count:720 duration:0.0s bands: 0: packet_count:5 byte_count:300 ]) @@ -360,7 +362,7 @@ ovs-appctl time/warp 5000 AT_CHECK([ ovs-appctl coverage/read-counter datapath_drop_meter ], [0], [dnl -14 +13 ]) AT_CHECK([cat ovs-vswitchd.log | filter_flow_install | strip_xout_keep_actions], [0], [dnl @@ -370,6 +372,8 @@ recirc_id(0),in_port(7),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), a recirc_id(0),in_port(8),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), actions:2 ]) +AT_CHECK([ovs-ofctl -O OpenFlow13 del-meters br0]) + OVS_VSWITCHD_STOP AT_CLEANUP @@ -589,3 +593,20 @@ arp,in_port=ANY,dl_vlan=11,dl_vlan_pcp=7,vlan_tci1=0x0000,dl_src=00:06:07:08:09: DPIF_NETDEV_FLOW_HW_OFFLOAD_OFFSETS_VID_ARP([dummy]) DPIF_NETDEV_FLOW_HW_OFFLOAD_OFFSETS_VID_ARP([dummy-pmd]) + +AT_SETUP([dpif-netdev - check dpctl/add-flow in_port exact match]) +OVS_VSWITCHD_START( + [add-port br0 p1 \ + -- set interface p1 type=dummy options:pstream=punix:$OVS_RUNDIR/p0.sock \ + -- set bridge br0 datapath-type=dummy \ + other-config:datapath-id=1234 fail-mode=secure]) + +AT_CHECK([ovs-appctl dpctl/add-flow "eth(),eth_type(0x0800),ipv4()" "3"], [2], +[], [dnl +ovs-vswitchd: updating flow table (Invalid argument) +ovs-appctl: ovs-vswitchd: server returned an error +]) +OVS_WAIT_UNTIL([grep "flow: in_port is not an exact match" ovs-vswitchd.log]) +OVS_VSWITCHD_STOP(["/flow: in_port is not an exact match/d +/failed to put/d"]) +AT_CLEANUP diff --git a/tests/fuzz-regression-list.at b/tests/fuzz-regression-list.at index e3173fb88f..2347c690ef 100644 --- a/tests/fuzz-regression-list.at +++ b/tests/fuzz-regression-list.at @@ -21,3 +21,4 @@ TEST_FUZZ_REGRESSION([ofp_print_fuzzer-5722747668791296]) TEST_FUZZ_REGRESSION([ofp_print_fuzzer-6285128790704128]) TEST_FUZZ_REGRESSION([ofp_print_fuzzer-6470117922701312]) TEST_FUZZ_REGRESSION([ofp_print_fuzzer-6502620041576448]) +TEST_FUZZ_REGRESSION([ofp_print_fuzzer-6540965472632832]) diff --git a/tests/fuzz-regression/ofp_print_fuzzer-6540965472632832 b/tests/fuzz-regression/ofp_print_fuzzer-6540965472632832 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at index 31064ed95e..24bbd884ca 100644 --- a/tests/ofproto-dpif.at +++ b/tests/ofproto-dpif.at @@ -2123,7 +2123,7 @@ AT_CHECK([ovs-appctl revalidator/purge]) AT_CHECK([ovs-ofctl monitor br0 65534 invalid_ttl -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log]) dnl Add a controller meter. -AT_CHECK([ovs-ofctl -O OpenFlow13 add-meter br0 'meter=controller pktps stats bands=type=drop rate=2']) +AT_CHECK([ovs-ofctl -O OpenFlow13 add-meter br0 'meter=controller pktps burst stats bands=type=drop rate=1 burst_size=1']) dnl Advance time by 1 second. AT_CHECK([ovs-appctl time/warp 1000], [0], [ignore]) diff --git a/tests/ovs-vsctl.at b/tests/ovs-vsctl.at index c8babe3612..1f1fc3c79a 100644 --- a/tests/ovs-vsctl.at +++ b/tests/ovs-vsctl.at @@ -1639,3 +1639,26 @@ AT_CHECK([grep "server name" ovsdb-server.log], [0], OVS_VSCTL_CLEANUP AT_CLEANUP + +dnl ---------------------------------------------------------------------- +AT_BANNER([set ingress policing test]) + +AT_SETUP([set ingress_policing_rate and ingress_policing_burst]) +AT_KEYWORDS([ingress_policing]) +OVS_VSCTL_SETUP +AT_CHECK([RUN_OVS_VSCTL_TOGETHER( + [add-br a], + [add-port a a1], + [set interface a1 ingress_policing_rate=100], + [set interface a1 ingress_policing_burst=10], + [--columns=ingress_policing_burst,ingress_policing_rate list interface a1])], + [0], + [ + + + +ingress_policing_burst: 10 +ingress_policing_rate: 100 +]) +OVS_VSCTL_CLEANUP +AT_CLEANUP diff --git a/tests/ovsdb-client.at b/tests/ovsdb-client.at index 8d777a0275..5e3b26aea8 100644 --- a/tests/ovsdb-client.at +++ b/tests/ovsdb-client.at @@ -12,6 +12,30 @@ AT_CHECK([ovsdb-client get-schema-cksum unix:socket ordinals], [0], [12345678 9 OVSDB_SERVER_SHUTDOWN AT_CLEANUP +AT_SETUP([ovsdb-client needs-conversion (no conversion needed)]) +AT_KEYWORDS([ovsdb client file positive]) +ordinal_schema > schema +touch .db.~lock~ +AT_CHECK([ovsdb-tool create db schema], [0], [], [ignore]) +AT_CHECK([ovsdb-server --detach --no-chdir --pidfile --remote=punix:socket db], [0], [ignore], [ignore]) +AT_CHECK([ovsdb-client needs-conversion unix:socket schema], [0], [no +]) +OVSDB_SERVER_SHUTDOWN +AT_CLEANUP + +AT_SETUP([ovsdb-client needs-conversion (conversion needed)]) +AT_KEYWORDS([ovsdb client file positive]) +ordinal_schema > schema +touch .db.~lock~ +AT_CHECK([ovsdb-tool create db schema], [0], [], [ignore]) +AT_CHECK([ovsdb-server --detach --no-chdir --pidfile --remote=punix:socket db], [0], [ignore], [ignore]) +sed 's/5\.1\.3/5.1.4/' < schema > schema2 +AT_CHECK([diff schema schema2], [1], [ignore]) +AT_CHECK([ovsdb-client needs-conversion unix:socket schema2], [0], [yes +]) +OVSDB_SERVER_SHUTDOWN +AT_CLEANUP + AT_SETUP([ovsdb-client backup and restore]) AT_KEYWORDS([ovsdb client positive]) diff --git a/tests/ovsdb-cluster.at b/tests/ovsdb-cluster.at index 92aa427093..cf43e9cf86 100644 --- a/tests/ovsdb-cluster.at +++ b/tests/ovsdb-cluster.at @@ -128,7 +128,7 @@ ovsdb_test_cluster_disconnect () { "rows": [{"i": 1}]}]]' > test-ovsdb.log 2>&1 & echo $! > test-ovsdb.pid - OVS_WAIT_UNTIL([grep "000: i=1" test-ovsdb.log]) + OVS_WAIT_UNTIL([grep "000: table simple: i=1" test-ovsdb.log]) # Start collecting raft_is_connected logs for $target before shutting down # any servers. diff --git a/tests/ovsdb-idl.at b/tests/ovsdb-idl.at index 4b4791a7da..62181dd4de 100644 --- a/tests/ovsdb-idl.at +++ b/tests/ovsdb-idl.at @@ -141,7 +141,7 @@ m4_define([OVSDB_CHECK_IDL_REGISTER_COLUMNS_PY], AT_CHECK([ovsdb_start_idltest]) m4_if([$2], [], [], [AT_CHECK([ovsdb-client transact unix:socket $2], [0], [ignore], [ignore])]) - AT_CHECK([$PYTHON3 $srcdir/test-ovsdb.py -t10 idl $srcdir/idltest.ovsschema unix:socket ?simple:b,ba,i,ia,r,ra,s,sa,u,ua?link1:i,k,ka,l2?link2:i,l1?singleton:name $3], + AT_CHECK([$PYTHON3 $srcdir/test-ovsdb.py -t10 idl $srcdir/idltest.ovsschema unix:socket ?simple:b,ba,i,ia,r,ra,s,sa,u,ua?simple3:name,uset,uref?simple4:name?simple6:name,weak_ref?link1:i,k,ka,l2?link2:i,l1?singleton:name $3], [0], [stdout], [ignore]) AT_CHECK([sort stdout | uuidfilt]m4_if([$6],,, [[| $6]]), [0], [$4]) @@ -355,28 +355,28 @@ OVSDB_CHECK_IDL([simple idl, initially empty, various ops], 'reconnect']], [[000: empty 001: {"error":null,"result":[{"uuid":["uuid","<0>"]},{"uuid":["uuid","<1>"]}]} -002: i=0 r=0 b=false s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> -002: i=1 r=2 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0> +002: table simple: i=0 r=0 b=false s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +002: table simple: i=1 r=2 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0> 003: {"error":null,"result":[{"count":2}]} -004: i=0 r=0 b=true s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> -004: i=1 r=2 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0> +004: table simple: i=0 r=0 b=true s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +004: table simple: i=1 r=2 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0> 005: {"error":null,"result":[{"count":2}]} -006: i=0 r=123.5 b=true s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> -006: i=1 r=123.5 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0> +006: table simple: i=0 r=123.5 b=true s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +006: table simple: i=1 r=123.5 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0> 007: {"error":null,"result":[{"uuid":["uuid","<6>"]}]} -008: i=-1 r=125 b=false s= u=<2> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6> -008: i=0 r=123.5 b=true s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> -008: i=1 r=123.5 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0> +008: table simple: i=-1 r=125 b=false s= u=<2> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6> +008: table simple: i=0 r=123.5 b=true s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +008: table simple: i=1 r=123.5 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0> 009: {"error":null,"result":[{"count":2}]} -010: i=-1 r=125 b=false s=newstring u=<2> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6> -010: i=0 r=123.5 b=true s=newstring u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> -010: i=1 r=123.5 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0> +010: table simple: i=-1 r=125 b=false s=newstring u=<2> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6> +010: table simple: i=0 r=123.5 b=true s=newstring u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +010: table simple: i=1 r=123.5 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0> 011: {"error":null,"result":[{"count":1}]} -012: i=-1 r=125 b=false s=newstring u=<2> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6> -012: i=1 r=123.5 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0> +012: table simple: i=-1 r=125 b=false s=newstring u=<2> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6> +012: table simple: i=1 r=123.5 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0> 013: reconnect -014: i=-1 r=125 b=false s=newstring u=<2> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6> -014: i=1 r=123.5 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0> +014: table simple: i=-1 r=125 b=false s=newstring u=<2> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6> +014: table simple: i=1 r=123.5 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0> 015: done ]]) @@ -403,11 +403,11 @@ OVSDB_CHECK_IDL([simple idl, initially populated], "table": "simple", "where": [], "row": {"b": true}}]']], - [[000: i=0 r=0 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> -000: i=1 r=2 b=true s=mystring u=<2> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<3> <4>] uuid=<5> + [[000: table simple: i=0 r=0 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +000: table simple: i=1 r=2 b=true s=mystring u=<2> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<3> <4>] uuid=<5> 001: {"error":null,"result":[{"count":2}]} -002: i=0 r=0 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> -002: i=1 r=2 b=true s=mystring u=<2> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<3> <4>] uuid=<5> +002: table simple: i=0 r=0 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +002: table simple: i=1 r=2 b=true s=mystring u=<2> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<3> <4>] uuid=<5> 003: done ]]) @@ -431,14 +431,14 @@ OVSDB_CHECK_IDL([simple idl, writing via IDL], "row": {}}]']], [['verify 0 b, verify 1 r, set 0 b 1, set 1 r 3.5' \ 'insert 2, verify 2 i, verify 1 b, delete 1']], - [[000: i=0 r=0 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> -000: i=1 r=2 b=true s=mystring u=<2> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<3> <4>] uuid=<5> + [[000: table simple: i=0 r=0 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +000: table simple: i=1 r=2 b=true s=mystring u=<2> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<3> <4>] uuid=<5> 001: commit, status=success -002: i=0 r=0 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> -002: i=1 r=3.5 b=true s=mystring u=<2> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<3> <4>] uuid=<5> +002: table simple: i=0 r=0 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +002: table simple: i=1 r=3.5 b=true s=mystring u=<2> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<3> <4>] uuid=<5> 003: commit, status=success -004: i=0 r=0 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> -004: i=2 r=0 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<6> +004: table simple: i=0 r=0 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +004: table simple: i=2 r=0 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<6> 005: done ]]) @@ -448,10 +448,10 @@ OVSDB_CHECK_IDL([simple idl, writing via IDL with unicode], "table": "simple", "row": {"s": "(╯°□°)╯︵ ┻━┻"}}]']], [['set 0 b 1, insert 1, set 1 s "¯\_(ツ)_/¯"']], - [[000: i=0 r=0 b=false s=(╯°□°)╯︵ ┻━┻ u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> + [[000: table simple: i=0 r=0 b=false s=(╯°□°)╯︵ ┻━┻ u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> 001: commit, status=success -002: i=0 r=0 b=true s=(╯°□°)╯︵ ┻━┻ u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> -002: i=1 r=0 b=false s="¯\_(ツ)_/¯" u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2> +002: table simple: i=0 r=0 b=true s=(╯°□°)╯︵ ┻━┻ u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +002: table simple: i=1 r=0 b=false s="¯\_(ツ)_/¯" u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2> 003: done ]]) @@ -475,10 +475,10 @@ OVSDB_CHECK_IDL_PY_WITH_EXPOUT([simple idl, writing large data via IDL with unic "table": "simple", "row": {"s": "'$(printf "测试超过四千零九十六个字节的中文字符串以使解码出现问题。%.0s" {1..50})'"}}]']], [['set 0 b 1, insert 1, set 1 s '$(printf "测试超过四千零九十六个字节的中文字符串以使解码出现问题。%.0s" {1..100})'']], - [[000: i=0 r=0 b=false s=$(printf "测试超过四千零九十六个字节的中文字符串以使解码出现问题。%.0s" {1..50}) u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> + [[000: table simple: i=0 r=0 b=false s=$(printf "测试超过四千零九十六个字节的中文字符串以使解码出现问题。%.0s" {1..50}) u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> 001: commit, status=success -002: i=0 r=0 b=true s=$(printf "测试超过四千零九十六个字节的中文字符串以使解码出现问题。%.0s" {1..50}) u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> -002: i=1 r=0 b=false s=$(printf "测试超过四千零九十六个字节的中文字符串以使解码出现问题。%.0s" {1..100}) u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2> +002: table simple: i=0 r=0 b=true s=$(printf "测试超过四千零九十六个字节的中文字符串以使解码出现问题。%.0s" {1..50}) u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +002: table simple: i=1 r=0 b=false s=$(printf "测试超过四千零九十六个字节的中文字符串以使解码出现问题。%.0s" {1..100}) u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2> 003: done]]) OVSDB_CHECK_IDL([simple idl, handling verification failure], @@ -499,16 +499,16 @@ OVSDB_CHECK_IDL([simple idl, handling verification failure], '+verify 1 r, set 1 r 3' \ 'verify 1 r, set 1 r 3' \ ]], - [[000: i=0 r=0 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> -000: i=1 r=2 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2> + [[000: table simple: i=0 r=0 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +000: table simple: i=1 r=2 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2> 001: commit, status=success 002: {"error":null,"result":[{"count":1}]} 003: commit, status=try again -004: i=0 r=0 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> -004: i=1 r=5 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2> +004: table simple: i=0 r=0 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +004: table simple: i=1 r=5 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2> 005: commit, status=success -006: i=0 r=0 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> -006: i=1 r=3 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2> +006: table simple: i=0 r=0 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +006: table simple: i=1 r=3 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2> 007: done ]]) @@ -518,9 +518,9 @@ OVSDB_CHECK_IDL([simple idl, increment operation], "table": "simple", "row": {}}]']], [['set 0 r 2.0, increment 0']], - [[000: i=0 r=0 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> + [[000: table simple: i=0 r=0 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> 001: commit, status=success, increment=1 -002: i=1 r=2 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +002: table simple: i=1 r=2 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> 003: done ]]) @@ -531,10 +531,10 @@ OVSDB_CHECK_IDL([simple idl, aborting], "row": {}}]']], [['set 0 r 2.0, abort' \ '+set 0 b 1']], - [[000: i=0 r=0 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> + [[000: table simple: i=0 r=0 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> 001: commit, status=aborted 002: commit, status=success -003: i=0 r=0 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +003: table simple: i=0 r=0 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> 004: done ]]) @@ -545,10 +545,10 @@ OVSDB_CHECK_IDL([simple idl, destroy without commit or abort], "row": {}}]']], [['set 0 r 2.0, destroy' \ '+set 0 b 1']], - [[000: i=0 r=0 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> + [[000: table simple: i=0 r=0 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> 001: destroy 002: commit, status=success -003: i=0 r=0 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +003: table simple: i=0 r=0 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> 004: done ]]) @@ -564,7 +564,7 @@ OVSDB_CHECK_IDL([simple idl, conditional, false condition], [[000: change conditions 001: empty 002: change conditions -003: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +003: table simple: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> 004: done ]]) @@ -580,7 +580,7 @@ OVSDB_CHECK_IDL([simple idl, conditional, true condition], [[000: change conditions 001: empty 002: change conditions -003: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +003: table simple: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> 004: done ]]) @@ -601,8 +601,8 @@ OVSDB_CHECK_IDL([simple idl, conditional, multiple clauses in condition], [[000: change conditions 001: empty 002: change conditions -003: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> -003: i=2 r=3 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2> +003: table simple: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +003: table simple: i=2 r=3 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2> 004: done ]]) @@ -618,7 +618,7 @@ OVSDB_CHECK_IDL([simple idl, conditional, modify as insert due to condition], [[000: change conditions 001: empty 002: change conditions -003: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +003: table simple: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> 004: done ]]) @@ -641,11 +641,11 @@ OVSDB_CHECK_IDL([simple idl, conditional, modify as delete due to condition], [[000: change conditions 001: empty 002: change conditions -003: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +003: table simple: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> 004: change conditions 005: empty 006: {"error":null,"result":[{"uuid":["uuid","<2>"]}]} -007: i=2 r=3 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2> +007: table simple: i=2 r=3 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2> 008: done ]]) @@ -676,15 +676,15 @@ OVSDB_CHECK_IDL([simple idl, conditional, multiple tables], [[000: change conditions 001: empty 002: change conditions -003: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +003: table simple: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> 004: change conditions -005: i=0 k=0 ka=[] l2= uuid=<2> -005: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +005: table link1: i=0 k=0 ka=[] l2= uuid=<2> +005: table simple: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> 006: change conditions 007: {"error":null,"result":[{"uuid":["uuid","<3>"]}]} -008: i=0 k=0 ka=[] l2= uuid=<2> -008: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> -008: i=3 l1= uuid=<3> +008: table link1: i=0 k=0 ka=[] l2= uuid=<2> +008: table link2: i=3 l1= uuid=<3> +008: table simple: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> 009: done ]]) @@ -716,19 +716,19 @@ OVSDB_CHECK_IDL([self-linking idl, consistent ops], "row": {"k": ["uuid", "#0#"]}}]']], [[000: empty 001: {"error":null,"result":[{"uuid":["uuid","<0>"]}]} -002: i=0 k=0 ka=[] l2= uuid=<0> +002: table link1: i=0 k=0 ka=[] l2= uuid=<0> 003: {"error":null,"result":[{"uuid":["uuid","<1>"]},{"uuid":["uuid","<2>"]}]} -004: i=0 k=0 ka=[] l2= uuid=<0> -004: i=1 k=2 ka=[] l2= uuid=<1> -004: i=2 k=1 ka=[] l2= uuid=<2> +004: table link1: i=0 k=0 ka=[] l2= uuid=<0> +004: table link1: i=1 k=2 ka=[] l2= uuid=<1> +004: table link1: i=2 k=1 ka=[] l2= uuid=<2> 005: {"error":null,"result":[{"count":1}]} -006: i=0 k=0 ka=[] l2= uuid=<0> -006: i=1 k=1 ka=[] l2= uuid=<1> -006: i=2 k=1 ka=[] l2= uuid=<2> +006: table link1: i=0 k=0 ka=[] l2= uuid=<0> +006: table link1: i=1 k=1 ka=[] l2= uuid=<1> +006: table link1: i=2 k=1 ka=[] l2= uuid=<2> 007: {"error":null,"result":[{"count":3}]} -008: i=0 k=0 ka=[] l2= uuid=<0> -008: i=1 k=0 ka=[] l2= uuid=<1> -008: i=2 k=0 ka=[] l2= uuid=<2> +008: table link1: i=0 k=0 ka=[] l2= uuid=<0> +008: table link1: i=1 k=0 ka=[] l2= uuid=<1> +008: table link1: i=2 k=0 ka=[] l2= uuid=<2> 009: done ]]) @@ -767,12 +767,12 @@ OVSDB_CHECK_IDL([self-linking idl, inconsistent ops], [[000: empty 001: {"error":null,"result":[{"uuid":["uuid","<0>"]},{"details":"Table link1 column k row <0> references nonexistent row <1> in table link1.","error":"referential integrity violation"}]} 002: {"error":null,"result":[{"uuid":["uuid","<2>"]},{"uuid":["uuid","<3>"]}]} -003: i=1 k=1 ka=[] l2= uuid=<2> -003: i=2 k=1 ka=[] l2= uuid=<3> +003: table link1: i=1 k=1 ka=[] l2= uuid=<2> +003: table link1: i=2 k=1 ka=[] l2= uuid=<3> 004: {"error":null,"result":[{"count":2},{"details":"Table link1 column k row references nonexistent row <4> in table link1.","error":"referential integrity violation"}]} 005: {"error":null,"result":[{"count":1},{"details":"cannot delete link1 row <2> because of 1 remaining reference(s)","error":"referential integrity violation"}]} 006: {"error":null,"result":[{"count":1}]} -007: i=1 k=1 ka=[] l2= uuid=<2> +007: table link1: i=1 k=1 ka=[] l2= uuid=<2> 008: {"error":null,"result":[{"count":1}]} 009: empty 010: done @@ -815,15 +815,15 @@ OVSDB_CHECK_IDL([self-linking idl, sets], "where": []}]']], [[000: empty 001: {"error":null,"result":[{"uuid":["uuid","<0>"]},{"uuid":["uuid","<1>"]},{"uuid":["uuid","<2>"]},{"uuid":["uuid","<3>"]}]} -002: i=0 k=0 ka=[0] l2= uuid=<0> -002: i=1 k=0 ka=[1] l2= uuid=<1> -002: i=2 k=0 ka=[2] l2= uuid=<2> -002: i=3 k=0 ka=[3] l2= uuid=<3> +002: table link1: i=0 k=0 ka=[0] l2= uuid=<0> +002: table link1: i=1 k=0 ka=[1] l2= uuid=<1> +002: table link1: i=2 k=0 ka=[2] l2= uuid=<2> +002: table link1: i=3 k=0 ka=[3] l2= uuid=<3> 003: {"error":null,"result":[{"count":4}]} -004: i=0 k=0 ka=[0 1 2 3] l2= uuid=<0> -004: i=1 k=0 ka=[0 1 2 3] l2= uuid=<1> -004: i=2 k=0 ka=[0 1 2 3] l2= uuid=<2> -004: i=3 k=0 ka=[0 1 2 3] l2= uuid=<3> +004: table link1: i=0 k=0 ka=[0 1 2 3] l2= uuid=<0> +004: table link1: i=1 k=0 ka=[0 1 2 3] l2= uuid=<1> +004: table link1: i=2 k=0 ka=[0 1 2 3] l2= uuid=<2> +004: table link1: i=3 k=0 ka=[0 1 2 3] l2= uuid=<3> 005: {"error":null,"result":[{"count":1},{"details":"Table link1 column ka row <2> references nonexistent row <4> in table link1.","error":"referential integrity violation"}]} 006: {"error":null,"result":[{"count":4}]} 007: empty @@ -843,8 +843,8 @@ OVSDB_CHECK_IDL([external-linking idl, consistent ops], "uuid-name": "row1"}]']], [[000: empty 001: {"error":null,"result":[{"uuid":["uuid","<0>"]},{"uuid":["uuid","<1>"]}]} -002: i=0 l1= uuid=<0> -002: i=1 k=1 ka=[] l2=0 uuid=<1> +002: table link1: i=1 k=1 ka=[] l2=0 uuid=<1> +002: table link2: i=0 l1= uuid=<0> 003: done ]]) @@ -867,20 +867,49 @@ OVSDB_CHECK_IDL([singleton idl, constraints], "row": {"name": "bar"}}]']], [[000: empty 001: {"error":null,"result":[{"uuid":["uuid","<0>"]}]} -002: name=foo uuid=<0> +002: table singleton: name=foo uuid=<0> 003: {"error":null,"result":[{"uuid":["uuid","<1>"]},{"details":"transaction causes \"singleton\" table to contain 2 rows, greater than the schema-defined limit of 1 row(s)","error":"constraint violation"}]} 004: {"error":null,"result":[{"count":1},{"uuid":["uuid","<2>"]}]} -005: name=bar uuid=<2> +005: table singleton: name=bar uuid=<2> 006: done ]]) +dnl This test creates a database with references and checks that deleting both +dnl source and destination rows of a reference in a single update doesn't leak +dnl rows that got orphaned when processing the update. +OVSDB_CHECK_IDL([simple idl, references, multiple deletes], + [['["idltest", + {"op": "insert", + "table": "simple", + "row": {"s": "row0_s"}, + "uuid-name": "weak_row0"}, + {"op": "insert", + "table": "simple6", + "row": {"name": "first_row", + "weak_ref": ["set", + [["named-uuid", "weak_row0"]] + ]}}]']], + [['["idltest", + {"op": "delete", + "table": "simple", + "where": [["s", "==", "row0_s"]]}, + {"op": "delete", + "table": "simple6", + "where": [["name", "==", "first_row"]]}]']], + [[000: table simple6: name=first_row weak_ref=[<0>] uuid=<1> +000: table simple: i=0 r=0 b=false s=row0_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<0> +001: {"error":null,"result":[{"count":1},{"count":1}]} +002: empty +003: done +]]) + OVSDB_CHECK_IDL_PY([external-linking idl, insert ops], [], [['linktest']], [[000: empty 001: commit, status=success -002: i=1 k=1 ka=[1] l2= uuid=<0> -002: i=2 k=1 ka=[1 2] l2= uuid=<1> +002: table link1: i=1 k=1 ka=[1] l2= uuid=<0> +002: table link1: i=2 k=1 ka=[1 2] l2= uuid=<1> 003: done ]]) @@ -889,7 +918,7 @@ OVSDB_CHECK_IDL_PY([getattr idl, insert ops], [['getattrtest']], [[000: empty 001: commit, status=success -002: i=2 k=2 ka=[] l2= uuid=<0> +002: table link1: i=2 k=2 ka=[] l2= uuid=<0> 003: done ]]) @@ -902,11 +931,11 @@ OVSDB_CHECK_IDL_PY([row-from-json idl, whats this], "table": "simple", "row": {}}]']], [['notifytest insert 2, notifytest set 1 b 1, notifytest delete 0']], - [[000: i=0 r=0 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> -000: i=1 r=0 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2> + [[000: table simple: i=0 r=0 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +000: table simple: i=1 r=0 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2> 001: commit, status=success, events=create|2|None, delete|0|None, update|1|b -002: i=1 r=0 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2> -002: i=2 r=0 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3> +002: table simple: i=1 r=0 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2> +002: table simple: i=2 r=0 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3> 003: done ]]) @@ -946,19 +975,19 @@ AT_CHECK([test-ovsdb '-vPATTERN:console:test-ovsdb|%c|%m' -vjsonrpc -t10 idl uni AT_CHECK([sort stdout | uuidfilt], [0], [[000: empty 001: {"error":null,"result":[{"uuid":["uuid","<0>"]}]} -002: i=0 k=0 ka=[] l2= uuid=<0> +002: table link1: i=0 k=0 ka=[] l2= uuid=<0> 003: {"error":null,"result":[{"uuid":["uuid","<1>"]},{"uuid":["uuid","<2>"]}]} -004: i=0 k=0 ka=[] l2= uuid=<0> -004: i=1 k=2 ka=[] l2= uuid=<1> -004: i=2 k=1 ka=[] l2= uuid=<2> +004: table link1: i=0 k=0 ka=[] l2= uuid=<0> +004: table link1: i=1 k=2 ka=[] l2= uuid=<1> +004: table link1: i=2 k=1 ka=[] l2= uuid=<2> 005: {"error":null,"result":[{"count":1}]} -006: i=0 k=0 ka=[] l2= uuid=<0> -006: i=1 k=1 ka=[] l2= uuid=<1> -006: i=2 k=1 ka=[] l2= uuid=<2> +006: table link1: i=0 k=0 ka=[] l2= uuid=<0> +006: table link1: i=1 k=1 ka=[] l2= uuid=<1> +006: table link1: i=2 k=1 ka=[] l2= uuid=<2> 007: {"error":null,"result":[{"count":3}]} -008: i=0 k=0 ka=[] l2= uuid=<0> -008: i=1 k=0 ka=[] l2= uuid=<1> -008: i=2 k=0 ka=[] l2= uuid=<2> +008: table link1: i=0 k=0 ka=[] l2= uuid=<0> +008: table link1: i=1 k=0 ka=[] l2= uuid=<1> +008: table link1: i=2 k=0 ka=[] l2= uuid=<2> 009: done ]]) @@ -1022,11 +1051,11 @@ OVSDB_CHECK_IDL_FETCH_COLUMNS([simple idl, initially populated], "row": {}}]']], [?simple:i,r!], ['fetch 0 r'], - [[000: i=0 uuid=<0> -000: i=1 uuid=<1> + [[000: table simple: i=0 uuid=<0> +000: table simple: i=1 uuid=<1> 001: commit, status=success -002: i=0 r=0 uuid=<0> -002: i=1 uuid=<1> +002: table simple: i=0 r=0 uuid=<0> +002: table simple: i=1 uuid=<1> 003: done ]]) @@ -1098,28 +1127,28 @@ OVSDB_CHECK_IDL_WO_MONITOR_COND([simple idl disable monitor-cond], 'reconnect']], [[000: empty 001: {"error":null,"result":[{"uuid":["uuid","<0>"]},{"uuid":["uuid","<1>"]}]} -002: i=0 r=0 b=false s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> -002: i=1 r=2 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0> +002: table simple: i=0 r=0 b=false s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +002: table simple: i=1 r=2 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0> 003: {"error":null,"result":[{"count":2}]} -004: i=0 r=0 b=true s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> -004: i=1 r=2 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0> +004: table simple: i=0 r=0 b=true s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +004: table simple: i=1 r=2 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0> 005: {"error":null,"result":[{"count":2}]} -006: i=0 r=123.5 b=true s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> -006: i=1 r=123.5 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0> +006: table simple: i=0 r=123.5 b=true s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +006: table simple: i=1 r=123.5 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0> 007: {"error":null,"result":[{"uuid":["uuid","<6>"]}]} -008: i=-1 r=125 b=false s= u=<2> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6> -008: i=0 r=123.5 b=true s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> -008: i=1 r=123.5 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0> +008: table simple: i=-1 r=125 b=false s= u=<2> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6> +008: table simple: i=0 r=123.5 b=true s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +008: table simple: i=1 r=123.5 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0> 009: {"error":null,"result":[{"count":2}]} -010: i=-1 r=125 b=false s=newstring u=<2> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6> -010: i=0 r=123.5 b=true s=newstring u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> -010: i=1 r=123.5 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0> +010: table simple: i=-1 r=125 b=false s=newstring u=<2> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6> +010: table simple: i=0 r=123.5 b=true s=newstring u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +010: table simple: i=1 r=123.5 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0> 011: {"error":null,"result":[{"count":1}]} -012: i=-1 r=125 b=false s=newstring u=<2> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6> -012: i=1 r=123.5 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0> +012: table simple: i=-1 r=125 b=false s=newstring u=<2> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6> +012: table simple: i=1 r=123.5 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0> 013: reconnect -014: i=-1 r=125 b=false s=newstring u=<2> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6> -014: i=1 r=123.5 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0> +014: table simple: i=-1 r=125 b=false s=newstring u=<2> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6> +014: table simple: i=1 r=123.5 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0> 015: done ]]) @@ -1162,13 +1191,12 @@ OVSDB_CHECK_IDL_TRACK([track, simple idl, initially populated], "table": "simple", "where": [], "row": {"b": true}}]']], - [[000: i=1 r=2 b=true s=mystring u=<0> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<1> <2>] uuid=<3> -000: inserted row: uuid=<3> -000: updated columns: b ba i ia r ra s sa u ua + [[000: table simple: inserted row: i=1 r=2 b=true s=mystring u=<0> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<1> <2>] uuid=<3> +000: table simple: updated columns: b ba i ia r ra s sa u ua 001: {"error":null,"result":[{"count":2}]} -002: i=0 r=0 b=true s= u=<4> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<5> -002: i=1 r=2 b=true s=mystring u=<0> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<1> <2>] uuid=<3> -002: updated columns: b +002: table simple: i=0 r=0 b=true s= u=<4> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<5> +002: table simple: i=1 r=2 b=true s=mystring u=<0> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<1> <2>] uuid=<3> +002: table simple: updated columns: b 003: done ]]) @@ -1209,19 +1237,17 @@ OVSDB_CHECK_IDL_TRACK([track, simple idl, initially populated, orphan weak refer "table": "simple6", "where": []}]']], [[000: change conditions -001: inserted row: uuid=<0> -001: name=first_row weak_ref=[] uuid=<0> -001: updated columns: name weak_ref +001: table simple6: inserted row: name=first_row weak_ref=[] uuid=<0> +001: table simple6: updated columns: name weak_ref 002: change conditions -003: i=0 r=0 b=false s=row1_s u=<1> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2> -003: inserted row: uuid=<2> -003: name=first_row weak_ref=[<2>] uuid=<0> -003: updated columns: s +003: table simple6: name=first_row weak_ref=[<1>] uuid=<0> +003: table simple: inserted row: i=0 r=0 b=false s=row1_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +003: table simple: updated columns: s 004: {"error":null,"result":[{"count":1}]} -005: name=new_name weak_ref=[<2>] uuid=<0> -005: updated columns: name +005: table simple6: name=new_name weak_ref=[<1>] uuid=<0> +005: table simple6: updated columns: name 006: {"error":null,"result":[{"count":1}]} -007: i=0 r=0 b=false s=row1_s u=<1> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2> +007: table simple: i=0 r=0 b=false s=row1_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> 008: done ]]) @@ -1253,30 +1279,266 @@ OVSDB_CHECK_IDL_TRACK([track, simple idl, initially populated, orphan rows, cond "table": "simple6", "where": []}]']], [[000: change conditions -001: inserted row: uuid=<0> -001: name=first_row weak_ref=[] uuid=<0> -001: updated columns: name weak_ref +001: table simple6: inserted row: name=first_row weak_ref=[] uuid=<0> +001: table simple6: updated columns: name weak_ref 002: change conditions -003: i=0 r=0 b=false s=row0_s u=<1> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2> -003: inserted row: uuid=<2> -003: name=first_row weak_ref=[<2>] uuid=<0> -003: updated columns: s +003: table simple6: name=first_row weak_ref=[<1>] uuid=<0> +003: table simple: inserted row: i=0 r=0 b=false s=row0_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +003: table simple: updated columns: s 004: change conditions -005: i=0 r=0 b=false s=row1_s u=<1> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3> -005: inserted row: uuid=<3> -005: updated columns: s +005: table simple6: name=first_row weak_ref=[] uuid=<0> +005: table simple: deleted row: i=0 r=0 b=false s=row0_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +005: table simple: inserted row: i=0 r=0 b=false s=row1_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3> +005: table simple: updated columns: s 006: change conditions -007: deleted row: uuid=<3> -007: i=0 r=0 b=false s=row0_s u=<1> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2> -007: i=0 r=0 b=false s=row1_s u=<1> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3> -007: inserted row: uuid=<2> -007: name=first_row weak_ref=[<2>] uuid=<0> -007: updated columns: s +007: table simple6: name=first_row weak_ref=[<1>] uuid=<0> +007: table simple: deleted row: i=0 r=0 b=false s=row1_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3> +007: table simple: inserted row: i=0 r=0 b=false s=row0_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +007: table simple: updated columns: s +008: {"error":null,"result":[{"count":1}]} +009: table simple: i=0 r=0 b=false s=row0_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +010: done +]]) + +dnl This test checks that deleting the destination of a weak reference +dnl without deleting the source, through monitor condition change, updates +dnl the source tracked record. +OVSDB_CHECK_IDL_TRACK([track, simple idl, initially populated, references, conditional delete], + [['["idltest", + {"op": "insert", + "table": "simple", + "row": {"s": "row0_s", "i": 0}, + "uuid-name": "weak_row0"}, + {"op": "insert", + "table": "simple", + "row": {"s": "row1_s", "i": 1}, + "uuid-name": "weak_row1"}, + {"op": "insert", + "table": "simple6", + "row": {"name": "first_row", + "weak_ref": ["set", + [["named-uuid", "weak_row0"], + ["named-uuid", "weak_row1"]] + ]}}]']], + [['condition simple []' \ + 'condition simple [["s","==","row0_s"]]' \ + 'condition simple [["s","==","row1_s"]]' \ + '["idltest", + {"op": "update", + "table": "simple6", + "where": [], + "row": {"name": "new_name"}}]' \ + '["idltest", + {"op": "delete", + "table": "simple6", + "where": []}]']], + [[000: change conditions +001: table simple6: inserted row: name=first_row weak_ref=[] uuid=<0> +001: table simple6: updated columns: name weak_ref +002: change conditions +003: table simple6: name=first_row weak_ref=[<1>] uuid=<0> +003: table simple: inserted row: i=0 r=0 b=false s=row0_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +003: table simple: updated columns: s +004: change conditions +005: table simple6: name=first_row weak_ref=[<3>] uuid=<0> +005: table simple: deleted row: i=0 r=0 b=false s=row0_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +005: table simple: inserted row: i=1 r=0 b=false s=row1_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3> +005: table simple: updated columns: i s +006: {"error":null,"result":[{"count":1}]} +007: table simple6: name=new_name weak_ref=[<3>] uuid=<0> +007: table simple6: updated columns: name 008: {"error":null,"result":[{"count":1}]} -009: i=0 r=0 b=false s=row0_s u=<1> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2> +009: table simple: i=1 r=0 b=false s=row1_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3> 010: done ]]) +dnl This test checks that deleting the destination of a reference updates the +dnl source tracked record. +OVSDB_CHECK_IDL_TRACK([track, simple idl, initially populated, references, single delete], + [['["idltest", + {"op": "insert", + "table": "simple", + "row": {"s": "row0_s"}, + "uuid-name": "uuid_row0_s"}, + {"op": "insert", + "table": "simple6", + "row": {"name": "row0_s6", + "weak_ref": ["set", + [["named-uuid", "uuid_row0_s"]] + ]}}]']], + [['condition simple [true];simple6 [true]' \ + '["idltest", + {"op": "delete", + "table": "simple", + "where": []}]' \ + '["idltest", + {"op": "insert", + "table": "simple", + "row": {"s": "row0_s"}}]']], + [[000: change conditions +001: table simple6: inserted row: name=row0_s6 weak_ref=[<0>] uuid=<1> +001: table simple6: updated columns: name weak_ref +001: table simple: inserted row: i=0 r=0 b=false s=row0_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<0> +001: table simple: updated columns: s +002: {"error":null,"result":[{"count":1}]} +003: table simple6: name=row0_s6 weak_ref=[] uuid=<1> +003: table simple6: updated columns: weak_ref +003: table simple: deleted row: i=0 r=0 b=false s=row0_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<0> +004: {"error":null,"result":[{"uuid":["uuid","<3>"]}]} +005: table simple6: name=row0_s6 weak_ref=[] uuid=<1> +005: table simple: inserted row: i=0 r=0 b=false s=row0_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3> +005: table simple: updated columns: s +006: done +]]) + +dnl This test checks that deleting both the destination and source of the +dnl reference doesn't remove the reference in the source tracked record. +OVSDB_CHECK_IDL_TRACK([track, simple idl, initially populated, weak references, multiple deletes], + [['["idltest", + {"op": "insert", + "table": "simple", + "row": {"s": "row0_s"}, + "uuid-name": "uuid_row0_s"}, + {"op": "insert", + "table": "simple6", + "row": {"name": "row0_s6", + "weak_ref": ["set", + [["named-uuid", "uuid_row0_s"]] + ]}}]']], + [['condition simple [true];simple6 [true]' \ + '["idltest", + {"op": "delete", + "table": "simple", + "where": []}, + {"op": "delete", + "table": "simple6", + "where": []}]' \ + '["idltest", + {"op": "insert", + "table": "simple", + "row": {"s": "row0_s"}}]']], + [[000: change conditions +001: table simple6: inserted row: name=row0_s6 weak_ref=[<0>] uuid=<1> +001: table simple6: updated columns: name weak_ref +001: table simple: inserted row: i=0 r=0 b=false s=row0_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<0> +001: table simple: updated columns: s +002: {"error":null,"result":[{"count":1},{"count":1}]} +003: table simple6: deleted row: name=row0_s6 weak_ref=[<0>] uuid=<1> +003: table simple: deleted row: i=0 r=0 b=false s=row0_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<0> +004: {"error":null,"result":[{"uuid":["uuid","<3>"]}]} +005: table simple: inserted row: i=0 r=0 b=false s=row0_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3> +005: table simple: updated columns: s +006: done +]]) + +dnl This test checks that deleting both the destination and source of the +dnl reference doesn't remove the reference in the source tracked record. +OVSDB_CHECK_IDL_TRACK([track, simple idl, initially populated, strong references, multiple deletes], + [['["idltest", + {"op": "insert", + "table": "simple4", + "row": {"name": "row0_s4"}, + "uuid-name": "uuid_row0_s4"}, + {"op": "insert", + "table": "simple3", + "row": {"name": "row0_s3", + "uref": ["set", + [["named-uuid", "uuid_row0_s4"]] + ]}}]']], + [['condition simple [true];simple3 [true];simple4 [true]' \ + '["idltest", + {"op": "delete", + "table": "simple3", + "where": []}, + {"op": "delete", + "table": "simple4", + "where": []}]' \ + '["idltest", + {"op": "insert", + "table": "simple", + "row": {"s": "row0_s"}}]']], + [[000: change conditions +001: table simple3: inserted row: name=row0_s3 uset=[] uref=[<0>] uuid=<1> +001: table simple3: updated columns: name uref +001: table simple4: inserted row: name=row0_s4 uuid=<0> +001: table simple4: updated columns: name +002: {"error":null,"result":[{"count":1},{"count":1}]} +003: table simple3: deleted row: name=row0_s3 uset=[] uref=[<0>] uuid=<1> +003: table simple4: deleted row: name=row0_s4 uuid=<0> +004: {"error":null,"result":[{"uuid":["uuid","<2>"]}]} +005: table simple: inserted row: i=0 r=0 b=false s=row0_s u=<3> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2> +005: table simple: updated columns: s +006: done +]]) + +dnl This test checks that changing conditions to not include the target of +dnl a strong reference also updates the source row when change tracking is +dnl enabled. +OVSDB_CHECK_IDL_TRACK([track, simple idl, initially populated, strong references, conditional], + [['["idltest", + {"op": "insert", + "table": "simple4", + "row": {"name": "row0_s4"}, + "uuid-name": "uuid_row0_s4"}, + {"op": "insert", + "table": "simple3", + "row": {"name": "row0_s3", + "uref": ["set", + [["named-uuid", "uuid_row0_s4"]] + ]}}]']], + [['condition simple [true];simple3 [true];simple4 [true]' \ + 'condition simple4 []' \ + '["idltest", + {"op": "insert", + "table": "simple", + "row": {"s": "row0_s"}}]']], + [[000: change conditions +001: table simple3: inserted row: name=row0_s3 uset=[] uref=[<0>] uuid=<1> +001: table simple3: updated columns: name uref +001: table simple4: inserted row: name=row0_s4 uuid=<0> +001: table simple4: updated columns: name +002: change conditions +003: table simple3: name=row0_s3 uset=[] uref=[] uuid=<1> +003: table simple4: deleted row: name=row0_s4 uuid=<0> +004: {"error":null,"result":[{"uuid":["uuid","<2>"]}]} +005: table simple3: name=row0_s3 uset=[] uref=[] uuid=<1> +005: table simple: inserted row: i=0 r=0 b=false s=row0_s u=<3> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2> +005: table simple: updated columns: s +006: done +]]) + +dnl This test checks that changing conditions to not include the target of +dnl a strong reference also updates the source row when change tracking is +dnl disabled. +OVSDB_CHECK_IDL([simple idl, initially populated, strong references, conditional], + [['["idltest", + {"op": "insert", + "table": "simple4", + "row": {"name": "row0_s4"}, + "uuid-name": "uuid_row0_s4"}, + {"op": "insert", + "table": "simple3", + "row": {"name": "row0_s3", + "uref": ["set", + [["named-uuid", "uuid_row0_s4"]] + ]}}]']], + [['condition simple [true];simple3 [true];simple4 [true]' \ + 'condition simple4 []' \ + '["idltest", + {"op": "insert", + "table": "simple", + "row": {"s": "row0_s"}}]']], + [[000: change conditions +001: table simple3: name=row0_s3 uset=[] uref=[<0>] uuid=<1> +001: table simple4: name=row0_s4 uuid=<0> +002: change conditions +003: table simple3: name=row0_s3 uset=[] uref=[] uuid=<1> +004: {"error":null,"result":[{"uuid":["uuid","<2>"]}]} +005: table simple3: name=row0_s3 uset=[] uref=[] uuid=<1> +005: table simple: i=0 r=0 b=false s=row0_s u=<3> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2> +006: done +]]) + OVSDB_CHECK_IDL_TRACK([track, simple idl, initially empty, various ops], [], [['["idltest", @@ -1330,34 +1592,31 @@ OVSDB_CHECK_IDL_TRACK([track, simple idl, initially empty, various ops], 'reconnect']], [[000: empty 001: {"error":null,"result":[{"uuid":["uuid","<0>"]},{"uuid":["uuid","<1>"]}]} -002: i=1 r=2 b=true s=mystring u=<2> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<3> <4>] uuid=<0> -002: inserted row: uuid=<0> -002: updated columns: b ba i ia r ra s sa u ua +002: table simple: inserted row: i=1 r=2 b=true s=mystring u=<2> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<3> <4>] uuid=<0> +002: table simple: updated columns: b ba i ia r ra s sa u ua 003: {"error":null,"result":[{"count":2}]} -004: i=0 r=0 b=true s= u=<5> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> -004: updated columns: b +004: table simple: i=0 r=0 b=true s= u=<5> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +004: table simple: updated columns: b 005: {"error":null,"result":[{"count":2}]} -006: i=0 r=123.5 b=true s= u=<5> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> -006: i=1 r=123.5 b=true s=mystring u=<2> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<3> <4>] uuid=<0> -006: updated columns: r -006: updated columns: r +006: table simple: i=0 r=123.5 b=true s= u=<5> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +006: table simple: i=1 r=123.5 b=true s=mystring u=<2> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<3> <4>] uuid=<0> +006: table simple: updated columns: r +006: table simple: updated columns: r 007: {"error":null,"result":[{"uuid":["uuid","<6>"]}]} -008: i=-1 r=125 b=false s= u=<5> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6> -008: inserted row: uuid=<6> -008: updated columns: ba i ia r ra +008: table simple: inserted row: i=-1 r=125 b=false s= u=<5> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6> +008: table simple: updated columns: ba i ia r ra 009: {"error":null,"result":[{"count":2}]} -010: i=-1 r=125 b=false s=newstring u=<5> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6> -010: i=0 r=123.5 b=true s=newstring u=<5> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> -010: updated columns: s -010: updated columns: s +010: table simple: i=-1 r=125 b=false s=newstring u=<5> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6> +010: table simple: i=0 r=123.5 b=true s=newstring u=<5> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +010: table simple: updated columns: s +010: table simple: updated columns: s 011: {"error":null,"result":[{"count":1}]} -012: deleted row: uuid=<1> -012: i=0 r=123.5 b=true s=newstring u=<5> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +012: table simple: deleted row: i=0 r=123.5 b=true s=newstring u=<5> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> 013: reconnect -014: i=-1 r=125 b=false s=newstring u=<5> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6> -014: i=1 r=123.5 b=true s=mystring u=<2> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<3> <4>] uuid=<0> -014: updated columns: b ba i ia r ra s sa u ua -014: updated columns: ba i ia r ra s +014: table simple: inserted row: i=-1 r=125 b=false s=newstring u=<5> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6> +014: table simple: inserted row: i=1 r=123.5 b=true s=mystring u=<2> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<3> <4>] uuid=<0> +014: table simple: updated columns: b ba i ia r ra s sa u ua +014: table simple: updated columns: ba i ia r ra s 015: done ]]) @@ -1397,16 +1656,16 @@ OVSDB_CHECK_IDL_PY([partial-map idl], "row":{"name":"myString1","smap":["map",[["key1","value1"],["key2","value2"]]]} }]'] ], [?simple2:name,smap,imap 'partialmapinsertelement' 'partialmapinsertmultipleelements' 'partialmapdelelements' 'partialmapmutatenew'], -[[000: name=myString1 smap=[(key1 value1) (key2 value2)] imap=[] +[[000: table simple2: name=myString1 smap=[(key1 value1) (key2 value2)] imap=[] uuid=<0> 001: commit, status=success -002: name=String2 smap=[(key1 myList1) (key2 value2)] imap=[(3 myids2)] +002: table simple2: name=String2 smap=[(key1 myList1) (key2 value2)] imap=[(3 myids2)] uuid=<0> 003: commit, status=success -004: name=String2 smap=[(key1 myList1) (key2 myList2) (key3 myList3) (key4 myList4)] imap=[(3 myids2)] +004: table simple2: name=String2 smap=[(key1 myList1) (key2 myList2) (key3 myList3) (key4 myList4)] imap=[(3 myids2)] uuid=<0> 005: commit, status=success -006: name=String2 smap=[(key2 myList2)] imap=[(3 myids2)] +006: table simple2: name=String2 smap=[(key2 myList2)] imap=[(3 myids2)] uuid=<0> 007: commit, status=success -008: name=String2 smap=[(key2 myList2)] imap=[(3 myids2)] -008: name=String2New smap=[(key1 newList1) (key2 newList2)] imap=[] +008: table simple2: name=String2 smap=[(key2 myList2)] imap=[(3 myids2)] uuid=<0> +008: table simple2: name=String2New smap=[(key1 newList1) (key2 newList2)] imap=[] uuid=<1> 009: done ]]) @@ -1414,11 +1673,11 @@ OVSDB_CHECK_IDL_PY([partial-map update set refmap idl], [['["idltest", {"op":"insert", "table":"simple3", "row":{"name":"myString1"}}, {"op":"insert", "table":"simple5", "row":{"name":"myString2"}}]']], ['partialmapmutateirefmap'], -[[000: name=myString1 uset=[] -000: name=myString2 irefmap=[] +[[000: table simple3: name=myString1 uset=[] uref=[] uuid=<0> +000: table simple5: name=myString2 irefmap=[] uuid=<1> 001: commit, status=success -002: name=myString1 uset=[] -002: name=myString2 irefmap=[(1 <0>)] +002: table simple3: name=myString1 uset=[] uref=[] uuid=<0> +002: table simple5: name=myString2 irefmap=[(1 <0>)] uuid=<1> 003: done ]]) @@ -1441,17 +1700,17 @@ OVSDB_CHECK_IDL_PARTIAL_UPDATE_SET_COLUMN([set, simple3 idl-partial-update-set-c ], [], [[000: Getting records -001: name=mySet1 uset=[[<0>],[<1>]] uref=[] +001: table simple3: name=mySet1 uset=[<0>,<1>] uref=[] uuid=<2> 002: After rename+add new value -003: name=String2 uset=[[<0>],[<1>],[<2>]] uref=[] +003: table simple3: name=String2 uset=[<0>,<1>,<3>] uref=[] uuid=<2> 004: After add new value -005: name=String2 uset=[[<0>],[<1>],[<2>],[<3>]] uref=[] +005: table simple3: name=String2 uset=[<0>,<1>,<3>,<4>] uref=[] uuid=<2> 006: After delete value -007: name=String2 uset=[[<0>],[<1>],[<3>]] uref=[] +007: table simple3: name=String2 uset=[<0>,<1>,<4>] uref=[] uuid=<2> 008: After trying to delete a deleted value -009: name=String2 uset=[[<0>],[<1>],[<3>]] uref=[] +009: table simple3: name=String2 uset=[<0>,<1>,<4>] uref=[] uuid=<2> 010: After add to other table + set of strong ref -011: name=String2 uset=[[<0>],[<1>],[<3>]] uref=[[<4>]] +011: table simple3: name=String2 uset=[<0>,<1>,<4>] uref=[<5>] uuid=<2> 012: End test ]]) @@ -1463,22 +1722,26 @@ OVSDB_CHECK_IDL_PY([partial-set idl], "mutations": [["uset", "insert", ["set", [["uuid", "000d2f6a-76af-412f-b59d-e7bcd3e84eff"]]]]]}]'] ], ['partialrenamesetadd' 'partialduplicateadd' 'partialsetdel' 'partialsetref' 'partialsetoverrideops' 'partialsetadddelete' 'partialsetmutatenew'], -[[000: name=mySet1 uset=[<0> <1>] +[[000: table simple3: name=mySet1 uset=[<0> <1>] uref=[] uuid=<2> 001: commit, status=success -002: name=String2 uset=[<0> <1> <2>] +002: table simple3: name=String2 uset=[<0> <1> <3>] uref=[] uuid=<2> 003: commit, status=success -004: name=String2 uset=[<0> <1> <2> <3>] +004: table simple3: name=String2 uset=[<0> <1> <3> <4>] uref=[] uuid=<2> 005: commit, status=success -006: name=String2 uset=[<0> <1> <3>] +006: table simple3: name=String2 uset=[<0> <1> <4>] uref=[] uuid=<2> 007: commit, status=success -008: name=String2 uset=[<0> <1> <3>] +008: table simple3: name=String2 uset=[<0> <1> <4>] uref=[<5>] uuid=<2> +008: table simple4: name=test uuid=<5> 009: commit, status=success -010: name=String2 uset=[<3>] +010: table simple3: name=String2 uset=[<4>] uref=[<5>] uuid=<2> +010: table simple4: name=test uuid=<5> 011: commit, status=success -012: name=String2 uset=[<4> <5>] +012: table simple3: name=String2 uset=[<6> <7>] uref=[<5>] uuid=<2> +012: table simple4: name=test uuid=<5> 013: commit, status=success -014: name=String2 uset=[<4> <5>] -014: name=String3 uset=[<6>] +014: table simple3: name=String2 uset=[<6> <7>] uref=[<5>] uuid=<2> +014: table simple3: name=String3 uset=[<8>] uref=[] uuid=<9> +014: table simple4: name=test uuid=<5> 015: done ]]) @@ -1486,6 +1749,28 @@ m4_define([OVSDB_CHECK_IDL_NOTIFY], [OVSDB_CHECK_IDL_PY([$1], [], [$2], [$3], [notify $4], [$5]) OVSDB_CHECK_IDL_SSL_PY([$1], [], [$2], [$3], [notify $4], [$5])]) +OVSDB_CHECK_IDL_NOTIFY([simple link idl verify notify], + [['track-notify' \ + '["idltest", + {"op": "insert", + "table": "link1", + "row": {"i": 1, "k": ["named-uuid", "l1row"], "l2": ["set", [["named-uuid", "l2row"]]]}, + "uuid-name": "l1row"}, + {"op": "insert", + "table": "link2", + "uuid-name": "l2row", + "row": {"i": 2, "l1": ["set", [["named-uuid", "l1row"]]]}}]']], +[[000: empty +000: event:create, row={}, uuid=<0>, updates=None +000: event:create, row={}, uuid=<1>, updates=None +001: {"error":null,"result":[{"uuid":["uuid","<2>"]},{"uuid":["uuid","<3>"]}]} +002: event:create, row={i=1 l2=[<3>]}, uuid=<2>, updates=None +002: event:create, row={i=2 l1=[<2>]}, uuid=<3>, updates=None +002: table link1: i=1 k=1 ka=[] l2=2 uuid=<2> +002: table link2: i=2 l1=1 uuid=<3> +003: done +]]) + OVSDB_CHECK_IDL_NOTIFY([simple idl verify notify], [['track-notify' \ '["idltest", @@ -1538,44 +1823,44 @@ OVSDB_CHECK_IDL_NOTIFY([simple idl verify notify], "where": [["i", "==", 0]]}]' \ 'reconnect']], [[000: empty -000: event:create, row={uuid=<0>}, updates=None -000: event:create, row={uuid=<1>}, updates=None +000: event:create, row={}, uuid=<0>, updates=None +000: event:create, row={}, uuid=<1>, updates=None 001: {"error":null,"result":[{"uuid":["uuid","<2>"]},{"uuid":["uuid","<3>"]}]} -002: event:create, row={i=0 r=0 b=false s= u=<4> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3>}, updates=None -002: event:create, row={i=1 r=2 b=true s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>] uuid=<2>}, updates=None -002: i=0 r=0 b=false s= u=<4> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3> -002: i=1 r=2 b=true s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>] uuid=<2> +002: event:create, row={i=0 r=0 b=false s= u=<4> ia=[] ra=[] ba=[] sa=[] ua=[]}, uuid=<3>, updates=None +002: event:create, row={i=1 r=2 b=true s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>]}, uuid=<2>, updates=None +002: table simple: i=0 r=0 b=false s= u=<4> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3> +002: table simple: i=1 r=2 b=true s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>] uuid=<2> 003: {"error":null,"result":[{"count":2}]} -004: event:update, row={i=1 r=2 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>] uuid=<2>}, updates={b=true uuid=<2>} -004: i=0 r=0 b=false s= u=<4> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3> -004: i=1 r=2 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>] uuid=<2> +004: event:update, row={i=1 r=2 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>]}, uuid=<2>, updates={b=true} +004: table simple: i=0 r=0 b=false s= u=<4> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3> +004: table simple: i=1 r=2 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>] uuid=<2> 005: {"error":null,"result":[{"count":2}]} -006: event:update, row={i=0 r=123.5 b=false s= u=<4> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3>}, updates={r=0 uuid=<3>} -006: event:update, row={i=1 r=123.5 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>] uuid=<2>}, updates={r=2 uuid=<2>} -006: i=0 r=123.5 b=false s= u=<4> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3> -006: i=1 r=123.5 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>] uuid=<2> +006: event:update, row={i=0 r=123.5 b=false s= u=<4> ia=[] ra=[] ba=[] sa=[] ua=[]}, uuid=<3>, updates={r=0} +006: event:update, row={i=1 r=123.5 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>]}, uuid=<2>, updates={r=2} +006: table simple: i=0 r=123.5 b=false s= u=<4> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3> +006: table simple: i=1 r=123.5 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>] uuid=<2> 007: {"error":null,"result":[{"uuid":["uuid","<8>"]}]} -008: event:create, row={i=-1 r=125 b=false s= u=<4> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<8>}, updates=None -008: i=-1 r=125 b=false s= u=<4> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<8> -008: i=0 r=123.5 b=false s= u=<4> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3> -008: i=1 r=123.5 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>] uuid=<2> +008: event:create, row={i=-1 r=125 b=false s= u=<4> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[]}, uuid=<8>, updates=None +008: table simple: i=-1 r=125 b=false s= u=<4> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<8> +008: table simple: i=0 r=123.5 b=false s= u=<4> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3> +008: table simple: i=1 r=123.5 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>] uuid=<2> 009: {"error":null,"result":[{"count":2}]} -010: event:update, row={i=-1 r=125 b=false s=newstring u=<4> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<8>}, updates={s= uuid=<8>} -010: event:update, row={i=0 r=123.5 b=false s=newstring u=<4> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3>}, updates={s= uuid=<3>} -010: i=-1 r=125 b=false s=newstring u=<4> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<8> -010: i=0 r=123.5 b=false s=newstring u=<4> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3> -010: i=1 r=123.5 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>] uuid=<2> +010: event:update, row={i=-1 r=125 b=false s=newstring u=<4> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[]}, uuid=<8>, updates={s=} +010: event:update, row={i=0 r=123.5 b=false s=newstring u=<4> ia=[] ra=[] ba=[] sa=[] ua=[]}, uuid=<3>, updates={s=} +010: table simple: i=-1 r=125 b=false s=newstring u=<4> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<8> +010: table simple: i=0 r=123.5 b=false s=newstring u=<4> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3> +010: table simple: i=1 r=123.5 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>] uuid=<2> 011: {"error":null,"result":[{"count":1}]} -012: event:delete, row={i=0 r=123.5 b=false s=newstring u=<4> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3>}, updates=None -012: i=-1 r=125 b=false s=newstring u=<4> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<8> -012: i=1 r=123.5 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>] uuid=<2> +012: event:delete, row={i=0 r=123.5 b=false s=newstring u=<4> ia=[] ra=[] ba=[] sa=[] ua=[]}, uuid=<3>, updates=None +012: table simple: i=-1 r=125 b=false s=newstring u=<4> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<8> +012: table simple: i=1 r=123.5 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>] uuid=<2> 013: reconnect -014: event:create, row={i=-1 r=125 b=false s=newstring u=<4> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<8>}, updates=None -014: event:create, row={i=1 r=123.5 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>] uuid=<2>}, updates=None -014: event:create, row={uuid=<0>}, updates=None -014: event:create, row={uuid=<1>}, updates=None -014: i=-1 r=125 b=false s=newstring u=<4> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<8> -014: i=1 r=123.5 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>] uuid=<2> +014: event:create, row={i=-1 r=125 b=false s=newstring u=<4> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[]}, uuid=<8>, updates=None +014: event:create, row={i=1 r=123.5 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>]}, uuid=<2>, updates=None +014: event:create, row={}, uuid=<0>, updates=None +014: event:create, row={}, uuid=<1>, updates=None +014: table simple: i=-1 r=125 b=false s=newstring u=<4> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<8> +014: table simple: i=1 r=123.5 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>] uuid=<2> 015: done ]]) @@ -1888,10 +2173,10 @@ OVSDB_CHECK_IDL_COMPOUND_INDEX_WITH_REF([set, simple3 idl-compound-index-with-re [], [], [[000: After add to other table + set of strong ref -001: name= uset=[] uref=[[<0>]] +001: table simple3: name= uset=[] uref=[<0>] uuid=<1> 002: check simple4: not empty 003: Query using index with reference -004: name= uset=[] uref=[[<0>]] +004: table simple3: name= uset=[] uref=[<0>] uuid=<1> 005: After delete 007: check simple4: empty 008: End test @@ -1989,11 +2274,11 @@ OVSDB_CHECK_CLUSTER_IDL_C([simple idl, monitor_cond_since, cluster disconnect], [[000: change conditions 001: empty 002: change conditions -003: i=2 r=1 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +003: table simple: i=2 r=1 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> 004: change conditions 005: reconnect -006: i=2 r=1 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> +006: table simple: i=2 r=1 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> 007: {"error":null,"result":[{"count":1}]} -008: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2> +008: table simple: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2> 009: done ]]) diff --git a/tests/system-offloads-traffic.at b/tests/system-offloads-traffic.at index 4f601ef939..c8e4c68fae 100644 --- a/tests/system-offloads-traffic.at +++ b/tests/system-offloads-traffic.at @@ -70,3 +70,53 @@ AT_CHECK([ovs-appctl upcall/show | grep -E "offloaded flows : [[1-9]]"], [0], [i OVS_TRAFFIC_VSWITCHD_STOP AT_CLEANUP + +AT_SETUP([offloads - set ingress_policing_rate and ingress_policing_burst - offloads disabled]) +AT_KEYWORDS([ingress_policing]) +AT_SKIP_IF([test $HAVE_TC = "no"]) +OVS_TRAFFIC_VSWITCHD_START() +AT_CHECK([ovs-vsctl set Open_vSwitch . other_config:hw-offload=false]) +AT_CHECK([ovs-ofctl add-flow br0 "actions=normal"]) +ADD_NAMESPACES(at_ns0) +ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24") +AT_CHECK([ovs-vsctl set interface ovs-p0 ingress_policing_rate=100]) +AT_CHECK([ovs-vsctl set interface ovs-p0 ingress_policing_burst=10]) +AT_CHECK([ovs-vsctl --columns=other_config list open], [0], [dnl +other_config : {hw-offload="false"} +]) +AT_CHECK([tc -o -s -d filter show dev ovs-p0 ingress | + sed -n 's/.*\(rate [[0-9]]*[[a-zA-Z]]* burst [[0-9]]*[[a-zA-Z]]*\).*/\1/; T; p; q'], + [0],[dnl +rate 100Kbit burst 1280b +]) +AT_CHECK([tc -s -d filter show dev ovs-p0 ingress | grep basic | + sed -n 's/.*\(basic\).*/\1/; T; p; q'], [0], [dnl +basic +]) +OVS_TRAFFIC_VSWITCHD_STOP +AT_CLEANUP + +AT_SETUP([offloads - set ingress_policing_rate and ingress_policing_burst - offloads enabled]) +AT_KEYWORDS([ingress_policing]) +AT_SKIP_IF([test $HAVE_TC = "no"]) +OVS_TRAFFIC_VSWITCHD_START() +AT_CHECK([ovs-vsctl set Open_vSwitch . other_config:hw-offload=true]) +AT_CHECK([ovs-ofctl add-flow br0 "actions=normal"]) +ADD_NAMESPACES(at_ns0) +ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24") +AT_CHECK([ovs-vsctl set interface ovs-p0 ingress_policing_rate=100]) +AT_CHECK([ovs-vsctl set interface ovs-p0 ingress_policing_burst=10]) +AT_CHECK([ovs-vsctl --columns=other_config list open], [0], [dnl +other_config : {hw-offload="true"} +]) +AT_CHECK([tc -o -s -d filter show dev ovs-p0 ingress | + sed -n 's/.*\(rate [[0-9]]*[[a-zA-Z]]* burst [[0-9]]*[[a-zA-Z]]*\).*/\1/; T; p; q'], + [0],[dnl +rate 100Kbit burst 1280b +]) +AT_CHECK([tc -o -s -d filter show dev ovs-p0 ingress | grep matchall | + sed -n 's/.*\(matchall\).*/\1/; T; p; q'], [0], [dnl +matchall +]) +OVS_TRAFFIC_VSWITCHD_STOP +AT_CLEANUP diff --git a/tests/test-ovsdb.c b/tests/test-ovsdb.c index 15433e3472..a886f971e7 100644 --- a/tests/test-ovsdb.c +++ b/tests/test-ovsdb.c @@ -1861,6 +1861,23 @@ print_and_log(const char *format, ...) free(message); } +static char * +format_idl_row(const struct ovsdb_idl_row *row, int step, const char *contents) +{ + const char *change_str = + !ovsdb_idl_track_is_set(row->table) + ? "" + : ovsdb_idl_row_get_seqno(row, OVSDB_IDL_CHANGE_INSERT) > 0 + ? "inserted row: " + : ovsdb_idl_row_get_seqno(row, OVSDB_IDL_CHANGE_DELETE) > 0 + ? "deleted row: " + : ""; + + return xasprintf("%03d: table %s: %s%s uuid=" UUID_FMT, + step, row->table->class_->name, change_str, contents, + UUID_ARGS(&row->uuid)); +} + static void print_idl_row_updated_simple(const struct idltest_simple *s, int step) { @@ -1871,7 +1888,9 @@ print_idl_row_updated_simple(const struct idltest_simple *s, int step) } } if (updates.length) { - print_and_log("%03d: updated columns:%s", step, ds_cstr(&updates)); + print_and_log("%03d: table %s: updated columns:%s", + step, s->header_.table->class_->name, + ds_cstr(&updates)); ds_destroy(&updates); } } @@ -1886,7 +1905,9 @@ print_idl_row_updated_link1(const struct idltest_link1 *l1, int step) } } if (updates.length) { - print_and_log("%03d: updated columns:%s", step, ds_cstr(&updates)); + print_and_log("%03d: table %s: updated columns:%s", + step, l1->header_.table->class_->name, + ds_cstr(&updates)); ds_destroy(&updates); } } @@ -1901,7 +1922,43 @@ print_idl_row_updated_link2(const struct idltest_link2 *l2, int step) } } if (updates.length) { - print_and_log("%03d: updated columns:%s", step, ds_cstr(&updates)); + print_and_log("%03d: table %s: updated columns:%s", + step, l2->header_.table->class_->name, + ds_cstr(&updates)); + ds_destroy(&updates); + } +} + +static void +print_idl_row_updated_simple3(const struct idltest_simple3 *s3, int step) +{ + struct ds updates = DS_EMPTY_INITIALIZER; + for (size_t i = 0; i < IDLTEST_SIMPLE3_N_COLUMNS; i++) { + if (idltest_simple3_is_updated(s3, i)) { + ds_put_format(&updates, " %s", idltest_simple3_columns[i].name); + } + } + if (updates.length) { + print_and_log("%03d: table %s: updated columns:%s", + step, s3->header_.table->class_->name, + ds_cstr(&updates)); + ds_destroy(&updates); + } +} + +static void +print_idl_row_updated_simple4(const struct idltest_simple4 *s4, int step) +{ + struct ds updates = DS_EMPTY_INITIALIZER; + for (size_t i = 0; i < IDLTEST_SIMPLE4_N_COLUMNS; i++) { + if (idltest_simple4_is_updated(s4, i)) { + ds_put_format(&updates, " %s", idltest_simple4_columns[i].name); + } + } + if (updates.length) { + print_and_log("%03d: table %s: updated columns:%s", + step, s4->header_.table->class_->name, + ds_cstr(&updates)); ds_destroy(&updates); } } @@ -1916,7 +1973,9 @@ print_idl_row_updated_simple6(const struct idltest_simple6 *s6, int step) } } if (updates.length) { - print_and_log("%03d: updated columns:%s", step, ds_cstr(&updates)); + print_and_log("%03d: table %s: updated columns:%s", + step, s6->header_.table->class_->name, + ds_cstr(&updates)); ds_destroy(&updates); } } @@ -1931,7 +1990,9 @@ print_idl_row_updated_singleton(const struct idltest_singleton *sng, int step) } } if (updates.length) { - print_and_log("%03d: updated columns:%s", step, ds_cstr(&updates)); + print_and_log("%03d: table %s: updated columns:%s", + step, sng->header_.table->class_->name, + ds_cstr(&updates)); ds_destroy(&updates); } } @@ -1940,8 +2001,8 @@ static void print_idl_row_simple(const struct idltest_simple *s, int step) { struct ds msg = DS_EMPTY_INITIALIZER; - ds_put_format(&msg, "%03d: i=%"PRId64" r=%g b=%s s=%s u="UUID_FMT" ia=[", - step, s->i, s->r, s->b ? "true" : "false", + ds_put_format(&msg, "i=%"PRId64" r=%g b=%s s=%s u="UUID_FMT" ia=[", + s->i, s->r, s->b ? "true" : "false", s->s, UUID_ARGS(&s->u)); for (size_t i = 0; i < s->n_ia; i++) { ds_put_format(&msg, "%s%"PRId64, i ? " " : "", s->ia[i]); @@ -1962,9 +2023,12 @@ print_idl_row_simple(const struct idltest_simple *s, int step) for (size_t i = 0; i < s->n_ua; i++) { ds_put_format(&msg, "%s"UUID_FMT, i ? " " : "", UUID_ARGS(&s->ua[i])); } - ds_put_format(&msg, "] uuid="UUID_FMT, UUID_ARGS(&s->header_.uuid)); - print_and_log("%s", ds_cstr(&msg)); + ds_put_cstr(&msg, "]"); + + char *row_msg = format_idl_row(&s->header_, step, ds_cstr(&msg)); + print_and_log("%s", row_msg); ds_destroy(&msg); + free(row_msg); print_idl_row_updated_simple(s, step); } @@ -1973,7 +2037,7 @@ static void print_idl_row_link1(const struct idltest_link1 *l1, int step) { struct ds msg = DS_EMPTY_INITIALIZER; - ds_put_format(&msg, "%03d: i=%"PRId64" k=", step, l1->i); + ds_put_format(&msg, "i=%"PRId64" k=", l1->i); if (l1->k) { ds_put_format(&msg, "%"PRId64, l1->k->i); } @@ -1988,9 +2052,11 @@ print_idl_row_link1(const struct idltest_link1 *l1, int step) if (l1->l2) { ds_put_format(&msg, "%"PRId64, l1->l2->i); } - ds_put_format(&msg, " uuid="UUID_FMT, UUID_ARGS(&l1->header_.uuid)); - print_and_log("%s", ds_cstr(&msg)); + + char *row_msg = format_idl_row(&l1->header_, step, ds_cstr(&msg)); + print_and_log("%s", row_msg); ds_destroy(&msg); + free(row_msg); print_idl_row_updated_link1(l1, step); } @@ -1999,30 +2065,77 @@ static void print_idl_row_link2(const struct idltest_link2 *l2, int step) { struct ds msg = DS_EMPTY_INITIALIZER; - ds_put_format(&msg, "%03d: i=%"PRId64" l1=", step, l2->i); + ds_put_format(&msg, "i=%"PRId64" l1=", l2->i); if (l2->l1) { ds_put_format(&msg, "%"PRId64, l2->l1->i); } - ds_put_format(&msg, " uuid="UUID_FMT, UUID_ARGS(&l2->header_.uuid)); - print_and_log("%s", ds_cstr(&msg)); + + char *row_msg = format_idl_row(&l2->header_, step, ds_cstr(&msg)); + print_and_log("%s", row_msg); ds_destroy(&msg); + free(row_msg); print_idl_row_updated_link2(l2, step); } +static void +print_idl_row_simple3(const struct idltest_simple3 *s3, int step) +{ + struct ds msg = DS_EMPTY_INITIALIZER; + size_t i; + + ds_put_format(&msg, "name=%s uset=[", s3->name); + for (i = 0; i < s3->n_uset; i++) { + ds_put_format(&msg, UUID_FMT"%s", + UUID_ARGS(&s3->uset[i]), + i < s3->n_uset - 1 ? "," : ""); + } + ds_put_cstr(&msg, "] uref=["); + for (i = 0; i < s3->n_uref; i++) { + ds_put_format(&msg, UUID_FMT"%s", + UUID_ARGS(&s3->uref[i]->header_.uuid), + i < s3->n_uref -1 ? "," : ""); + } + ds_put_cstr(&msg, "]"); + + char *row_msg = format_idl_row(&s3->header_, step, ds_cstr(&msg)); + print_and_log("%s", row_msg); + ds_destroy(&msg); + free(row_msg); + + print_idl_row_updated_simple3(s3, step); +} + +static void +print_idl_row_simple4(const struct idltest_simple4 *s4, int step) +{ + struct ds msg = DS_EMPTY_INITIALIZER; + ds_put_format(&msg, "name=%s", s4->name); + + char *row_msg = format_idl_row(&s4->header_, step, ds_cstr(&msg)); + print_and_log("%s", row_msg); + ds_destroy(&msg); + free(row_msg); + + print_idl_row_updated_simple4(s4, step); +} + static void print_idl_row_simple6(const struct idltest_simple6 *s6, int step) { struct ds msg = DS_EMPTY_INITIALIZER; - ds_put_format(&msg, "%03d: name=%s ", step, s6->name); + ds_put_format(&msg, "name=%s ", s6->name); ds_put_cstr(&msg, "weak_ref=["); for (size_t i = 0; i < s6->n_weak_ref; i++) { ds_put_format(&msg, "%s"UUID_FMT, i ? " " : "", UUID_ARGS(&s6->weak_ref[i]->header_.uuid)); } - ds_put_format(&msg, "] uuid="UUID_FMT, UUID_ARGS(&s6->header_.uuid)); - print_and_log("%s", ds_cstr(&msg)); + ds_put_cstr(&msg, "]"); + + char *row_msg = format_idl_row(&s6->header_, step, ds_cstr(&msg)); + print_and_log("%s", row_msg); ds_destroy(&msg); + free(row_msg); print_idl_row_updated_simple6(s6, step); } @@ -2030,14 +2143,23 @@ print_idl_row_simple6(const struct idltest_simple6 *s6, int step) static void print_idl_row_singleton(const struct idltest_singleton *sng, int step) { - print_and_log("%03d: name=%s uuid="UUID_FMT, step, sng->name, - UUID_ARGS(&sng->header_.uuid)); + struct ds msg = DS_EMPTY_INITIALIZER; + ds_put_format(&msg, "name=%s", sng->name); + + char *row_msg = format_idl_row(&sng->header_, step, ds_cstr(&msg)); + print_and_log("%s", row_msg); + ds_destroy(&msg); + free(row_msg); + print_idl_row_updated_singleton(sng, step); } static void print_idl(struct ovsdb_idl *idl, int step) { + const struct idltest_simple3 *s3; + const struct idltest_simple4 *s4; + const struct idltest_simple6 *s6; const struct idltest_simple *s; const struct idltest_link1 *l1; const struct idltest_link2 *l2; @@ -2056,6 +2178,18 @@ print_idl(struct ovsdb_idl *idl, int step) print_idl_row_link2(l2, step); n++; } + IDLTEST_SIMPLE3_FOR_EACH (s3, idl) { + print_idl_row_simple3(s3, step); + n++; + } + IDLTEST_SIMPLE4_FOR_EACH (s4, idl) { + print_idl_row_simple4(s4, step); + n++; + } + IDLTEST_SIMPLE6_FOR_EACH (s6, idl) { + print_idl_row_simple6(s6, step); + n++; + } IDLTEST_SINGLETON_FOR_EACH (sng, idl) { print_idl_row_singleton(sng, step); n++; @@ -2068,6 +2202,8 @@ print_idl(struct ovsdb_idl *idl, int step) static void print_idl_track(struct ovsdb_idl *idl, int step) { + const struct idltest_simple3 *s3; + const struct idltest_simple4 *s4; const struct idltest_simple6 *s6; const struct idltest_simple *s; const struct idltest_link1 *l1; @@ -2076,51 +2212,26 @@ print_idl_track(struct ovsdb_idl *idl, int step) IDLTEST_SIMPLE_FOR_EACH_TRACKED (s, idl) { print_idl_row_simple(s, step); - if (idltest_simple_is_deleted(s)) { - print_and_log("%03d: deleted row: uuid="UUID_FMT, step, - UUID_ARGS(&s->header_.uuid)); - } else if (idltest_simple_is_new(s)) { - print_and_log("%03d: inserted row: uuid="UUID_FMT, step, - UUID_ARGS(&s->header_.uuid)); - } n++; } IDLTEST_LINK1_FOR_EACH_TRACKED (l1, idl) { - if (idltest_link1_is_deleted(l1)) { - print_and_log("%03d: deleted row: uuid="UUID_FMT, step, - UUID_ARGS(&l1->header_.uuid)); - } else { - print_idl_row_link1(l1, step); - if (idltest_link1_is_new(l1)) { - print_and_log("%03d: inserted row: uuid="UUID_FMT, step, - UUID_ARGS(&l1->header_.uuid)); - } - } + print_idl_row_link1(l1, step); n++; } IDLTEST_LINK2_FOR_EACH_TRACKED (l2, idl) { - if (idltest_link2_is_deleted(l2)) { - print_and_log("%03d: deleted row: uuid="UUID_FMT, step, - UUID_ARGS(&l2->header_.uuid)); - } else { - print_idl_row_link2(l2, step); - if (idltest_link2_is_new(l2)) { - print_and_log("%03d: inserted row: uuid="UUID_FMT, step, - UUID_ARGS(&l2->header_.uuid)); - } - - } + print_idl_row_link2(l2, step); + n++; + } + IDLTEST_SIMPLE3_FOR_EACH_TRACKED (s3, idl) { + print_idl_row_simple3(s3, step); + n++; + } + IDLTEST_SIMPLE4_FOR_EACH_TRACKED (s4, idl) { + print_idl_row_simple4(s4, step); n++; } IDLTEST_SIMPLE6_FOR_EACH_TRACKED (s6, idl) { print_idl_row_simple6(s6, step); - if (idltest_simple6_is_deleted(s6)) { - print_and_log("%03d: deleted row: uuid="UUID_FMT, step, - UUID_ARGS(&s6->header_.uuid)); - } else if (idltest_simple6_is_new(s6)) { - print_and_log("%03d: inserted row: uuid="UUID_FMT, step, - UUID_ARGS(&s6->header_.uuid)); - } n++; } @@ -2349,6 +2460,10 @@ find_table_class(const char *name) return &idltest_table_link1; } else if (!strcmp(name, "link2")) { return &idltest_table_link2; + } else if (!strcmp(name, "simple3")) { + return &idltest_table_simple3; + } else if (!strcmp(name, "simple4")) { + return &idltest_table_simple4; } else if (!strcmp(name, "simple6")) { return &idltest_table_simple6; } @@ -2702,27 +2817,6 @@ do_idl_partial_update_map_column(struct ovs_cmdl_context *ctx) printf("%03d: End test\n", step); } -static void -print_idl_row_simple3(const struct idltest_simple3 *s, int step) -{ - size_t i; - const struct ovsdb_datum *uset; - const struct ovsdb_datum *uref; - - uset = idltest_simple3_get_uset(s, OVSDB_TYPE_UUID); - printf("%03d: name=%s uset=[", - step, s->name); - for (i = 0; i < uset->n; i++) { - printf("["UUID_FMT"]%s", UUID_ARGS(&(uset->keys[i].uuid)), i < uset->n-1? ",": ""); - } - uref = idltest_simple3_get_uref(s, OVSDB_TYPE_UUID); - printf("] uref=["); - for (i = 0; i < uref->n; i++) { - printf("["UUID_FMT"]%s", UUID_ARGS(&(uref->keys[i].uuid)), i < uref->n-1? ",": ""); - } - printf("]\n"); -} - static void dump_simple3(struct ovsdb_idl *idl, const struct idltest_simple3 *myRow, diff --git a/tests/test-ovsdb.py b/tests/test-ovsdb.py index a196802743..72a319123e 100644 --- a/tests/test-ovsdb.py +++ b/tests/test-ovsdb.py @@ -162,6 +162,10 @@ def get_simple_printable_row_string(row, columns): if isinstance(value, dict): value = sorted((row_to_uuid(k), row_to_uuid(v)) for k, v in value.items()) + if isinstance(value, (list, tuple)): + value = sorted((row_to_uuid(v) for v in value)) + elif isinstance(value, list): + value = sorted(row_to_uuid(v) for v in value) s += "%s=%s " % (column, value) s = s.strip() s = re.sub('""|,|u?\'', "", s) @@ -172,9 +176,10 @@ def get_simple_printable_row_string(row, columns): return s -def get_simple_table_printable_row(row): +def get_simple_table_printable_row(row, *additional_columns): simple_columns = ["i", "r", "b", "s", "u", "ia", - "ra", "ba", "sa", "ua", "uuid"] + "ra", "ba", "sa", "ua"] + simple_columns.extend(additional_columns) return get_simple_printable_row_string(row, simple_columns) @@ -184,81 +189,118 @@ def get_simple2_table_printable_row(row): def get_simple3_table_printable_row(row): - simple3_columns = ["name", "uset"] + simple3_columns = ["name", "uset", "uref"] return get_simple_printable_row_string(row, simple3_columns) +def get_simple4_table_printable_row(row): + simple4_columns = ["name"] + return get_simple_printable_row_string(row, simple4_columns) + + +def get_simple5_table_printable_row(row): + simple5_columns = ["name", "irefmap"] + return get_simple_printable_row_string(row, simple5_columns) + + +def get_simple6_table_printable_row(row): + simple6_columns = ["name", "weak_ref"] + return get_simple_printable_row_string(row, simple6_columns) + + +def get_link1_table_printable_row(row): + s = ["i=%s k=" % row.i] + if hasattr(row, "k") and row.k: + s.append(str(row.k.i)) + if hasattr(row, "ka"): + s.append(" ka=[") + s.append(' '.join(sorted(str(ka.i) for ka in row.ka))) + s.append("] l2=") + if hasattr(row, "l2") and row.l2: + s.append(str(row.l2[0].i)) + return ''.join(s) + + +def get_link2_table_printable_row(row): + s = "i=%s l1=" % row.i + if hasattr(row, "l1") and row.l1: + s += str(row.l1[0].i) + return s + + +def get_singleton_table_printable_row(row): + return "name=%s" % row.name + + +def print_row(table, row, step, contents): + s = "%03d: table %s: %s " % (step, table, contents) + s += get_simple_printable_row_string(row, ["uuid"]) + print(s) + + def print_idl(idl, step): n = 0 if "simple" in idl.tables: simple = idl.tables["simple"].rows for row in simple.values(): - s = "%03d: " % step - s += get_simple_table_printable_row(row) - print(s) + print_row("simple", row, step, + get_simple_table_printable_row(row)) n += 1 if "simple2" in idl.tables: simple2 = idl.tables["simple2"].rows for row in simple2.values(): - s = "%03d: " % step - s += get_simple2_table_printable_row(row) - print(s) + print_row("simple2", row, step, + get_simple2_table_printable_row(row)) n += 1 if "simple3" in idl.tables: simple3 = idl.tables["simple3"].rows for row in simple3.values(): - s = "%03d: " % step - s += get_simple3_table_printable_row(row) - print(s) + print_row("simple3", row, step, + get_simple3_table_printable_row(row)) + n += 1 + + if "simple4" in idl.tables: + simple4 = idl.tables["simple4"].rows + for row in simple4.values(): + print_row("simple4", row, step, + get_simple4_table_printable_row(row)) n += 1 if "simple5" in idl.tables: simple5 = idl.tables["simple5"].rows for row in simple5.values(): - s = "%03d: " % step - s += get_simple_printable_row_string(row, ["name", "irefmap"]) - print(s) + print_row("simple5", row, step, + get_simple5_table_printable_row(row)) + n += 1 + + if "simple6" in idl.tables: + simple6 = idl.tables["simple6"].rows + for row in simple6.values(): + print_row("simple6", row, step, + get_simple6_table_printable_row(row)) n += 1 if "link1" in idl.tables: l1 = idl.tables["link1"].rows for row in l1.values(): - s = ["%03d: i=%s k=" % (step, row.i)] - if hasattr(row, "k") and row.k: - s.append(str(row.k.i)) - if hasattr(row, "ka"): - s.append(" ka=[") - s.append(' '.join(sorted(str(ka.i) for ka in row.ka))) - s.append("] l2=") - if hasattr(row, "l2") and row.l2: - s.append(str(row.l2[0].i)) - if hasattr(row, "uuid"): - s.append(" uuid=%s" % row.uuid) - print(''.join(s)) + print_row("link1", row, step, + get_link1_table_printable_row(row)) n += 1 if "link2" in idl.tables: l2 = idl.tables["link2"].rows for row in l2.values(): - s = ["%03d:" % step] - s.append(" i=%s l1=" % row.i) - if hasattr(row, "l1") and row.l1: - s.append(str(row.l1[0].i)) - if hasattr(row, "uuid"): - s.append(" uuid=%s" % row.uuid) - print(''.join(s)) + print_row("link2", row, step, + get_link2_table_printable_row(row)) n += 1 if "singleton" in idl.tables: sng = idl.tables["singleton"].rows for row in sng.values(): - s = ["%03d:" % step] - s.append(" name=%s" % row.name) - if hasattr(row, "uuid"): - s.append(" uuid=%s" % row.uuid) - print(''.join(s)) + print_row("singleton", row, step, + get_singleton_table_printable_row(row)) n += 1 if not n: @@ -637,7 +679,8 @@ def do_idl(schema_file, remote, *commands): def mock_notify(event, row, updates=None): output = "%03d: " % step output += "event:" + str(event) + ", row={" - output += get_simple_table_printable_row(row) + "}, updates=" + output += get_simple_table_printable_row(row, 'l2', 'l1') + "}, " + output += get_simple_printable_row_string(row, ["uuid"]) + ", updates=" if updates is None: output += "None" else: diff --git a/utilities/ovs-ctl.in b/utilities/ovs-ctl.in index d71c34e691..4156da20ef 100644 --- a/utilities/ovs-ctl.in +++ b/utilities/ovs-ctl.in @@ -226,7 +226,9 @@ start_forwarding () { if test X"$OVS_VSWITCHD" = Xyes; then do_start_forwarding || return 1 fi - set_hostname & + if test X"$RECORD_HOSTNAME" = Xyes; then + set_hostname & + fi return 0 } @@ -317,6 +319,7 @@ set_defaults () { SYSTEM_ID= FULL_HOSTNAME=yes + RECORD_HOSTNAME=yes DELETE_BRIDGES=no DELETE_TRANSIENT_PORTS=no @@ -378,19 +381,24 @@ This program is intended to be invoked internally by Open vSwitch startup scripts. System administrators should not normally invoke it directly. Commands: - start start Open vSwitch daemons - stop stop Open vSwitch daemons - restart stop and start Open vSwitch daemons - status check whether Open vSwitch daemons are running - version print versions of Open vSwitch daemons - load-kmod insert modules if not already present - force-reload-kmod save OVS network device state, stop OVS, unload kernel - module, reload kernel module, start OVS, restore state - enable-protocol enable protocol specified in options with iptables - delete-transient-ports delete transient (other_config:transient=true) ports - start-ovs-ipsec start Open vSwitch ipsec daemon - stop-ovs-ipsec stop Open vSwitch ipsec daemon - help display this help message + start start Open vSwitch daemons + stop stop Open vSwitch daemons + restart stop and start Open vSwitch daemons + status check whether Open vSwitch daemons are running + version print versions of Open vSwitch daemons + load-kmod insert modules if not already present + force-reload-kmod save OVS network device state, stop OVS, unload + kernel module, reload kernel module, start OVS, + restore state + enable-protocol enable protocol specified in options with + iptables + delete-transient-ports delete transient (other_config:transient=true) + ports + start-ovs-ipsec start Open vSwitch ipsec daemon + stop-ovs-ipsec stop Open vSwitch ipsec daemon + record-hostname-if-not-set determine the system hostname and record it in + the Open vSwitch database if not already set + help display this help message One of the following options is required for "start", "restart" and "force-reload-kmod": --system-id=UUID set specific ID to uniquely identify this system @@ -411,6 +419,8 @@ Less important options for "start", "restart" and "force-reload-kmod": --ovsdb-server-priority=NICE set ovsdb-server's niceness (default: $OVSDB_SERVER_PRIORITY) --ovs-vswitchd-priority=NICE set ovs-vswitchd's niceness (default: $OVS_VSWITCHD_PRIORITY) --no-full-hostname set short hostname instead of full hostname + --no-record-hostname do not attempt to determine/record system + hostname as part of start command Debugging options for "start", "restart" and "force-reload-kmod": --ovsdb-server-wrapper=WRAPPER @@ -569,6 +579,9 @@ case $command in stop-ovs-ipsec) stop_ovs_ipsec ;; + record-hostname-if-not-set) + set_hostname + ;; help) usage ;; diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c index 3601890f40..62059e962f 100644 --- a/utilities/ovs-ofctl.c +++ b/utilities/ovs-ofctl.c @@ -4020,6 +4020,7 @@ ofctl_meter_mod__(const char *bridge, const char *str, int command) enum ofputil_protocol usable_protocols; enum ofp_version version; + memset(&mm, 0, sizeof mm); if (str) { char *error; error = parse_ofp_meter_mod_str(&mm, str, command, &usable_protocols); @@ -4030,7 +4031,6 @@ ofctl_meter_mod__(const char *bridge, const char *str, int command) usable_protocols = OFPUTIL_P_OF13_UP; mm.command = command; mm.meter.meter_id = OFPM13_ALL; - mm.meter.bands = NULL; } protocol = open_vconn_for_flow_mod(bridge, &vconn, usable_protocols); @@ -4050,6 +4050,7 @@ ofctl_meter_request__(const char *bridge, const char *str, enum ofputil_protocol protocol; enum ofp_version version; + memset(&mm, 0, sizeof mm); if (str) { char *error; error = parse_ofp_meter_mod_str(&mm, str, -1, &usable_protocols); @@ -4059,7 +4060,6 @@ ofctl_meter_request__(const char *bridge, const char *str, } else { usable_protocols = OFPUTIL_P_OF13_UP; mm.meter.meter_id = OFPM13_ALL; - mm.meter.bands = NULL; } protocol = open_vconn_for_flow_mod(bridge, &vconn, usable_protocols); diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml index a2ad84edef..4597a215d9 100644 --- a/vswitchd/vswitch.xml +++ b/vswitchd/vswitch.xml @@ -4660,7 +4660,8 @@ ovs-vsctl add-port br0 p0 -- set Interface p0 type=patch options:peer=p1 \ packets per second the CIR would be set to to to 46000000. This value can be broken into '1,000,000 x 46'. Where 1,000,000 is the policing rate for the number of packets per second and 46 represents the size - of the packet data for a 64 byte ip packet. + of the packet data for a 64 bytes IP packet without 14 bytes Ethernet + and 4 bytes FCS header. The Committed Burst Size (CBS) is measured in bytes and represents a @@ -4681,7 +4682,8 @@ ovs-vsctl add-port br0 p0 -- set Interface p0 type=patch options:peer=p1 \ packets per second the EIR would be set to to to 46000000. This value can be broken into '1,000,000 x 46'. Where 1,000,000 is the policing rate for the number of packets per second and 46 represents the size - of the packet data for a 64 byte ip packet. + of the packet data for a 64 bytes IP packet without 14 bytes Ethernet + and 4 bytes FCS header. The Excess Burst Size (EBS) is measured in bytes and represents a