diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/acinclude.m4 openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/acinclude.m4
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/acinclude.m4 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/acinclude.m4 2020-03-11 16:15:44.000000000 +0000
@@ -183,6 +183,8 @@
[AC_DEFINE([HAVE_TCA_FLOWER_KEY_FLAGS_FRAG_IS_FIRST], [1],
[Define to 1 if TCA_FLOWER_KEY_FLAGS_FRAG_IS_FIRST is avaiable.])])
+ AC_CHECK_MEMBERS([struct tcf_t.firstuse], [], [], [#include ])
+
AC_COMPILE_IFELSE([
AC_LANG_PROGRAM([#include ], [
int x = TCA_VLAN_PUSH_VLAN_PRIORITY;
@@ -242,7 +244,6 @@
esac
DPDK_LIB="-ldpdk"
- DPDK_EXTRA_LIB=""
ovs_save_CFLAGS="$CFLAGS"
ovs_save_LDFLAGS="$LDFLAGS"
@@ -255,13 +256,12 @@
AC_LANG_PROGRAM(
[
#include
-#if RTE_LIBRTE_VHOST_NUMA
+#if defined(RTE_LIBRTE_VHOST_NUMA) || defined(RTE_EAL_NUMA_AWARE_HUGEPAGES)
#error
#endif
], [])
], [],
[AC_SEARCH_LIBS([get_mempolicy],[numa],[],[AC_MSG_ERROR([unable to find libnuma, install the dependency package])])
- DPDK_EXTRA_LIB="-lnuma"
AC_DEFINE([VHOST_NUMA], [1], [NUMA Aware vHost support detected in DPDK.])])
AC_COMPILE_IFELSE([
@@ -274,7 +274,6 @@
], [])
], [],
[AC_SEARCH_LIBS([pcap_dump],[pcap],[],[AC_MSG_ERROR([unable to find libpcap, install the dependency package])])
- DPDK_EXTRA_LIB="-lpcap"
AC_COMPILE_IFELSE([
AC_LANG_PROGRAM(
[
@@ -297,7 +296,7 @@
DPDKLIB_FOUND=false
save_LIBS=$LIBS
for extras in "" "-ldl"; do
- LIBS="$DPDK_LIB $extras $save_LIBS $DPDK_EXTRA_LIB"
+ LIBS="$DPDK_LIB $extras $save_LIBS"
AC_LINK_IFELSE(
[AC_LANG_PROGRAM([#include
#include ],
@@ -467,8 +466,10 @@
OVS_GREP_IFELSE([$KSRC/include/linux/err.h], [IS_ERR_OR_NULL])
OVS_GREP_IFELSE([$KSRC/include/linux/err.h], [PTR_ERR_OR_ZERO])
- OVS_GREP_IFELSE([$KSRC/include/linux/jump_label.h], [DEFINE_STATIC_KEY_FALSE],
+ OVS_GREP_IFELSE([$KSRC/include/linux/jump_label.h], [static_branch_unlikely(],
[OVS_DEFINE([HAVE_UPSTREAM_STATIC_KEY])])
+ OVS_GREP_IFELSE([$KSRC/include/linux/jump_label.h], [DEFINE_STATIC_KEY_FALSE],
+ [OVS_DEFINE([HAVE_DEFINE_STATIC_KEY])])
OVS_GREP_IFELSE([$KSRC/include/linux/etherdevice.h], [eth_hw_addr_random])
OVS_GREP_IFELSE([$KSRC/include/linux/etherdevice.h], [ether_addr_copy])
@@ -584,6 +585,8 @@
[ndo_change_mtu], [OVS_DEFINE([HAVE_RHEL7_MAX_MTU])])
OVS_GREP_IFELSE([$KSRC/include/linux/netfilter.h], [nf_hook_state])
+ OVS_FIND_FIELD_IFELSE([$KSRC/include/linux/netfilter.h], [nf_hook_state],
+ [struct net ], [OVS_DEFINE([HAVE_NF_HOOK_STATE_NET])])
OVS_GREP_IFELSE([$KSRC/include/linux/netfilter.h], [nf_register_net_hook])
OVS_GREP_IFELSE([$KSRC/include/linux/netfilter.h], [nf_hookfn.*nf_hook_ops],
[OVS_DEFINE([HAVE_NF_HOOKFN_ARG_OPS])])
@@ -615,8 +618,8 @@
[nf_ct_is_untracked])
OVS_GREP_IFELSE([$KSRC/include/net/netfilter/nf_conntrack_zones.h],
[nf_ct_zone_init])
- OVS_FIND_FIELD_IFELSE([$KSRC/include/net/netfilter/nf_conntrack_l3proto.h],
- [net_ns_get])
+ OVS_GREP_IFELSE([$KSRC/include/net/netfilter/nf_conntrack_l3proto.h],
+ [net_ns_get])
OVS_GREP_IFELSE([$KSRC/include/net/netfilter/nf_conntrack_labels.h],
[nf_connlabels_get])
OVS_FIND_PARAM_IFELSE([$KSRC/include/net/netfilter/nf_conntrack_labels.h],
@@ -893,6 +896,27 @@
[OVS_DEFINE([HAVE_VOID_NDO_GET_STATS64])])
OVS_GREP_IFELSE([$KSRC/include/linux/timer.h], [init_timer_deferrable],
[OVS_DEFINE([HAVE_INIT_TIMER_DEFERRABLE])])
+ OVS_FIND_FIELD_IFELSE([$KSRC/include/net/inet_frag.h], [inet_frags],
+ [rnd],
+ [OVS_DEFINE([HAVE_INET_FRAGS_RND])])
+ OVS_GREP_IFELSE([$KSRC/include/linux/overflow.h], [__LINUX_OVERFLOW_H],
+ [OVS_DEFINE([HAVE_OVERFLOW_H])])
+ OVS_GREP_IFELSE([$KSRC/include/linux/overflow.h], [struct_size],
+ [OVS_DEFINE([HAVE_STRUCT_SIZE])])
+ OVS_GREP_IFELSE([$KSRC/include/linux/mm.h], [kvmalloc_array],
+ [OVS_DEFINE([HAVE_KVMALLOC_ARRAY])])
+ OVS_GREP_IFELSE([$KSRC/include/linux/mm.h], [kvmalloc_node],
+ [OVS_DEFINE([HAVE_KVMALLOC_NODE])])
+ OVS_GREP_IFELSE([$KSRC/include/net/netfilter/nf_conntrack_l3proto.h],
+ [nf_conntrack_l3proto],
+ [OVS_DEFINE([HAVE_NF_CONNTRACK_L3PROATO_H])])
+ OVS_FIND_PARAM_IFELSE([$KSRC/include/net/netfilter/nf_conntrack_core.h],
+ [nf_conntrack_in], [nf_hook_state],
+ [OVS_DEFINE([HAVE_NF_CONNTRACK_IN_TAKES_NF_HOOK_STATE])])
+ OVS_GREP_IFELSE([$KSRC/include/net/ipv6_frag.h], [IP6_DEFRAG_CONNTRACK_IN],
+ [OVS_DEFINE([HAVE_IPV6_FRAG_H])])
+ OVS_GREP_IFELSE([$KSRC/include/net/dst_ops.h], [bool confirm_neigh],
+ [OVS_DEFINE([HAVE_DST_OPS_CONFIRM_NEIGH])])
if cmp -s datapath/linux/kcompat.h.new \
datapath/linux/kcompat.h >/dev/null 2>&1; then
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/build-aux/generate-dhparams-c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/build-aux/generate-dhparams-c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/build-aux/generate-dhparams-c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/build-aux/generate-dhparams-c 2020-03-11 16:15:44.000000000 +0000
@@ -25,6 +25,7 @@
(openssl dhparam -C -in lib/dh1024.pem -noout &&
openssl dhparam -C -in lib/dh2048.pem -noout &&
openssl dhparam -C -in lib/dh4096.pem -noout) | sed '
+ s/^static DH/DH/
s/\(get_dh[0-9]*\)()/\1(void)/
s/\(DH_set0_pqg\)/my_\1/
s/[ ]*$//
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/configure.ac openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/configure.ac
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/configure.ac 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/configure.ac 2020-03-11 16:15:44.000000000 +0000
@@ -13,7 +13,7 @@
# limitations under the License.
AC_PREREQ(2.63)
-AC_INIT(openvswitch, 2.10.1, bugs@openvswitch.org)
+AC_INIT(openvswitch, 2.10.5, bugs@openvswitch.org)
AC_CONFIG_SRCDIR([datapath/datapath.c])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_AUX_DIR([build-aux])
@@ -110,7 +110,7 @@
#include ]])
AC_CHECK_FUNCS([mlockall strnlen getloadavg statvfs getmntent_r sendmmsg clock_gettime])
AC_CHECK_HEADERS([mntent.h sys/statvfs.h linux/types.h linux/if_ether.h])
-AC_CHECK_HEADERS([linux/net_namespace.h stdatomic.h])
+AC_CHECK_HEADERS([linux/net_namespace.h stdatomic.h bits/floatn-common.h])
AC_CHECK_HEADERS([net/if_mib.h], [], [], [[#include
#include ]])
@@ -173,6 +173,7 @@
OVS_ENABLE_OPTION([-Qunused-arguments])
OVS_ENABLE_OPTION([-Wshadow])
OVS_ENABLE_OPTION([-Wno-null-pointer-arithmetic])
+OVS_ENABLE_OPTION([-Warray-bounds-pointer-arithmetic])
OVS_CONDITIONAL_CC_OPTION([-Wno-unused], [HAVE_WNO_UNUSED])
OVS_CONDITIONAL_CC_OPTION([-Wno-unused-parameter], [HAVE_WNO_UNUSED_PARAMETER])
OVS_ENABLE_WERROR
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/compat.h openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/compat.h
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/compat.h 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/compat.h 2020-03-11 16:15:44.000000000 +0000
@@ -28,6 +28,13 @@
#include
#include
+/* Fix grsecurity patch compilation issue. */
+#ifdef CONSTIFY_PLUGIN
+#include
+#undef __read_mostly
+#define __read_mostly
+#endif
+
/* Even though vanilla 3.10 kernel has grp->id, RHEL 7 kernel is missing
* this field. */
#ifdef HAVE_GENL_MULTICAST_GROUP_WITH_ID
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/conntrack.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/conntrack.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/conntrack.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/conntrack.c 2020-03-11 16:15:44.000000000 +0000
@@ -31,6 +31,7 @@
#include
#include
#include
+#include
#ifdef CONFIG_NF_NAT_NEEDED
#include
@@ -569,6 +570,11 @@
return -EPFNOSUPPORT;
}
+ /* The key extracted from the fragment that completed this datagram
+ * likely didn't have an L4 header, so regenerate it.
+ */
+ ovs_flow_key_update_l3l4(skb, key);
+
key->ip.frag = OVS_FRAG_TYPE_NONE;
skb_clear_hash(skb);
skb->ignore_df = 1;
@@ -987,6 +993,11 @@
struct nf_conn *ct;
if (!cached) {
+ struct nf_hook_state state = {
+ .hook = NF_INET_PRE_ROUTING,
+ .pf = info->family,
+ .net = net,
+ };
struct nf_conn *tmpl = info->ct;
int err;
@@ -998,8 +1009,7 @@
nf_ct_set(skb, tmpl, IP_CT_NEW);
}
- err = nf_conntrack_in(net, info->family,
- NF_INET_PRE_ROUTING, skb);
+ err = nf_conntrack_in(skb, &state);
if (err != NF_ACCEPT)
return -ENOENT;
@@ -1687,10 +1697,6 @@
OVS_NLERR(log, "Failed to allocate conntrack template");
return -ENOMEM;
}
-
- __set_bit(IPS_CONFIRMED_BIT, &ct_info.ct->status);
- nf_conntrack_get(&ct_info.ct->ct_general);
-
if (helper) {
err = ovs_ct_add_helper(&ct_info, helper, key, log);
if (err)
@@ -1702,6 +1708,8 @@
if (err)
goto err_free_ct;
+ __set_bit(IPS_CONFIRMED_BIT, &ct_info.ct->status);
+ nf_conntrack_get(&ct_info.ct->ct_general);
return 0;
err_free_ct:
__ovs_ct_free_action(&ct_info);
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/flow.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/flow.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/flow.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/flow.c 2020-03-11 16:15:44.000000000 +0000
@@ -254,21 +254,18 @@
static int parse_ipv6hdr(struct sk_buff *skb, struct sw_flow_key *key)
{
+ unsigned short frag_off;
+ unsigned int payload_ofs = 0;
unsigned int nh_ofs = skb_network_offset(skb);
unsigned int nh_len;
- int payload_ofs;
struct ipv6hdr *nh;
- uint8_t nexthdr;
- __be16 frag_off;
- int err;
+ int err, nexthdr, flags = 0;
err = check_header(skb, nh_ofs + sizeof(*nh));
if (unlikely(err))
return err;
nh = ipv6_hdr(skb);
- nexthdr = nh->nexthdr;
- payload_ofs = (u8 *)(nh + 1) - skb->data;
key->ip.proto = NEXTHDR_NONE;
key->ip.tos = ipv6_get_dsfield(nh);
@@ -277,22 +274,23 @@
key->ipv6.addr.src = nh->saddr;
key->ipv6.addr.dst = nh->daddr;
- payload_ofs = ipv6_skip_exthdr(skb, payload_ofs, &nexthdr, &frag_off);
-
- if (frag_off) {
- if (frag_off & htons(~0x7))
+ nexthdr = ipv6_find_hdr(skb, &payload_ofs, -1, &frag_off, &flags);
+ if (flags & IP6_FH_F_FRAG) {
+ if (frag_off) {
key->ip.frag = OVS_FRAG_TYPE_LATER;
- else
- key->ip.frag = OVS_FRAG_TYPE_FIRST;
+ key->ip.proto = nexthdr;
+ return 0;
+ }
+ key->ip.frag = OVS_FRAG_TYPE_FIRST;
} else {
key->ip.frag = OVS_FRAG_TYPE_NONE;
}
- /* Delayed handling of error in ipv6_skip_exthdr() as it
- * always sets frag_off to a valid value which may be
+ /* Delayed handling of error in ipv6_find_hdr() as it
+ * always sets flags and frag_off to a valid value which may be
* used to set key->ip.frag above.
*/
- if (unlikely(payload_ofs < 0))
+ if (unlikely(nexthdr < 0))
return -EPROTO;
nh_len = payload_ofs - nh_ofs;
@@ -543,79 +541,14 @@
}
/**
- * key_extract - extracts a flow key from an Ethernet frame.
+ * key_extract_l3l4 - extracts L3/L4 header information.
* @skb: sk_buff that contains the frame, with skb->data pointing to the
- * Ethernet header
+ * L3 header
* @key: output flow key
- *
- * The caller must ensure that skb->len >= ETH_HLEN.
- *
- * Returns 0 if successful, otherwise a negative errno value.
- *
- * Initializes @skb header fields as follows:
- *
- * - skb->mac_header: the L2 header.
- *
- * - skb->network_header: just past the L2 header, or just past the
- * VLAN header, to the first byte of the L2 payload.
- *
- * - skb->transport_header: If key->eth.type is ETH_P_IP or ETH_P_IPV6
- * on output, then just past the IP header, if one is present and
- * of a correct length, otherwise the same as skb->network_header.
- * For other key->eth.type values it is left untouched.
- *
- * - skb->protocol: the type of the data starting at skb->network_header.
- * Equals to key->eth.type.
*/
-static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
+static int key_extract_l3l4(struct sk_buff *skb, struct sw_flow_key *key)
{
int error;
- struct ethhdr *eth;
-
- /* Flags are always used as part of stats */
- key->tp.flags = 0;
-
- skb_reset_mac_header(skb);
-
- /* Link layer. */
- clear_vlan(key);
- if (ovs_key_mac_proto(key) == MAC_PROTO_NONE) {
- if (unlikely(eth_type_vlan(skb->protocol)))
- return -EINVAL;
-
- skb_reset_network_header(skb);
- key->eth.type = skb->protocol;
- } else {
- eth = eth_hdr(skb);
- ether_addr_copy(key->eth.src, eth->h_source);
- ether_addr_copy(key->eth.dst, eth->h_dest);
-
- __skb_pull(skb, 2 * ETH_ALEN);
- /* We are going to push all headers that we pull, so no need to
- * update skb->csum here.
- */
-
- if (unlikely(parse_vlan(skb, key)))
- return -ENOMEM;
-
- key->eth.type = parse_ethertype(skb);
- if (unlikely(key->eth.type == htons(0)))
- return -ENOMEM;
-
- /* Multiple tagged packets need to retain TPID to satisfy
- * skb_vlan_pop(), which will later shift the ethertype into
- * skb->protocol.
- */
- if (key->eth.cvlan.tci & htons(VLAN_TAG_PRESENT))
- skb->protocol = key->eth.cvlan.tpid;
- else
- skb->protocol = key->eth.type;
-
- skb_reset_network_header(skb);
- __skb_push(skb, skb->data - skb_mac_header(skb));
- }
-
- skb_reset_mac_len(skb);
/* Network layer. */
if (key->eth.type == htons(ETH_P_IP)) {
@@ -644,6 +577,7 @@
offset = nh->frag_off & htons(IP_OFFSET);
if (offset) {
key->ip.frag = OVS_FRAG_TYPE_LATER;
+ memset(&key->tp, 0, sizeof(key->tp));
return 0;
}
#ifdef HAVE_SKB_GSO_UDP
@@ -766,8 +700,10 @@
return error;
}
- if (key->ip.frag == OVS_FRAG_TYPE_LATER)
+ if (key->ip.frag == OVS_FRAG_TYPE_LATER) {
+ memset(&key->tp, 0, sizeof(key->tp));
return 0;
+ }
#ifdef HAVE_SKB_GSO_UDP
if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP)
key->ip.frag = OVS_FRAG_TYPE_FIRST;
@@ -816,6 +752,92 @@
return 0;
}
+/**
+ * key_extract - extracts a flow key from an Ethernet frame.
+ * @skb: sk_buff that contains the frame, with skb->data pointing to the
+ * Ethernet header
+ * @key: output flow key
+ *
+ * The caller must ensure that skb->len >= ETH_HLEN.
+ *
+ * Returns 0 if successful, otherwise a negative errno value.
+ *
+ * Initializes @skb header fields as follows:
+ *
+ * - skb->mac_header: the L2 header.
+ *
+ * - skb->network_header: just past the L2 header, or just past the
+ * VLAN header, to the first byte of the L2 payload.
+ *
+ * - skb->transport_header: If key->eth.type is ETH_P_IP or ETH_P_IPV6
+ * on output, then just past the IP header, if one is present and
+ * of a correct length, otherwise the same as skb->network_header.
+ * For other key->eth.type values it is left untouched.
+ *
+ * - skb->protocol: the type of the data starting at skb->network_header.
+ * Equals to key->eth.type.
+ */
+static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
+{
+ struct ethhdr *eth;
+
+ /* Flags are always used as part of stats */
+ key->tp.flags = 0;
+
+ skb_reset_mac_header(skb);
+
+ /* Link layer. */
+ clear_vlan(key);
+ if (ovs_key_mac_proto(key) == MAC_PROTO_NONE) {
+ if (unlikely(eth_type_vlan(skb->protocol)))
+ return -EINVAL;
+
+ skb_reset_network_header(skb);
+ key->eth.type = skb->protocol;
+ } else {
+ eth = eth_hdr(skb);
+ ether_addr_copy(key->eth.src, eth->h_source);
+ ether_addr_copy(key->eth.dst, eth->h_dest);
+
+ __skb_pull(skb, 2 * ETH_ALEN);
+ /* We are going to push all headers that we pull, so no need to
+ * update skb->csum here.
+ */
+
+ if (unlikely(parse_vlan(skb, key)))
+ return -ENOMEM;
+
+ key->eth.type = parse_ethertype(skb);
+ if (unlikely(key->eth.type == htons(0)))
+ return -ENOMEM;
+
+ /* Multiple tagged packets need to retain TPID to satisfy
+ * skb_vlan_pop(), which will later shift the ethertype into
+ * skb->protocol.
+ */
+ if (key->eth.cvlan.tci & htons(VLAN_CFI_MASK))
+ skb->protocol = key->eth.cvlan.tpid;
+ else
+ skb->protocol = key->eth.type;
+
+ skb_reset_network_header(skb);
+ __skb_push(skb, skb->data - skb_mac_header(skb));
+ }
+
+ skb_reset_mac_len(skb);
+
+ /* Fill out L3/L4 key info, if any */
+ return key_extract_l3l4(skb, key);
+}
+
+/* In the case of conntrack fragment handling it expects L3 headers,
+ * add a helper.
+ */
+int ovs_flow_key_update_l3l4(struct sk_buff *skb, struct sw_flow_key *key)
+{
+ return key_extract_l3l4(skb, key);
+}
+
int ovs_flow_key_update(struct sk_buff *skb, struct sw_flow_key *key)
{
int res;
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/flow.h openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/flow.h
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/flow.h 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/flow.h 2020-03-11 16:15:44.000000000 +0000
@@ -284,6 +284,7 @@
/* Update the non-metadata part of the flow key using skb. */
int ovs_flow_key_update(struct sk_buff *skb, struct sw_flow_key *key);
+int ovs_flow_key_update_l3l4(struct sk_buff *skb, struct sw_flow_key *key);
int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info,
struct sk_buff *skb,
struct sw_flow_key *key);
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/flow_netlink.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/flow_netlink.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/flow_netlink.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/flow_netlink.c 2020-03-11 16:15:44.000000000 +0000
@@ -502,7 +502,7 @@
return -EINVAL;
}
- if (!nz || !is_all_zero(nla_data(nla), expected_len)) {
+ if (!nz || !is_all_zero(nla_data(nla), nla_len(nla))) {
attrs |= 1ULL << type;
a[type] = nla;
}
@@ -2311,14 +2311,14 @@
struct sw_flow_actions *acts;
int new_acts_size;
- int req_size = NLA_ALIGN(attr_len);
+ size_t req_size = NLA_ALIGN(attr_len);
int next_offset = offsetof(struct sw_flow_actions, actions) +
(*sfa)->actions_len;
if (req_size <= (ksize(*sfa) - next_offset))
goto out;
- new_acts_size = ksize(*sfa) * 2;
+ new_acts_size = max(next_offset + req_size, ksize(*sfa) * 2);
if (new_acts_size > MAX_ACTIONS_BUFSIZE) {
if ((MAX_ACTIONS_BUFSIZE - next_offset) < req_size) {
@@ -2998,7 +2998,7 @@
* is already present */
if (mac_proto != MAC_PROTO_NONE)
return -EINVAL;
- mac_proto = MAC_PROTO_NONE;
+ mac_proto = MAC_PROTO_ETHERNET;
break;
case OVS_ACTION_ATTR_POP_ETH:
@@ -3006,7 +3006,7 @@
return -EINVAL;
if (vlan_tci & htons(VLAN_TAG_PRESENT))
return -EINVAL;
- mac_proto = MAC_PROTO_ETHERNET;
+ mac_proto = MAC_PROTO_NONE;
break;
case OVS_ACTION_ATTR_PUSH_NSH:
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/linux/compat/include/linux/mm.h openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/linux/compat/include/linux/mm.h
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/linux/compat/include/linux/mm.h 1970-01-01 00:00:00.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/linux/compat/include/linux/mm.h 2020-03-11 16:15:44.000000000 +0000
@@ -0,0 +1,44 @@
+#ifndef OVS_MM_H
+#define OVS_MM_H
+
+#include
+
+#ifndef HAVE_KVMALLOC_ARRAY
+#ifndef HAVE_KVMALLOC_NODE
+extern void *vmalloc_node(unsigned long size, int node);
+#define kvmalloc_node(a, b, c) vmalloc_node(a, c)
+#else
+extern void *kvmalloc_node(size_t size, gfp_t flags, int node);
+#endif /* HAVE_KVMALLOC_NODE */
+static inline void *kvmalloc(size_t size, gfp_t flags)
+{
+ return kvmalloc_node(size, flags, NUMA_NO_NODE);
+}
+static inline void *kvzalloc_node(size_t size, gfp_t flags, int node)
+{
+ return kvmalloc_node(size, flags | __GFP_ZERO, node);
+}
+static inline void *kvzalloc(size_t size, gfp_t flags)
+{
+ return kvmalloc(size, flags | __GFP_ZERO);
+}
+
+static inline void *kvmalloc_array(size_t n, size_t size, gfp_t flags)
+{
+ size_t bytes;
+
+ if (unlikely(check_mul_overflow(n, size, &bytes)))
+ return NULL;
+
+ return kvmalloc(bytes, flags);
+}
+
+static inline void *kvcalloc(size_t n, size_t size, gfp_t flags)
+{
+ return kvmalloc_array(n, size, flags | __GFP_ZERO);
+}
+
+#endif
+#include_next
+#endif /* OVS_MM_H */
+
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/linux/compat/include/linux/netfilter.h openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/linux/compat/include/linux/netfilter.h
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/linux/compat/include/linux/netfilter.h 1970-01-01 00:00:00.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/linux/compat/include/linux/netfilter.h 2020-03-11 16:15:44.000000000 +0000
@@ -0,0 +1,19 @@
+#ifndef __NETFILTER_WRAPPER_H
+#define __NETFILTER_WRAPPER_H
+
+#include_next
+
+#if !defined(HAVE_NF_HOOK_STATE) || !defined(HAVE_NF_HOOK_STATE_NET)
+struct rpl_nf_hook_state {
+ unsigned int hook;
+ u_int8_t pf;
+ struct net_device *in;
+ struct net_device *out;
+ struct sock *sk;
+ struct net *net;
+ int (*okfn)(struct net *, struct sock *, struct sk_buff *);
+};
+#define nf_hook_state rpl_nf_hook_state
+#endif
+
+#endif /* __NETFILTER_WRAPPER_H */
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/linux/compat/include/linux/overflow.h openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/linux/compat/include/linux/overflow.h
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/linux/compat/include/linux/overflow.h 1970-01-01 00:00:00.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/linux/compat/include/linux/overflow.h 2020-03-11 16:15:44.000000000 +0000
@@ -0,0 +1,313 @@
+/* SPDX-License-Identifier: GPL-2.0 OR MIT */
+#if defined(HAVE_OVERFLOW_H) && defined(HAVE_STRUCT_SIZE)
+#include_next
+#else
+#ifndef __LINUX_OVERFLOW_H
+#define __LINUX_OVERFLOW_H
+
+#include
+
+/*
+ * In the fallback code below, we need to compute the minimum and
+ * maximum values representable in a given type. These macros may also
+ * be useful elsewhere, so we provide them outside the
+ * COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW block.
+ *
+ * It would seem more obvious to do something like
+ *
+ * #define type_min(T) (T)(is_signed_type(T) ? (T)1 << (8*sizeof(T)-1) : 0)
+ * #define type_max(T) (T)(is_signed_type(T) ? ((T)1 << (8*sizeof(T)-1)) - 1 : ~(T)0)
+ *
+ * Unfortunately, the middle expressions, strictly speaking, have
+ * undefined behaviour, and at least some versions of gcc warn about
+ * the type_max expression (but not if -fsanitize=undefined is in
+ * effect; in that case, the warning is deferred to runtime...).
+ *
+ * The slightly excessive casting in type_min is to make sure the
+ * macros also produce sensible values for the exotic type _Bool. [The
+ * overflow checkers only almost work for _Bool, but that's
+ * a-feature-not-a-bug, since people shouldn't be doing arithmetic on
+ * _Bools. Besides, the gcc builtins don't allow _Bool* as third
+ * argument.]
+ *
+ * Idea stolen from
+ * https://mail-index.netbsd.org/tech-misc/2007/02/05/0000.html -
+ * credit to Christian Biere.
+ */
+#define is_signed_type(type) (((type)(-1)) < (type)1)
+#define __type_half_max(type) ((type)1 << (8*sizeof(type) - 1 - is_signed_type(type)))
+#define type_max(T) ((T)((__type_half_max(T) - 1) + __type_half_max(T)))
+#define type_min(T) ((T)((T)-type_max(T)-(T)1))
+
+
+#ifdef COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW
+/*
+ * For simplicity and code hygiene, the fallback code below insists on
+ * a, b and *d having the same type (similar to the min() and max()
+ * macros), whereas gcc's type-generic overflow checkers accept
+ * different types. Hence we don't just make check_add_overflow an
+ * alias for __builtin_add_overflow, but add type checks similar to
+ * below.
+ */
+#define check_add_overflow(a, b, d) ({ \
+ typeof(a) __a = (a); \
+ typeof(b) __b = (b); \
+ typeof(d) __d = (d); \
+ (void) (&__a == &__b); \
+ (void) (&__a == __d); \
+ __builtin_add_overflow(__a, __b, __d); \
+})
+
+#define check_sub_overflow(a, b, d) ({ \
+ typeof(a) __a = (a); \
+ typeof(b) __b = (b); \
+ typeof(d) __d = (d); \
+ (void) (&__a == &__b); \
+ (void) (&__a == __d); \
+ __builtin_sub_overflow(__a, __b, __d); \
+})
+
+#define check_mul_overflow(a, b, d) ({ \
+ typeof(a) __a = (a); \
+ typeof(b) __b = (b); \
+ typeof(d) __d = (d); \
+ (void) (&__a == &__b); \
+ (void) (&__a == __d); \
+ __builtin_mul_overflow(__a, __b, __d); \
+})
+
+#else
+
+
+/* Checking for unsigned overflow is relatively easy without causing UB. */
+#define __unsigned_add_overflow(a, b, d) ({ \
+ typeof(a) __a = (a); \
+ typeof(b) __b = (b); \
+ typeof(d) __d = (d); \
+ (void) (&__a == &__b); \
+ (void) (&__a == __d); \
+ *__d = __a + __b; \
+ *__d < __a; \
+})
+#define __unsigned_sub_overflow(a, b, d) ({ \
+ typeof(a) __a = (a); \
+ typeof(b) __b = (b); \
+ typeof(d) __d = (d); \
+ (void) (&__a == &__b); \
+ (void) (&__a == __d); \
+ *__d = __a - __b; \
+ __a < __b; \
+})
+/*
+ * If one of a or b is a compile-time constant, this avoids a division.
+ */
+#define __unsigned_mul_overflow(a, b, d) ({ \
+ typeof(a) __a = (a); \
+ typeof(b) __b = (b); \
+ typeof(d) __d = (d); \
+ (void) (&__a == &__b); \
+ (void) (&__a == __d); \
+ *__d = __a * __b; \
+ __builtin_constant_p(__b) ? \
+ __b > 0 && __a > type_max(typeof(__a)) / __b : \
+ __a > 0 && __b > type_max(typeof(__b)) / __a; \
+})
+
+/*
+ * For signed types, detecting overflow is much harder, especially if
+ * we want to avoid UB. But the interface of these macros is such that
+ * we must provide a result in *d, and in fact we must produce the
+ * result promised by gcc's builtins, which is simply the possibly
+ * wrapped-around value. Fortunately, we can just formally do the
+ * operations in the widest relevant unsigned type (u64) and then
+ * truncate the result - gcc is smart enough to generate the same code
+ * with and without the (u64) casts.
+ */
+
+/*
+ * Adding two signed integers can overflow only if they have the same
+ * sign, and overflow has happened iff the result has the opposite
+ * sign.
+ */
+#define __signed_add_overflow(a, b, d) ({ \
+ typeof(a) __a = (a); \
+ typeof(b) __b = (b); \
+ typeof(d) __d = (d); \
+ (void) (&__a == &__b); \
+ (void) (&__a == __d); \
+ *__d = (u64)__a + (u64)__b; \
+ (((~(__a ^ __b)) & (*__d ^ __a)) \
+ & type_min(typeof(__a))) != 0; \
+})
+
+/*
+ * Subtraction is similar, except that overflow can now happen only
+ * when the signs are opposite. In this case, overflow has happened if
+ * the result has the opposite sign of a.
+ */
+#define __signed_sub_overflow(a, b, d) ({ \
+ typeof(a) __a = (a); \
+ typeof(b) __b = (b); \
+ typeof(d) __d = (d); \
+ (void) (&__a == &__b); \
+ (void) (&__a == __d); \
+ *__d = (u64)__a - (u64)__b; \
+ ((((__a ^ __b)) & (*__d ^ __a)) \
+ & type_min(typeof(__a))) != 0; \
+})
+
+/*
+ * Signed multiplication is rather hard. gcc always follows C99, so
+ * division is truncated towards 0. This means that we can write the
+ * overflow check like this:
+ *
+ * (a > 0 && (b > MAX/a || b < MIN/a)) ||
+ * (a < -1 && (b > MIN/a || b < MAX/a) ||
+ * (a == -1 && b == MIN)
+ *
+ * The redundant casts of -1 are to silence an annoying -Wtype-limits
+ * (included in -Wextra) warning: When the type is u8 or u16, the
+ * __b_c_e in check_mul_overflow obviously selects
+ * __unsigned_mul_overflow, but unfortunately gcc still parses this
+ * code and warns about the limited range of __b.
+ */
+
+#define __signed_mul_overflow(a, b, d) ({ \
+ typeof(a) __a = (a); \
+ typeof(b) __b = (b); \
+ typeof(d) __d = (d); \
+ typeof(a) __tmax = type_max(typeof(a)); \
+ typeof(a) __tmin = type_min(typeof(a)); \
+ (void) (&__a == &__b); \
+ (void) (&__a == __d); \
+ *__d = (u64)__a * (u64)__b; \
+ (__b > 0 && (__a > __tmax/__b || __a < __tmin/__b)) || \
+ (__b < (typeof(__b))-1 && (__a > __tmin/__b || __a < __tmax/__b)) || \
+ (__b == (typeof(__b))-1 && __a == __tmin); \
+})
+
+
+#define check_add_overflow(a, b, d) \
+ __builtin_choose_expr(is_signed_type(typeof(a)), \
+ __signed_add_overflow(a, b, d), \
+ __unsigned_add_overflow(a, b, d))
+
+#define check_sub_overflow(a, b, d) \
+ __builtin_choose_expr(is_signed_type(typeof(a)), \
+ __signed_sub_overflow(a, b, d), \
+ __unsigned_sub_overflow(a, b, d))
+
+#define check_mul_overflow(a, b, d) \
+ __builtin_choose_expr(is_signed_type(typeof(a)), \
+ __signed_mul_overflow(a, b, d), \
+ __unsigned_mul_overflow(a, b, d))
+
+
+#endif /* COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW */
+
+/** check_shl_overflow() - Calculate a left-shifted value and check overflow
+ *
+ * @a: Value to be shifted
+ * @s: How many bits left to shift
+ * @d: Pointer to where to store the result
+ *
+ * Computes *@d = (@a << @s)
+ *
+ * Returns true if '*d' cannot hold the result or when 'a << s' doesn't
+ * make sense. Example conditions:
+ * - 'a << s' causes bits to be lost when stored in *d.
+ * - 's' is garbage (e.g. negative) or so large that the result of
+ * 'a << s' is guaranteed to be 0.
+ * - 'a' is negative.
+ * - 'a << s' sets the sign bit, if any, in '*d'.
+ *
+ * '*d' will hold the results of the attempted shift, but is not
+ * considered "safe for use" if false is returned.
+ */
+#define check_shl_overflow(a, s, d) ({ \
+ typeof(a) _a = a; \
+ typeof(s) _s = s; \
+ typeof(d) _d = d; \
+ u64 _a_full = _a; \
+ unsigned int _to_shift = \
+ _s >= 0 && _s < 8 * sizeof(*d) ? _s : 0; \
+ *_d = (_a_full << _to_shift); \
+ (_to_shift != _s || *_d < 0 || _a < 0 || \
+ (*_d >> _to_shift) != _a); \
+})
+
+/**
+ * array_size() - Calculate size of 2-dimensional array.
+ *
+ * @a: dimension one
+ * @b: dimension two
+ *
+ * Calculates size of 2-dimensional array: @a * @b.
+ *
+ * Returns: number of bytes needed to represent the array or SIZE_MAX on
+ * overflow.
+ */
+static inline __must_check size_t array_size(size_t a, size_t b)
+{
+ size_t bytes;
+
+ if (check_mul_overflow(a, b, &bytes))
+ return SIZE_MAX;
+
+ return bytes;
+}
+
+/**
+ * array3_size() - Calculate size of 3-dimensional array.
+ *
+ * @a: dimension one
+ * @b: dimension two
+ * @c: dimension three
+ *
+ * Calculates size of 3-dimensional array: @a * @b * @c.
+ *
+ * Returns: number of bytes needed to represent the array or SIZE_MAX on
+ * overflow.
+ */
+static inline __must_check size_t array3_size(size_t a, size_t b, size_t c)
+{
+ size_t bytes;
+
+ if (check_mul_overflow(a, b, &bytes))
+ return SIZE_MAX;
+ if (check_mul_overflow(bytes, c, &bytes))
+ return SIZE_MAX;
+
+ return bytes;
+}
+
+static inline __must_check size_t __ab_c_size(size_t n, size_t size, size_t c)
+{
+ size_t bytes;
+
+ if (check_mul_overflow(n, size, &bytes))
+ return SIZE_MAX;
+ if (check_add_overflow(bytes, c, &bytes))
+ return SIZE_MAX;
+
+ return bytes;
+}
+
+/**
+ * struct_size() - Calculate size of structure with trailing array.
+ * @p: Pointer to the structure.
+ * @member: Name of the array member.
+ * @n: Number of elements in the array.
+ *
+ * Calculates size of memory needed for structure @p followed by an
+ * array of @n @member elements.
+ *
+ * Return: number of bytes needed or SIZE_MAX on overflow.
+ */
+#define struct_size(p, member, n) \
+ __ab_c_size(n, \
+ sizeof(*(p)->member) + __must_be_array((p)->member),\
+ sizeof(*(p)))
+
+#endif /* __LINUX_OVERFLOW_H */
+#endif /* defined(HAVE_OVERFLOW_H) && defined(HAVE_STRUCT_SIZE) */
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/linux/compat/include/linux/static_key.h openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/linux/compat/include/linux/static_key.h
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/linux/compat/include/linux/static_key.h 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/linux/compat/include/linux/static_key.h 2020-03-11 16:15:44.000000000 +0000
@@ -1,6 +1,7 @@
#ifndef _STATIC_KEY_WRAPPER_H
#define _STATIC_KEY_WRAPPER_H
+#include
#include_next
#ifndef HAVE_UPSTREAM_STATIC_KEY
/*
@@ -23,16 +24,16 @@
#define rpl_STATIC_KEY_INIT_TRUE { .enabled = ATOMIC_INIT(1) }
#define rpl_STATIC_KEY_INIT_FALSE { .enabled = ATOMIC_INIT(0) }
-#define STATIC_KEY_TRUE_INIT \
+#define rpl_STATIC_KEY_TRUE_INIT \
(struct static_key_true) { .key = rpl_STATIC_KEY_INIT_TRUE, }
-#define STATIC_KEY_FALSE_INIT \
+#define rpl_STATIC_KEY_FALSE_INIT \
(struct static_key_false){ .key = rpl_STATIC_KEY_INIT_FALSE, }
-#define DEFINE_STATIC_KEY_TRUE(name) \
- struct static_key_true name = STATIC_KEY_TRUE_INIT
+#define rpl_DEFINE_STATIC_KEY_TRUE(name) \
+ struct static_key_true name = rpl_STATIC_KEY_TRUE_INIT
-#define DEFINE_STATIC_KEY_FALSE(name) \
- struct static_key_false name = STATIC_KEY_FALSE_INIT
+#define rpl_DEFINE_STATIC_KEY_FALSE(name) \
+ struct static_key_false name = rpl_STATIC_KEY_FALSE_INIT
static inline int rpl_static_key_count(struct static_key *key)
{
@@ -59,6 +60,14 @@
static_key_slow_dec(key);
}
+#ifdef HAVE_DEFINE_STATIC_KEY
+#undef DEFINE_STATIC_KEY_TRUE
+#undef DEFINE_STATIC_KEY_FALSE
+#endif
+
+#define DEFINE_STATIC_KEY_TRUE rpl_DEFINE_STATIC_KEY_TRUE
+#define DEFINE_STATIC_KEY_FALSE rpl_DEFINE_STATIC_KEY_FALSE
+
#define static_branch_likely(x) likely(static_key_enabled(&(x)->key))
#define static_branch_unlikely(x) unlikely(static_key_enabled(&(x)->key))
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/linux/compat/include/net/ipv6_frag.h openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/linux/compat/include/net/ipv6_frag.h
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/linux/compat/include/net/ipv6_frag.h 1970-01-01 00:00:00.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/linux/compat/include/net/ipv6_frag.h 2020-03-11 16:15:44.000000000 +0000
@@ -0,0 +1,8 @@
+#ifndef __NET_IPV6_FRAG_WRAPPER_H
+#define __NET_IPV6_FRAG_WRAPPER_H
+
+#if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6) && defined(HAVE_IPV6_FRAG_H)
+#include_next
+#endif
+
+#endif /* __NET_IPV6_FRAG_WRAPPER_H */
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/linux/compat/include/net/netfilter/nf_conntrack_core.h openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/linux/compat/include/net/netfilter/nf_conntrack_core.h
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/linux/compat/include/net/netfilter/nf_conntrack_core.h 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/linux/compat/include/net/netfilter/nf_conntrack_core.h 2020-03-11 16:15:44.000000000 +0000
@@ -67,27 +67,6 @@
#define nf_ct_get_tuple rpl_nf_ct_get_tuple
#endif /* HAVE_NF_CT_GET_TUPLEPR_TAKES_STRUCT_NET */
-/* Commit 08733a0cb7de ("netfilter: handle NF_REPEAT from nf_conntrack_in()")
- * introduced behavioural changes to this function which cannot be detected
- * in the headers. Unconditionally backport to kernels older than the one which
- * contains this commit. */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0)
-static unsigned int rpl_nf_conntrack_in(struct net *net, u_int8_t pf,
- unsigned int hooknum,
- struct sk_buff *skb)
-{
- int err;
-
- /* Repeat if requested, see nf_iterate(). */
- do {
- err = nf_conntrack_in(net, pf, hooknum, skb);
- } while (err == NF_REPEAT);
-
- return err;
-}
-#define nf_conntrack_in rpl_nf_conntrack_in
-#endif /* < 4.10 */
-
#ifdef HAVE_NF_CONN_TIMER
#ifndef HAVE_NF_CT_DELETE
@@ -125,4 +104,13 @@
#define nf_ct_delete rpl_nf_ct_delete
#endif /* HAVE_NF_CONN_TIMER */
+#ifndef HAVE_NF_CONNTRACK_IN_TAKES_NF_HOOK_STATE
+static inline unsigned int
+rpl_nf_conntrack_in(struct sk_buff *skb, const struct nf_hook_state *state)
+{
+ return nf_conntrack_in(state->net, state->pf, state->hook, skb);
+}
+#define nf_conntrack_in rpl_nf_conntrack_in
+#endif /* HAVE_NF_CONNTRACK_IN_TAKES_NF_HOOK_STATE */
+
#endif /* _NF_CONNTRACK_CORE_WRAPPER_H */
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/linux/compat/include/net/nsh.h openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/linux/compat/include/net/nsh.h
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/linux/compat/include/net/nsh.h 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/linux/compat/include/net/nsh.h 2020-03-11 16:15:44.000000000 +0000
@@ -247,10 +247,10 @@
#define NSH_M_TYPE1_LEN 24
/* NSH header maximum Length. */
-#define NSH_HDR_MAX_LEN 256
+#define NSH_HDR_MAX_LEN 252
/* NSH context headers maximum Length. */
-#define NSH_CTX_HDRS_MAX_LEN 248
+#define NSH_CTX_HDRS_MAX_LEN 244
static inline struct nshhdr *nsh_hdr(struct sk_buff *skb)
{
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/linux/compat/ip6_gre.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/linux/compat/ip6_gre.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/linux/compat/ip6_gre.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/linux/compat/ip6_gre.c 2020-03-11 16:15:44.000000000 +0000
@@ -377,7 +377,7 @@
if (parms->name[0])
strlcpy(name, parms->name, IFNAMSIZ);
else
- strcpy(name, "ip6gre%d");
+ strlcpy(name, "ovs-ip6gre%d", IFNAMSIZ);
dev = alloc_netdev(sizeof(*t), name, NET_NAME_UNKNOWN,
ip6gre_tunnel_setup);
@@ -876,9 +876,6 @@
struct tnl_ptk_info tpi;
__be16 protocol;
- if (dev->type == ARPHRD_ETHER)
- IPCB(skb)->flags = 0;
-
if (dev->header_ops && dev->type == ARPHRD_IP6GRE)
fl6->daddr = ((struct ipv6hdr *)skb->data)->daddr;
else
@@ -1146,7 +1143,6 @@
goto tx_err;
t->parms.o_flags &= ~TUNNEL_KEY;
- IPCB(skb)->flags = 0;
tun_info = ovs_skb_tunnel_info(skb);
if (unlikely(!tun_info ||
@@ -1200,7 +1196,11 @@
/* TooBig packet may have updated dst->dev's mtu */
if (!t->parms.collect_md && dst && dst_mtu(dst) > dst->dev->mtu)
+#ifndef HAVE_DST_OPS_CONFIRM_NEIGH
dst->ops->update_pmtu(dst, NULL, skb, dst->dev->mtu);
+#else
+ dst->ops->update_pmtu(dst, NULL, skb, dst->dev->mtu, false);
+#endif
err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu,
NEXTHDR_GRE);
@@ -1716,7 +1716,8 @@
struct ip6gre_net *ign = net_generic(net, ip6gre_net_id);
int err;
- ign->fb_tunnel_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6gre0",
+ ign->fb_tunnel_dev = alloc_netdev(sizeof(struct ip6_tnl),
+ "ovs-ip6gre0",
NET_NAME_UNKNOWN,
ip6gre_tunnel_setup);
if (!ign->fb_tunnel_dev) {
@@ -1983,6 +1984,7 @@
if (data[IFLA_GRE_COLLECT_METADATA])
parms->collect_md = true;
+ parms->erspan_ver = 1;
if (data[IFLA_GRE_ERSPAN_VER])
parms->erspan_ver = nla_get_u8(data[IFLA_GRE_ERSPAN_VER]);
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/linux/compat/ip6_tunnel.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/linux/compat/ip6_tunnel.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/linux/compat/ip6_tunnel.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/linux/compat/ip6_tunnel.c 2020-03-11 16:15:44.000000000 +0000
@@ -355,7 +355,7 @@
if (p->name[0])
strlcpy(name, p->name, IFNAMSIZ);
else
- sprintf(name, "ip6tnl%%d");
+ strlcpy(name, "ovs-ip6tnl%d", IFNAMSIZ);
dev = alloc_netdev(sizeof(*t), name, NET_NAME_UNKNOWN,
ip6_tnl_dev_setup);
@@ -1410,7 +1410,7 @@
* %SIOCCHGTUNNEL: change tunnel parameters to those given
* %SIOCDELTUNNEL: delete tunnel
*
- * The fallback device "ip6tnl0", created during module
+ * The fallback device "ovs-ip6tnl0", created during module
* initialization, can be used for creating other tunnel devices.
*
* Return:
@@ -2093,7 +2093,7 @@
ip6n->tnls[1] = ip6n->tnls_r_l;
err = -ENOMEM;
- ip6n->fb_tnl_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6tnl0",
+ ip6n->fb_tnl_dev = alloc_netdev(sizeof(struct ip6_tnl), "ovs-ip6tnl0",
NET_NAME_UNKNOWN, ip6_tnl_dev_setup);
if (!ip6n->fb_tnl_dev)
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/linux/compat/ip_gre.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/linux/compat/ip_gre.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/linux/compat/ip_gre.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/linux/compat/ip_gre.c 2020-03-11 16:15:44.000000000 +0000
@@ -312,6 +312,9 @@
if (tpi->proto == htons(ETH_P_TEB))
itn = net_generic(net, gre_tap_net_id);
+ else if (tpi->proto == htons(ETH_P_ERSPAN) ||
+ tpi->proto == htons(ETH_P_ERSPAN2))
+ itn = net_generic(net, erspan_net_id);
else
itn = net_generic(net, ipgre_net_id);
@@ -1229,12 +1232,15 @@
static void erspan_setup(struct net_device *dev)
{
+ struct ip_tunnel *t = netdev_priv(dev);
+
eth_hw_addr_random(dev);
ether_setup(dev);
dev->netdev_ops = &erspan_netdev_ops;
dev->priv_flags &= ~IFF_TX_SKB_SHARING;
dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
ip_tunnel_setup(dev, erspan_net_id);
+ t->erspan_ver = 1;
}
#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
@@ -1467,7 +1473,7 @@
static int __net_init ipgre_tap_init_net(struct net *net)
{
- return ip_tunnel_init_net(net, gre_tap_net_id, &ipgre_tap_ops, "gretap0");
+ return ip_tunnel_init_net(net, gre_tap_net_id, &ipgre_tap_ops, "ovs-gretap0");
}
static void __net_exit ipgre_tap_exit_net(struct net *net)
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/linux/compat/ip_tunnel.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/linux/compat/ip_tunnel.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/linux/compat/ip_tunnel.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/linux/compat/ip_tunnel.c 2020-03-11 16:15:44.000000000 +0000
@@ -266,7 +266,12 @@
mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu;
if (skb_dst(skb))
+#ifndef HAVE_DST_OPS_CONFIRM_NEIGH
skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu);
+#else
+ skb_dst(skb)->ops->update_pmtu(skb_dst(skb),
+ NULL, skb, mtu, false);
+#endif
if (skb->protocol == htons(ETH_P_IP)) {
if (!skb_is_gso(skb) &&
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/linux/compat/lisp.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/linux/compat/lisp.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/linux/compat/lisp.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/linux/compat/lisp.c 2020-03-11 16:15:44.000000000 +0000
@@ -457,6 +457,7 @@
rcu_assign_pointer(lisp->sock, sock);
/* Mark socket as an encapsulation socket */
+ memset(&tunnel_cfg, 0, sizeof(tunnel_cfg));
tunnel_cfg.sk_user_data = dev;
tunnel_cfg.encap_type = 1;
tunnel_cfg.encap_rcv = lisp_rcv;
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/linux/compat/nf_conntrack_proto.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/linux/compat/nf_conntrack_proto.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/linux/compat/nf_conntrack_proto.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/linux/compat/nf_conntrack_proto.c 2020-03-11 16:15:44.000000000 +0000
@@ -1,7 +1,9 @@
#include
#include
+#ifdef HAVE_NF_CONNTRACK_L3PROATO_H
#include
+#endif
/*
* Upstream net-next commmit 7e35ec0e8044
@@ -11,10 +13,10 @@
*
* However, we only need this feature if the underlying nf_conntrack_l3proto
* supports net_ns_get/put. Thus, we just mock the functions if
- * HAVE_NET_NS_SET is false.
+ * HAVE_NET_NS_GET is false.
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)
-#ifdef HAVE_NET_NS_SET
+#ifdef HAVE_NET_NS_GET
static int nf_ct_netns_do_get(struct net *net, u8 nfproto)
{
const struct nf_conntrack_l3proto *l3proto;
@@ -96,7 +98,7 @@
}
EXPORT_SYMBOL_GPL(rpl_nf_ct_netns_put);
-#else /* !HAVE_NET_NS_SET */
+#else /* !HAVE_NET_NS_GET */
void rpl_nf_ct_netns_put(struct net *net, uint8_t nfproto)
{
}
@@ -108,5 +110,5 @@
}
EXPORT_SYMBOL_GPL(rpl_nf_ct_netns_get);
-#endif /* HAVE_NET_NS_SET */
+#endif /* HAVE_NET_NS_GET */
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0) */
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/linux/compat/nf_conntrack_reasm.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/linux/compat/nf_conntrack_reasm.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/linux/compat/nf_conntrack_reasm.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/linux/compat/nf_conntrack_reasm.c 2020-03-11 16:15:44.000000000 +0000
@@ -99,6 +99,7 @@
return 1 << (ipv6_get_dsfield(ipv6h) & INET_ECN_MASK);
}
+#ifdef HAVE_INET_FRAGS_RND
static unsigned int nf_hash_frag(__be32 id, const struct in6_addr *saddr,
const struct in6_addr *daddr)
{
@@ -125,6 +126,7 @@
return nf_hash_frag(nq->id, &nq->saddr, &nq->daddr);
}
+#endif /* HAVE_INET_FRAGS_RND */
static void nf_ct_frag6_expire(unsigned long data)
{
struct frag_queue *fq;
@@ -133,9 +135,14 @@
fq = container_of((struct inet_frag_queue *)data, struct frag_queue, q);
net = get_net_from_netns_frags6(fq->q.net);
+#ifdef HAVE_INET_FRAGS_RND
ip6_expire_frag_queue(net, fq, &nf_frags);
+#else
+ ip6_expire_frag_queue(net, fq);
+#endif
}
+#ifdef HAVE_INET_FRAGS_RND
/* Creation primitives. */
static inline struct frag_queue *fq_find(struct net *net, __be32 id,
u32 user, struct in6_addr *src,
@@ -168,7 +175,27 @@
}
return container_of(q, struct frag_queue, q);
}
+#else
+static struct frag_queue *fq_find(struct net *net, __be32 id, u32 user,
+ const struct ipv6hdr *hdr, int iif)
+{
+ struct frag_v6_compare_key key = {
+ .id = id,
+ .saddr = hdr->saddr,
+ .daddr = hdr->daddr,
+ .user = user,
+ .iif = iif,
+ };
+ struct inet_frag_queue *q;
+
+ q = inet_frag_find(&net->nf_frag.frags, &key);
+ if (!q)
+ return NULL;
+
+ return container_of(q, struct frag_queue, q);
+}
+#endif /* HAVE_INET_FRAGS_RND */
static int nf_ct_frag6_queue(struct frag_queue *fq, struct sk_buff *skb,
const struct frag_hdr *fhdr, int nhoff)
@@ -317,7 +344,11 @@
return 0;
discard_fq:
+#ifdef HAVE_INET_FRAGS_RND
inet_frag_kill(&fq->q, &nf_frags);
+#else
+ inet_frag_kill(&fq->q);
+#endif
err:
return -1;
}
@@ -339,7 +370,11 @@
int payload_len;
u8 ecn;
+#ifdef HAVE_INET_FRAGS_RND
inet_frag_kill(&fq->q, &nf_frags);
+#else
+ inet_frag_kill(&fq->q);
+#endif
WARN_ON(head == NULL);
WARN_ON(NFCT_FRAG6_CB(head)->offset != 0);
@@ -561,8 +596,13 @@
#endif
skb_orphan(skb);
+#ifdef HAVE_INET_FRAGS_RND
fq = fq_find(net, fhdr->identification, user, &hdr->saddr, &hdr->daddr,
ip6_frag_ecn(hdr));
+#else
+ fq = fq_find(net, fhdr->identification, user, hdr,
+ skb->dev ? skb->dev->ifindex : 0);
+#endif
if (fq == NULL)
return -ENOMEM;
@@ -584,7 +624,11 @@
out_unlock:
spin_unlock_bh(&fq->q.lock);
+#ifdef HAVE_INET_FRAGS_RND
inet_frag_put(&fq->q, &nf_frags);
+#else
+ inet_frag_put(&fq->q);
+#endif
return ret;
}
@@ -614,10 +658,12 @@
void ovs_netns_frags6_exit(struct net *net)
{
+#ifdef HAVE_INET_FRAGS_RND
struct netns_frags *frags;
frags = get_netns_frags6_from_net(net);
inet_frags_exit_net(frags, &nf_frags);
+#endif
}
static struct pernet_operations nf_ct_net_ops = {
@@ -634,13 +680,17 @@
#ifndef HAVE_DEFRAG_ENABLE_TAKES_NET
nf_defrag_ipv6_enable();
#endif
+#ifdef HAVE_INET_FRAGS_RND
nf_frags.hashfn = nf_hashfn;
+ nf_frags.match = ip6_frag_match;
+#else
+ nf_frags.rhash_params = ip6_rhash_params;
+#endif
nf_frags.constructor = ip6_frag_init;
nf_frags.destructor = NULL;
nf_frags.qsize = sizeof(struct frag_queue);
- nf_frags.match = ip6_frag_match;
nf_frags.frag_expire = nf_ct_frag6_expire;
-#ifdef HAVE_INET_FRAGS_WITH_FRAGS_WORK
+#if defined(HAVE_INET_FRAGS_WITH_FRAGS_WORK) || !defined(HAVE_INET_FRAGS_RND)
nf_frags.frags_cache_name = nf_frags_cache_name;
#endif
#if RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(8,0)
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/linux/compat/stt.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/linux/compat/stt.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/linux/compat/stt.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/linux/compat/stt.c 2020-03-11 16:15:44.000000000 +0000
@@ -1026,7 +1026,7 @@
error:
kfree_skb(skb);
dev->stats.tx_errors++;
- return NETDEV_TX_OK;
+ return err;
}
EXPORT_SYMBOL(ovs_stt_xmit);
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/linux/Modules.mk openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/linux/Modules.mk
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/linux/Modules.mk 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/linux/Modules.mk 2020-03-11 16:15:44.000000000 +0000
@@ -86,6 +86,7 @@
linux/compat/include/net/ip6_route.h \
linux/compat/include/net/ip6_tunnel.h \
linux/compat/include/net/ipv6.h \
+ linux/compat/include/net/ipv6_frag.h \
linux/compat/include/net/mpls.h \
linux/compat/include/net/net_namespace.h \
linux/compat/include/net/netlink.h \
@@ -112,5 +113,8 @@
linux/compat/include/net/netfilter/ipv6/nf_defrag_ipv6.h \
linux/compat/include/net/sctp/checksum.h \
linux/compat/include/net/erspan.h \
- linux/compat/include/uapi/linux/netfilter.h
+ linux/compat/include/uapi/linux/netfilter.h \
+ linux/compat/include/linux/mm.h \
+ linux/compat/include/linux/netfilter.h \
+ linux/compat/include/linux/overflow.h
EXTRA_DIST += linux/compat/build-aux/export-check-whitelist
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/meter.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/meter.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath/meter.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath/meter.c 2020-03-11 16:15:44.000000000 +0000
@@ -13,11 +13,13 @@
#include
#include
#include
+#include
#include
#include
#include
#include
+#include
#include "datapath.h"
#include "meter.h"
@@ -216,8 +218,7 @@
return ERR_PTR(-EINVAL);
/* Allocate and set up the meter before locking anything. */
- meter = kzalloc(n_bands * sizeof(struct dp_meter_band) +
- sizeof(*meter), GFP_KERNEL);
+ meter = kzalloc(struct_size(meter, bands, n_bands), GFP_KERNEL);
if (!meter)
return ERR_PTR(-ENOMEM);
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath-windows/include/OvsDpInterfaceExt.h openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath-windows/include/OvsDpInterfaceExt.h
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath-windows/include/OvsDpInterfaceExt.h 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath-windows/include/OvsDpInterfaceExt.h 2020-03-11 16:15:44.000000000 +0000
@@ -72,6 +72,7 @@
*/
#define OVS_WIN_NL_CT_FAMILY_ID (NLMSG_MIN_TYPE + 7)
+#define OVS_WIN_NL_CTLIMIT_FAMILY_ID (NLMSG_MIN_TYPE + 8)
#define OVS_WIN_NL_INVALID_MCGRP_ID 0
#define OVS_WIN_NL_MCGRP_START_ID 100
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath-windows/ovsext/BufferMgmt.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath-windows/ovsext/BufferMgmt.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath-windows/ovsext/BufferMgmt.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath-windows/ovsext/BufferMgmt.c 2020-03-11 16:15:44.000000000 +0000
@@ -1622,6 +1622,7 @@
{
POVS_BUFFER_CONTEXT ctx;
UINT16 flags;
+ UINT32 dataOffsetDelta;
PNET_BUFFER_LIST parent;
NDIS_STATUS status;
NDIS_HANDLE poolHandle;
@@ -1653,6 +1654,7 @@
nb = NET_BUFFER_LIST_FIRST_NB(nbl);
flags = ctx->flags;
+ dataOffsetDelta = ctx->dataOffsetDelta;
if (!(flags & OVS_BUFFER_FRAGMENT) &&
NET_BUFFER_DATA_LENGTH(nb) != ctx->origDataLength) {
UINT32 diff;
@@ -1667,7 +1669,7 @@
}
}
- if (ctx->flags & OVS_BUFFER_PRIVATE_CONTEXT) {
+ if (flags & OVS_BUFFER_PRIVATE_CONTEXT) {
NdisFreeNetBufferListContext(nbl, sizeof (OVS_BUFFER_CONTEXT));
}
@@ -1740,7 +1742,7 @@
#ifdef DBG
InterlockedDecrement((LONG volatile *)&ovsPool->fragNBLCount);
#endif
- NdisFreeFragmentNetBufferList(nbl, ctx->dataOffsetDelta, 0);
+ NdisFreeFragmentNetBufferList(nbl, dataOffsetDelta, 0);
}
if (parent != NULL) {
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath-windows/ovsext/Conntrack.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath-windows/ovsext/Conntrack.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath-windows/ovsext/Conntrack.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath-windows/ovsext/Conntrack.c 2020-03-11 16:15:44.000000000 +0000
@@ -27,13 +27,17 @@
#define WINDOWS_TICK 10000000
#define SEC_TO_UNIX_EPOCH 11644473600LL
#define SEC_TO_NANOSEC 1000000000LL
+#define CT_MAX_ZONE (UINT16_MAX + 1)
KSTART_ROUTINE OvsConntrackEntryCleaner;
static PLIST_ENTRY ovsConntrackTable;
static OVS_CT_THREAD_CTX ctThreadCtx;
static PNDIS_RW_LOCK_EX *ovsCtBucketLock = NULL;
+static NDIS_SPIN_LOCK ovsCtZoneLock;
+static POVS_CT_ZONE_INFO zoneInfo = NULL;
extern POVS_SWITCH_CONTEXT gOvsSwitchContext;
static ULONG ctTotalEntries;
+static ULONG defaultCtLimit;
static __inline OvsCtFlush(UINT16 zone, struct ovs_key_ct_tuple_ipv4 *tuple);
static __inline NDIS_STATUS
@@ -94,6 +98,20 @@
ZwClose(threadHandle);
threadHandle = NULL;
+ zoneInfo = OvsAllocateMemoryWithTag(sizeof(OVS_CT_ZONE_INFO) *
+ CT_MAX_ZONE, OVS_CT_POOL_TAG);
+ if (zoneInfo == NULL) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ goto freeBucketLock;
+ }
+
+ NdisAllocateSpinLock(&ovsCtZoneLock);
+ defaultCtLimit = CT_MAX_ENTRIES;
+ for (UINT32 i = 0; i < CT_MAX_ZONE; i++) {
+ zoneInfo[i].entries = 0;
+ zoneInfo[i].limit = defaultCtLimit;
+ }
+
status = OvsNatInit();
if (status != STATUS_SUCCESS) {
@@ -149,6 +167,25 @@
OvsFreeMemoryWithTag(ovsCtBucketLock, OVS_CT_POOL_TAG);
ovsCtBucketLock = NULL;
OvsNatCleanup();
+ NdisFreeSpinLock(&ovsCtZoneLock);
+ if (zoneInfo) {
+ OvsFreeMemoryWithTag(zoneInfo, OVS_CT_POOL_TAG);
+ }
+}
+
+VOID
+OvsCtSetZoneLimit(int zone, ULONG value) {
+ NdisAcquireSpinLock(&ovsCtZoneLock);
+ if (zone == -1) {
+ /* Set default limit for all zones. */
+ defaultCtLimit = value;
+ for (UINT32 i = 0; i < CT_MAX_ZONE; i++) {
+ zoneInfo[i].limit = value;
+ }
+ } else {
+ zoneInfo[(UINT16)zone].limit = value;
+ }
+ NdisReleaseSpinLock(&ovsCtZoneLock);
}
/*
@@ -263,6 +300,7 @@
&entry->link);
NdisInterlockedIncrement((PLONG)&ctTotalEntries);
+ NdisInterlockedIncrement((PLONG)&zoneInfo[ctx->key.zone].entries);
NdisReleaseRWLock(ovsCtBucketLock[bucketIdx], &lockState);
return TRUE;
}
@@ -437,6 +475,7 @@
if (entry->natInfo.natAction) {
OvsNatDeleteKey(&entry->key);
}
+ NdisInterlockedDecrement((PLONG)&zoneInfo[entry->key.zone].entries);
OvsPostCtEventEntry(entry, OVS_EVENT_CT_DELETE);
RemoveEntryList(&entry->link);
OVS_RELEASE_SPIN_LOCK(&(entry->lock), irql);
@@ -770,6 +809,7 @@
ovs_u128 v, m, pktMdLabel = {0};
memcpy(&v, val, sizeof v);
memcpy(&m, mask, sizeof m);
+ memcpy(&pktMdLabel, &entry->labels, sizeof(struct ovs_key_ct_labels));
pktMdLabel.u64.lo = v.u64.lo | (pktMdLabel.u64.lo & ~(m.u64.lo));
pktMdLabel.u64.hi = v.u64.hi | (pktMdLabel.u64.hi & ~(m.u64.hi));
@@ -877,12 +917,16 @@
&entryCreated);
} else {
- if (commit && ctTotalEntries >= CT_MAX_ENTRIES) {
+ if (commit && (ctTotalEntries >= CT_MAX_ENTRIES ||
+ zoneInfo[ctx.key.zone].entries >= zoneInfo[ctx.key.zone].limit)) {
/* Don't proceed with processing if the max limit has been hit.
* This blocks only new entries from being created and doesn't
* affect existing connections.
*/
- OVS_LOG_ERROR("Conntrack Limit hit: %lu", ctTotalEntries);
+ OVS_LOG_ERROR("Conntrack Limit hit: zone(%u), zoneLimit(%lu),"
+ "zoneEntries(%lu), ctTotalEntries(%lu)",
+ zone, zoneInfo[ctx.key.zone].limit,
+ zoneInfo[ctx.key.zone].entries, ctTotalEntries);
return NDIS_STATUS_RESOURCES;
}
/* If no matching entry was found, create one and add New state */
@@ -1783,4 +1827,124 @@
return STATUS_SUCCESS;
}
+static NTSTATUS
+OvsCreateNlMsgFromCtLimit(POVS_MESSAGE msgIn,
+ PVOID outBuffer,
+ UINT32 outBufLen,
+ PCHAR attr,
+ UINT32 numAttrs,
+ int dpIfIndex)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ NL_BUFFER nlBuffer;
+ PNL_MSG_HDR nlMsg;
+ PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);
+
+ NlBufInit(&nlBuffer, outBuffer, outBufLen);
+
+ if (!NlFillOvsMsg(&nlBuffer, msgIn->nlMsg.nlmsgType, NLM_F_MULTI,
+ msgIn->nlMsg.nlmsgSeq, msgIn->nlMsg.nlmsgPid,
+ msgIn->genlMsg.cmd, msgIn->genlMsg.version,
+ dpIfIndex)) {
+ return STATUS_INVALID_BUFFER_SIZE;
+ }
+
+ if (genlMsgHdr->cmd == OVS_CT_LIMIT_CMD_GET && numAttrs) {
+ POVS_CT_ZONE_LIMIT zoneLimitAttr = (POVS_CT_ZONE_LIMIT) attr;
+ UINT32 offset = NlMsgStartNested(&nlBuffer, OVS_CT_LIMIT_ATTR_ZONE_LIMIT);
+ if (!offset) {
+ /* Starting the nested attribute failed. */
+ status = STATUS_INVALID_BUFFER_SIZE;
+ goto done;
+ }
+
+ /* Insert OVS_CT_ZONE_LIMIT attributes.*/
+ for (UINT32 i = 0; i < numAttrs; i++) {
+ if (zoneLimitAttr) {
+ zoneLimitAttr->limit = zoneInfo[zoneLimitAttr->zone_id].limit;
+ zoneLimitAttr->count = zoneInfo[zoneLimitAttr->zone_id].entries;
+ if (zoneLimitAttr->zone_id == -1) {
+ zoneLimitAttr->limit = defaultCtLimit;
+ }
+ NlMsgPutTail(&nlBuffer, (const PCHAR)zoneLimitAttr,
+ sizeof(OVS_CT_ZONE_LIMIT));
+ } else {
+ status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+ zoneLimitAttr = (POVS_CT_ZONE_LIMIT)((PCHAR) zoneLimitAttr +
+ sizeof(OVS_CT_ZONE_LIMIT));
+ }
+ NlMsgEndNested(&nlBuffer, offset);
+ }
+
+done:
+ nlMsg = (PNL_MSG_HDR)NlBufAt(&nlBuffer, 0, 0);
+ nlMsg->nlmsgLen = NlBufSize(&nlBuffer);
+
+ return status;
+}
+
+NTSTATUS
+OvsCtLimitHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
+ UINT32 *replyLen)
+{
+ NTSTATUS status;
+ POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;
+ POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer;
+ PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
+ PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);
+ POVS_HDR ovsHdr = &(msgIn->ovsHdr);
+ PCHAR attr = NULL;
+ UINT32 numAttrs = 0;
+ UINT32 attrOffset = NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN;
+
+ static const NL_POLICY ovsCtLimitPolicy[] = {
+ [OVS_CT_LIMIT_ATTR_ZONE_LIMIT] = { .type = NL_A_NESTED, .optional = TRUE }
+ };
+ PNL_ATTR nlAttrs[ARRAY_SIZE(ovsCtLimitPolicy)];
+
+ if ((NlAttrParse(nlMsgHdr, attrOffset, NlMsgAttrsLen(nlMsgHdr),
+ ovsCtLimitPolicy, ARRAY_SIZE(ovsCtLimitPolicy),
+ nlAttrs, ARRAY_SIZE(nlAttrs)))
+ != TRUE) {
+ OVS_LOG_ERROR("Attr Parsing failed for msg: %p", nlMsgHdr);
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if (nlAttrs[OVS_CT_LIMIT_ATTR_ZONE_LIMIT]) {
+ numAttrs = NlAttrGetSize(nlAttrs[OVS_CT_LIMIT_ATTR_ZONE_LIMIT])/sizeof(OVS_CT_ZONE_LIMIT);
+ attr = NlAttrGet(nlAttrs[OVS_CT_LIMIT_ATTR_ZONE_LIMIT]);
+ }
+
+ if (genlMsgHdr->cmd == OVS_CT_LIMIT_CMD_SET ||
+ genlMsgHdr->cmd == OVS_CT_LIMIT_CMD_DEL) {
+ POVS_CT_ZONE_LIMIT zoneLimitAttr = (POVS_CT_ZONE_LIMIT)attr;
+ for (UINT32 i = 0; i < numAttrs; i++) {
+ /* Parse zone limit attributes. */
+ if (zoneLimitAttr) {
+ if (genlMsgHdr->cmd == OVS_CT_LIMIT_CMD_DEL) {
+ zoneLimitAttr->limit = CT_MAX_ENTRIES;
+ }
+ OvsCtSetZoneLimit(zoneLimitAttr->zone_id, zoneLimitAttr->limit);
+ } else {
+ OVS_LOG_ERROR("Failed to get zone limit attribute at index(%u),"
+ " numAttrs(%u)", i, numAttrs);
+ return STATUS_INVALID_PARAMETER;
+ }
+ zoneLimitAttr = (POVS_CT_ZONE_LIMIT)((PCHAR) zoneLimitAttr +
+ sizeof(OVS_CT_ZONE_LIMIT));
+ }
+ }
+
+ /* Output buffer has been validated while validating transact dev op. */
+ ASSERT(msgOut != NULL && usrParamsCtx->outputLength >= sizeof *msgOut);
+ status = OvsCreateNlMsgFromCtLimit(msgIn, msgOut,
+ usrParamsCtx->outputLength,
+ attr, numAttrs, ovsHdr->dp_ifindex);
+ *replyLen = msgOut->nlMsg.nlmsgLen;
+
+ return status;
+}
+
#pragma warning(pop)
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath-windows/ovsext/Conntrack.h openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath-windows/ovsext/Conntrack.h
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath-windows/ovsext/Conntrack.h 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath-windows/ovsext/Conntrack.h 2020-03-11 16:15:44.000000000 +0000
@@ -132,6 +132,18 @@
BOOLEAN related;
} OvsConntrackKeyLookupCtx;
+/* Per zone strucuture. */
+typedef struct _OVS_CT_ZONE_INFO {
+ ULONG limit;
+ ULONG entries;
+} OVS_CT_ZONE_INFO, *POVS_CT_ZONE_INFO;
+
+typedef struct _OVS_CT_ZONE_LIMIT {
+ int zone_id;
+ ULONG limit;
+ ULONG count;
+} OVS_CT_ZONE_LIMIT, *POVS_CT_ZONE_LIMIT;
+
#define CT_MAX_ENTRIES 1 << 21
#define CT_HASH_TABLE_SIZE ((UINT32)1 << 10)
#define CT_HASH_TABLE_MASK (CT_HASH_TABLE_SIZE - 1)
@@ -175,8 +187,7 @@
tcp = (TCPHdr *)((PCHAR)ipHdr + ipHdr->ihl * 4);
if (tcp->doff * 4 >= sizeof *tcp) {
NdisMoveMemory(dest, tcp, sizeof(TCPHdr));
- *tcpPayloadLen = ntohs((ipHdr->tot_len) - (ipHdr->ihl * 4) -
- (TCP_HDR_LEN(tcp)));
+ *tcpPayloadLen = TCP_DATA_LENGTH(ipHdr, tcp);
return storage;
}
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath-windows/ovsext/Datapath.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath-windows/ovsext/Datapath.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath-windows/ovsext/Datapath.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath-windows/ovsext/Datapath.c 2020-03-11 16:15:44.000000000 +0000
@@ -99,7 +99,8 @@
OvsSubscribePacketCmdHandler,
OvsReadPacketCmdHandler,
OvsCtDeleteCmdHandler,
- OvsCtDumpCmdHandler;
+ OvsCtDumpCmdHandler,
+ OvsCtLimitHandler;
static NTSTATUS HandleGetDpTransaction(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
UINT32 *replyLen);
@@ -324,6 +325,34 @@
.opsCount = ARRAY_SIZE(nlNetdevFamilyCmdOps)
};
+
+/* Netlink conntrack limit family. */
+NETLINK_CMD nlCtLimitFamilyCmdOps[] = {
+ { .cmd = OVS_CT_LIMIT_CMD_GET,
+ .handler = OvsCtLimitHandler,
+ .supportedDevOp = OVS_TRANSACTION_DEV_OP,
+ .validateDpIndex = FALSE
+ },
+ { .cmd = OVS_CT_LIMIT_CMD_SET,
+ .handler = OvsCtLimitHandler,
+ .supportedDevOp = OVS_TRANSACTION_DEV_OP,
+ .validateDpIndex = FALSE
+ },
+ { .cmd = OVS_CT_LIMIT_CMD_DEL,
+ .handler = OvsCtLimitHandler,
+ .supportedDevOp = OVS_TRANSACTION_DEV_OP,
+ .validateDpIndex = FALSE
+ },
+};
+
+NETLINK_FAMILY nlCtLimitFamilyOps = {
+ .name = OVS_CT_LIMIT_FAMILY,
+ .id = OVS_WIN_NL_CTLIMIT_FAMILY_ID,
+ .version = OVS_CT_LIMIT_VERSION,
+ .maxAttr = OVS_CT_LIMIT_ATTR_MAX,
+ .cmds = nlCtLimitFamilyCmdOps,
+ .opsCount = ARRAY_SIZE(nlCtLimitFamilyCmdOps)
+};
static NTSTATUS MapIrpOutputBuffer(PIRP irp,
UINT32 bufferLength,
UINT32 requiredLength,
@@ -941,6 +970,9 @@
case OVS_WIN_NL_NETDEV_FAMILY_ID:
nlFamilyOps = &nlNetdevFamilyOps;
break;
+ case OVS_WIN_NL_CTLIMIT_FAMILY_ID:
+ nlFamilyOps = &nlCtLimitFamilyOps;
+ break;
default:
status = STATUS_INVALID_PARAMETER;
goto done;
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath-windows/ovsext/IpFragment.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath-windows/ovsext/IpFragment.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath-windows/ovsext/IpFragment.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath-windows/ovsext/IpFragment.c 2020-03-11 16:15:44.000000000 +0000
@@ -230,7 +230,7 @@
/*
*----------------------------------------------------------------------------
* OvsProcessIpv4Fragment
- * Reassemble the fragments once all the fragments are recieved and
+ * Reassemble the fragments once all the fragments are received and
* return NDIS_STATUS_PENDING for the pending fragments
* XXX - Instead of copying NBls, Keep the NBLs in limbo state.
*----------------------------------------------------------------------------
@@ -403,7 +403,7 @@
entry->tail = fragStorage;
}
- /*Update Maximum recieved Unit */
+ /*Update Maximum Receive Unit */
entry->mru = entry->mru > (ETH_HEADER_LENGTH + ipHdrLen + payloadLen) ?
entry->mru : (ETH_HEADER_LENGTH + ipHdrLen + payloadLen);
entry->numFragments++;
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath-windows/ovsext/IpFragment.h openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath-windows/ovsext/IpFragment.h
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath-windows/ovsext/IpFragment.h 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath-windows/ovsext/IpFragment.h 2020-03-11 16:15:44.000000000 +0000
@@ -57,7 +57,7 @@
#define IP_FRAG_HASH_TABLE_SIZE ((UINT32)1 << 10)
#define IP_FRAG_HASH_TABLE_MASK (IP_FRAG_HASH_TABLE_SIZE - 1)
-/*30s -Sufficient time to recieve all fragments.*/
+/*30s -Sufficient time to receive all fragments.*/
#define IPFRAG_ENTRY_TIMEOUT 300000000LL
#define IPFRAG_CLEANUP_INTERVAL IPFRAG_ENTRY_TIMEOUT * 2 /*1m.*/
PNET_BUFFER_LIST OvsIpv4FragmentNBL(PVOID ovsContext,
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath-windows/ovsext/IpHelper.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath-windows/ovsext/IpHelper.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath-windows/ovsext/IpHelper.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath-windows/ovsext/IpHelper.c 2020-03-11 16:15:44.000000000 +0000
@@ -40,34 +40,6 @@
static ERESOURCE ovsInstanceListLock;
/*
- * This structure is used to define each adapter instance.
- *
- * Note:
- * Only when the internal IP is configured and virtual
- * internal port is connected, the IP helper request can be
- * queued.
- *
- * We only keep internal IP for reference, it will not be used for determining
- * SRC IP of the Tunnel.
- *
- * The lock must not raise the IRQL higher than PASSIVE_LEVEL in order for the
- * route manipulation functions, i.e. GetBestRoute, to work.
- */
-typedef struct _OVS_IPHELPER_INSTANCE
-{
- LIST_ENTRY link;
-
- BOOLEAN isIpConfigured;
- UINT32 portNo;
- GUID netCfgId;
- MIB_IF_ROW2 internalRow;
- MIB_IPINTERFACE_ROW internalIPRow;
- UINT32 ipAddress;
-
- ERESOURCE lock;
-} OVS_IPHELPER_INSTANCE, *POVS_IPHELPER_INSTANCE;
-
-/*
* FWD_ENTRY --------> IPFORWARD_ENTRY
* |
* |--------------------------------------> IPENIGH_ENTRY
@@ -100,7 +72,7 @@
static POVS_IPFORWARD_ENTRY OvsLookupIPForwardEntry(PIP_ADDRESS_PREFIX prefix);
static VOID OvsRemoveIPForwardEntry(POVS_IPFORWARD_ENTRY ipf);
static VOID OvsRemoveAllFwdEntriesWithSrc(UINT32 ipAddr);
-static VOID OvsRemoveAllFwdEntriesWithPortNo(UINT32 portNo);
+static VOID OvsRemoveIPNeighEntriesWithInstance(POVS_IPHELPER_INSTANCE instance);
static VOID OvsCleanupIpHelperRequestList(VOID);
static VOID OvsCleanupFwdTable(VOID);
static VOID OvsAddToSortedNeighList(POVS_IPNEIGH_ENTRY ipn);
@@ -1070,7 +1042,7 @@
RtlCopyMemory(entry->macAddr, ipNeigh->PhysicalAddress,
ETH_ADDR_LEN);
InitializeListHead(&entry->fwdList);
- entry->context = (PVOID)instance;
+ entry->instance = instance;
return entry;
}
@@ -1271,18 +1243,16 @@
static VOID
-OvsRemoveAllFwdEntriesWithPortNo(UINT32 portNo)
+OvsRemoveIPNeighEntriesWithInstance(POVS_IPHELPER_INSTANCE instance)
{
- UINT32 i;
- PLIST_ENTRY link, next;
-
- for (i = 0; i < OVS_FWD_HASH_TABLE_SIZE; i++) {
- LIST_FORALL_SAFE(&ovsFwdHashTable[i], link, next) {
- POVS_FWD_ENTRY fwdEntry;
-
- fwdEntry = CONTAINING_RECORD(link, OVS_FWD_ENTRY, link);
- if (fwdEntry->info.srcPortNo == portNo) {
- OvsRemoveFwdEntry(fwdEntry);
+ if (ovsNumFwdEntries) {
+ POVS_IPNEIGH_ENTRY ipn;
+ PLIST_ENTRY link, next;
+ LIST_FORALL_SAFE(&ovsSortedIPNeighList, link, next) {
+ ipn = CONTAINING_RECORD(link, OVS_IPNEIGH_ENTRY, slink);
+ POVS_IPHELPER_INSTANCE ipnInstance = ipn->instance;
+ if (ipnInstance == instance) {
+ OvsRemoveIPNeighEntry(ipn);
}
}
}
@@ -1885,7 +1855,7 @@
IsEqualGUID(&instance->netCfgId, &netCfgInstanceId)) {
NdisAcquireRWLockWrite(ovsTableLock, &lockState, 0);
- OvsRemoveAllFwdEntriesWithPortNo(instance->portNo);
+ OvsRemoveIPNeighEntriesWithInstance(instance);
NdisReleaseRWLock(ovsTableLock, &lockState);
RemoveEntryList(&instance->link);
@@ -1934,16 +1904,18 @@
ipAddr = ipn->ipAddr;
MIB_IPNET_ROW2 ipNeigh;
NTSTATUS status;
- POVS_IPHELPER_INSTANCE instance = (POVS_IPHELPER_INSTANCE)ipn->context;
+ POVS_IPHELPER_INSTANCE instance = ipn->instance;
NdisReleaseSpinLock(&ovsIpHelperLock);
- ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE);
- status = OvsGetOrResolveIPNeigh(&instance->internalRow,
- ipAddr, &ipNeigh);
- OvsUpdateIPNeighEntry(ipAddr, &ipNeigh, status);
+ if (instance) {
+ ExAcquireResourceExclusiveLite(&instance->lock, TRUE);
- ExReleaseResourceLite(&ovsInstanceListLock);
+ status = OvsGetOrResolveIPNeigh(&instance->internalRow,
+ ipAddr, &ipNeigh);
+ OvsUpdateIPNeighEntry(ipAddr, &ipNeigh, status);
+ ExReleaseResourceLite(&instance->lock);
+ }
NdisAcquireSpinLock(&ovsIpHelperLock);
}
if (!IsListEmpty(&ovsIpHelperRequestList)) {
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath-windows/ovsext/IpHelper.h openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath-windows/ovsext/IpHelper.h
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath-windows/ovsext/IpHelper.h 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath-windows/ovsext/IpHelper.h 2020-03-11 16:15:44.000000000 +0000
@@ -32,17 +32,44 @@
#define OVS_IPNEIGH_TIMEOUT 100000000 // 10 s
+ /*
+ * This structure is used to define each adapter instance.
+ *
+ * Note:
+ * Only when the internal IP is configured and virtual
+ * internal port is connected, the IP helper request can be
+ * queued.
+ *
+ * We only keep internal IP for reference, it will not be used for determining
+ * SRC IP of the Tunnel.
+ *
+ * The lock must not raise the IRQL higher than PASSIVE_LEVEL in order for the
+ * route manipulation functions, i.e. GetBestRoute, to work.
+ */
+typedef struct _OVS_IPHELPER_INSTANCE
+{
+ LIST_ENTRY link;
+
+ BOOLEAN isIpConfigured;
+ UINT32 portNo;
+ GUID netCfgId;
+ MIB_IF_ROW2 internalRow;
+ MIB_IPINTERFACE_ROW internalIPRow;
+ UINT32 ipAddress;
+
+ ERESOURCE lock;
+} OVS_IPHELPER_INSTANCE, *POVS_IPHELPER_INSTANCE;
typedef struct _OVS_IPNEIGH_ENTRY {
- UINT8 macAddr[ETH_ADDR_LEN];
- UINT16 refCount;
- UINT32 ipAddr;
- UINT32 pad;
- UINT64 timeout;
- LIST_ENTRY link;
- LIST_ENTRY slink;
- LIST_ENTRY fwdList;
- PVOID context;
+ UINT8 macAddr[ETH_ADDR_LEN];
+ UINT16 refCount;
+ UINT32 ipAddr;
+ UINT32 pad;
+ UINT64 timeout;
+ LIST_ENTRY link;
+ LIST_ENTRY slink;
+ LIST_ENTRY fwdList;
+ POVS_IPHELPER_INSTANCE instance;
} OVS_IPNEIGH_ENTRY, *POVS_IPNEIGH_ENTRY;
typedef struct _OVS_IPFORWARD_ENTRY {
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath-windows/ovsext/Vport.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath-windows/ovsext/Vport.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/datapath-windows/ovsext/Vport.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/datapath-windows/ovsext/Vport.c 2020-03-11 16:15:44.000000000 +0000
@@ -632,13 +632,13 @@
OvsRemoveAndDeleteVport(NULL, switchContext, vport, FALSE, TRUE);
OvsPostVportEvent(&event);
}
- NdisReleaseRWLock(switchContext->dispatchLock, &lockState);
if (isInternalPort) {
OvsInternalAdapterDown(vport->portNo, vport->netCfgInstanceId);
OvsRemoveAndDeleteVport(NULL, switchContext, vport, TRUE, TRUE);
OvsPostVportEvent(&event);
}
+ NdisReleaseRWLock(switchContext->dispatchLock, &lockState);
done:
VPORT_NIC_EXIT(nicParam);
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/debian/changelog openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/debian/changelog
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/debian/changelog 2020-03-06 12:35:38.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/debian/changelog 2020-03-11 16:21:39.000000000 +0000
@@ -1,8 +1,12 @@
-openvswitch (2.10.0+2018.08.28+git.8ca7c82b7d+ds1-12+deb10u2~bpo10+1) UNRELEASED; urgency=medium
+openvswitch (2.10.4+2020.01.14.b2ccc307f1+dfsg1-1+deb10u3) UNRELEASED; urgency=medium
- * Rebuilt by bop.
+ * New upstream point release + git head.
+ * Refreshed patches. Disabled "disable-failed-tests.patch" which doesn't
+ apply anymore.
+ * Disable patch:
+ Fix_vswitchd_abort_when_a_port_is_added_and_the_controller_is_down.patch.
- -- Jenkins Fri, 06 Mar 2020 12:35:38 +0000
+ -- Thomas Goirand Wed, 11 Mar 2020 17:21:39 +0100
openvswitch (2.10.0+2018.08.28+git.8ca7c82b7d+ds1-12+deb10u2) buster; urgency=medium
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/debian/patches/blacklist-ofproto-async-msg-ctrl-of1.3-because-of-mips.patch openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/debian/patches/blacklist-ofproto-async-msg-ctrl-of1.3-because-of-mips.patch
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/debian/patches/blacklist-ofproto-async-msg-ctrl-of1.3-because-of-mips.patch 2020-03-06 12:35:38.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/debian/patches/blacklist-ofproto-async-msg-ctrl-of1.3-because-of-mips.patch 2020-03-11 16:21:39.000000000 +0000
@@ -5,9 +5,11 @@
Forwarded: not-needed
Last-Update: 2018-10-22
---- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1.orig/tests/ofproto.at
-+++ openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/ofproto.at
-@@ -3446,121 +3446,6 @@ OVS_APP_EXIT_AND_WAIT([ovs-ofctl])
+Index: openvswitch/tests/ofproto.at
+===================================================================
+--- openvswitch.orig/tests/ofproto.at
++++ openvswitch/tests/ofproto.at
+@@ -3476,121 +3476,6 @@ OVS_APP_EXIT_AND_WAIT([ovs-ofctl])
OVS_VSWITCHD_STOP
AT_CLEANUP
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/debian/patches/disable-even-more-tests.patch openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/debian/patches/disable-even-more-tests.patch
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/debian/patches/disable-even-more-tests.patch 2020-03-06 12:35:38.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/debian/patches/disable-even-more-tests.patch 2020-03-11 16:21:39.000000000 +0000
@@ -4,8 +4,10 @@
Forwarded: no
Last-Update: 2018-10-12
---- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1.orig/tests/ofproto-dpif.at
-+++ openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/ofproto-dpif.at
+Index: openvswitch/tests/ofproto-dpif.at
+===================================================================
+--- openvswitch.orig/tests/ofproto-dpif.at
++++ openvswitch/tests/ofproto-dpif.at
@@ -474,93 +474,6 @@ recirc_id(0x1),dp_hash(0xXXXX/0xf),in_po
OVS_VSWITCHD_STOP
AT_CLEANUP
@@ -100,9 +102,11 @@
AT_SETUP([ofproto-dpif - select group with explicit dp_hash selection method])
OVS_VSWITCHD_START
---- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1.orig/tests/ofproto.at
-+++ openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/ofproto.at
-@@ -738,44 +738,6 @@ AT_CHECK([ovs-ofctl -O OpenFlow11 -vwarn
+Index: openvswitch/tests/ofproto.at
+===================================================================
+--- openvswitch.orig/tests/ofproto.at
++++ openvswitch/tests/ofproto.at
+@@ -752,44 +752,6 @@ AT_CHECK([ovs-ofctl -O OpenFlow11 -vwarn
OVS_VSWITCHD_STOP
AT_CLEANUP
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/debian/patches/Fix_vswitchd_abort_when_a_port_is_added_and_the_controller_is_down.patch openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/debian/patches/Fix_vswitchd_abort_when_a_port_is_added_and_the_controller_is_down.patch
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/debian/patches/Fix_vswitchd_abort_when_a_port_is_added_and_the_controller_is_down.patch 2020-03-06 12:35:38.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/debian/patches/Fix_vswitchd_abort_when_a_port_is_added_and_the_controller_is_down.patch 2020-03-11 16:21:39.000000000 +0000
@@ -41,13 +41,13 @@
Origin: upstream, https://github.com/openvswitch/ovs/commit/903f6c4f8a9bce51984435ca3990f2717c63f703.patch
Last-Update: 2020-03-06
-diff --git a/ofproto/connmgr.c b/ofproto/connmgr.c
-index 50e0b8f991..9431200249 100644
---- a/ofproto/connmgr.c
-+++ b/ofproto/connmgr.c
-@@ -1538,6 +1538,10 @@ ofconn_receives_async_msg(const struct ofconn *ofconn,
- ovs_assert(reason < 32);
- ovs_assert((unsigned int) type < OAM_N_TYPES);
+Index: openvswitch/ofproto/connmgr.c
+===================================================================
+--- openvswitch.orig/ofproto/connmgr.c
++++ openvswitch/ofproto/connmgr.c
+@@ -1542,6 +1542,10 @@ ofconn_receives_async_msg(const struct o
+ return false;
+ }
+ if (!rconn_is_connected(ofconn->rconn)) {
+ return false;
@@ -56,11 +56,11 @@
/* Keep the following code in sync with the documentation in the
* "Asynchronous Messages" section in 'topics/design' */
-diff --git a/tests/bridge.at b/tests/bridge.at
-index 1c36185632..ee398bdb1e 100644
---- a/tests/bridge.at
-+++ b/tests/bridge.at
-@@ -79,3 +79,24 @@ AT_CHECK([ovs-vsctl --columns=status list controller | dnl
+Index: openvswitch/tests/bridge.at
+===================================================================
+--- openvswitch.orig/tests/bridge.at
++++ openvswitch/tests/bridge.at
+@@ -103,3 +103,24 @@ AT_CHECK([ovs-appctl -t ovs-vswitchd ver
OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])
OVS_APP_EXIT_AND_WAIT([ovsdb-server])
AT_CLEANUP
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/debian/patches/ovs-dev-ovs-macros-Make-tests-log-how-long-they-waited-when-they-succeed..diff openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/debian/patches/ovs-dev-ovs-macros-Make-tests-log-how-long-they-waited-when-they-succeed..diff
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/debian/patches/ovs-dev-ovs-macros-Make-tests-log-how-long-they-waited-when-they-succeed..diff 2020-03-06 12:35:38.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/debian/patches/ovs-dev-ovs-macros-Make-tests-log-how-long-they-waited-when-they-succeed..diff 2020-03-11 16:21:39.000000000 +0000
@@ -21,7 +21,7 @@
sort $exp_text > expout
}
])
-@@ -4290,6 +4288,9 @@ test_dhcp() {
+@@ -4298,6 +4296,9 @@ test_dhcp() {
# dhcp message type
request=${request}3501${dhcp_type}ff
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/debian/patches/removed-tests-which-are-failing-in-mips-and-armel.patch openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/debian/patches/removed-tests-which-are-failing-in-mips-and-armel.patch
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/debian/patches/removed-tests-which-are-failing-in-mips-and-armel.patch 2020-03-06 12:35:38.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/debian/patches/removed-tests-which-are-failing-in-mips-and-armel.patch 2020-03-11 16:21:39.000000000 +0000
@@ -4,8 +4,10 @@
Forwarded: not-needed
Last-Update: 2018-10-10
---- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1.orig/tests/ofproto-dpif.at
-+++ openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/ofproto-dpif.at
+Index: openvswitch/tests/ofproto-dpif.at
+===================================================================
+--- openvswitch.orig/tests/ofproto-dpif.at
++++ openvswitch/tests/ofproto-dpif.at
@@ -1864,70 +1864,6 @@ OVS_VSWITCHD_STOP
AT_CLEANUP
@@ -77,9 +79,11 @@
AT_SETUP([ofproto-dpif - MPLS handling])
OVS_VSWITCHD_START([dnl
add-port br0 p1 -- set Interface p1 type=dummy
---- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1.orig/tests/ofproto.at
-+++ openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/ofproto.at
-@@ -3599,215 +3599,6 @@ OVS_APP_EXIT_AND_WAIT([ovs-ofctl])
+Index: openvswitch/tests/ofproto.at
+===================================================================
+--- openvswitch.orig/tests/ofproto.at
++++ openvswitch/tests/ofproto.at
+@@ -3629,215 +3629,6 @@ OVS_APP_EXIT_AND_WAIT([ovs-ofctl])
OVS_VSWITCHD_STOP
AT_CLEANUP
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/debian/patches/remove-non-deterministic-tests.patch openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/debian/patches/remove-non-deterministic-tests.patch
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/debian/patches/remove-non-deterministic-tests.patch 2020-03-06 12:35:38.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/debian/patches/remove-non-deterministic-tests.patch 2020-03-11 16:21:39.000000000 +0000
@@ -5,8 +5,10 @@
Forwarded: no
Last-Update: 2018-12-14
---- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1.orig/tests/ovsdb-cluster.at
-+++ openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/ovsdb-cluster.at
+Index: openvswitch/tests/ovsdb-cluster.at
+===================================================================
+--- openvswitch.orig/tests/ovsdb-cluster.at
++++ openvswitch/tests/ovsdb-cluster.at
@@ -246,36 +246,3 @@ AT_SETUP([OVSDB 5-server torture test -
AT_KEYWORDS([ovsdb server positive unix cluster cluster5])
ovsdb_torture_test 5 5 kill
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/debian/patches/remove-tests-broken-in-mips64el-and-mipsel.patch openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/debian/patches/remove-tests-broken-in-mips64el-and-mipsel.patch
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/debian/patches/remove-tests-broken-in-mips64el-and-mipsel.patch 2020-03-06 12:35:38.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/debian/patches/remove-tests-broken-in-mips64el-and-mipsel.patch 2020-03-11 16:21:39.000000000 +0000
@@ -6,9 +6,11 @@
Forwarded: no
Last-Update: 2018-08-30
---- openvswitch-2.8.1+dfsg1.orig/tests/ofproto-dpif.at
-+++ openvswitch-2.8.1+dfsg1/tests/ofproto-dpif.at
-@@ -1888,13 +1888,6 @@
+Index: openvswitch/tests/ofproto-dpif.at
+===================================================================
+--- openvswitch.orig/tests/ofproto-dpif.at
++++ openvswitch/tests/ofproto-dpif.at
+@@ -1888,13 +1888,6 @@ flow-dump from non-dpdk interfaces:
packets:1, bytes:14, used:0.001s, actions:userspace(pid=0,controller(reason=1,dont_send=0,continuation=0,recirc_id=1,rule_cookie=0,controller_id=0,max_len=65535))
])
@@ -22,7 +24,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])
-@@ -6559,25 +6552,6 @@
+@@ -6627,25 +6620,6 @@ AT_CHECK([ovs-appctl time/warp 2000 100]
AT_CHECK([ovs-appctl revalidator/purge], [0])
OVS_VSWITCHD_STOP
OVS_APP_EXIT_AND_WAIT([test-sflow])
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/debian/patches/remove-yet-another-mips-failing-test.patch openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/debian/patches/remove-yet-another-mips-failing-test.patch
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/debian/patches/remove-yet-another-mips-failing-test.patch 2020-03-06 12:35:38.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/debian/patches/remove-yet-another-mips-failing-test.patch 2020-03-11 16:21:39.000000000 +0000
@@ -3,9 +3,11 @@
Forwarded: no
Last-Update: 2018-10-25
---- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1.orig/tests/ovn.at
-+++ openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/ovn.at
-@@ -2039,208 +2039,6 @@ OVN_CLEANUP([hv1],[hv2])
+Index: openvswitch/tests/ovn.at
+===================================================================
+--- openvswitch.orig/tests/ovn.at
++++ openvswitch/tests/ovn.at
+@@ -2047,208 +2047,6 @@ OVN_CLEANUP([hv1],[hv2])
AT_CLEANUP
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/debian/patches/series openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/debian/patches/series
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/debian/patches/series 2020-03-06 12:35:38.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/debian/patches/series 2020-03-11 16:21:39.000000000 +0000
@@ -1,7 +1,7 @@
remove-include-debian-automake.mk.patch
remove-tests-broken-in-mips64el-and-mipsel.patch
remove-bfd-decay-tests.patch
-disable-failed-tests.patch
+#disable-failed-tests.patch
py3-compat.patch
use-python3-m-sphinx-to-build-doc.patch
ovs-dev-ovs-macros-Make-tests-log-how-long-they-waited-when-they-succeed..diff
@@ -10,4 +10,4 @@
blacklist-ofproto-async-msg-ctrl-of1.3-because-of-mips.patch
remove-yet-another-mips-failing-test.patch
remove-non-deterministic-tests.patch
-Fix_vswitchd_abort_when_a_port_is_added_and_the_controller_is_down.patch
+#Fix_vswitchd_abort_when_a_port_is_added_and_the_controller_is_down.patch
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/Documentation/faq/releases.rst openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/Documentation/faq/releases.rst
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/Documentation/faq/releases.rst 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/Documentation/faq/releases.rst 2020-03-11 16:15:44.000000000 +0000
@@ -165,10 +165,10 @@
2.4.x 2.0
2.5.x 2.2
2.6.x 16.07.2
- 2.7.x 16.11.7
+ 2.7.x 16.11.8
2.8.x 17.05.2
- 2.9.x 17.11.3
- 2.10.x 17.11.3
+ 2.9.x 17.11.6
+ 2.10.x 17.11.6
============ =======
Q: Are all the DPDK releases that OVS versions work with maintained?
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/Documentation/faq/vlan.rst openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/Documentation/faq/vlan.rst
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/Documentation/faq/vlan.rst 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/Documentation/faq/vlan.rst 2020-03-11 16:15:44.000000000 +0000
@@ -191,7 +191,7 @@
$ ovs-vsctl add-port br0 vlan9 tag=9 \
-- set interface vlan9 type=internal
$ ip addr add 192.168.0.7/24 dev vlan9
- $ ip link set vlan0 up
+ $ ip link set vlan9 up
See also the following question.
@@ -203,7 +203,7 @@
$ ip link set br0 up
$ ovs-vsctl add-port br0 vlan9 tag=9 -- set interface vlan9 type=internal
$ ip addr add 192.168.0.9/24 dev vlan9
- $ ip link set vlan0 up
+ $ ip link set vlan9 up
but other hosts that are only on VLAN 0 can reach the IP address configured on
VLAN 9. What's going on?
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/Documentation/howto/dpdk.rst openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/Documentation/howto/dpdk.rst
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/Documentation/howto/dpdk.rst 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/Documentation/howto/dpdk.rst 2020-03-11 16:15:44.000000000 +0000
@@ -284,7 +284,7 @@
We must configure with appropriate software versions to ensure this feature
is supported.
- .. list-table:: Recommended BIOS Settings
+ .. list-table:: VM Configuration
:header-rows: 1
* - Setting
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/Documentation/internals/mailing-lists.rst openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/Documentation/internals/mailing-lists.rst
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/Documentation/internals/mailing-lists.rst 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/Documentation/internals/mailing-lists.rst 2020-03-11 16:15:44.000000000 +0000
@@ -93,4 +93,4 @@
The `security`__ mailing list is for submitting security vulnerabilities to the
security team.
-__ security@ovs.org
+__ security@openvswitch.org
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/Documentation/intro/install/dpdk.rst openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/Documentation/intro/install/dpdk.rst
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/Documentation/intro/install/dpdk.rst 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/Documentation/intro/install/dpdk.rst 2020-03-11 16:15:44.000000000 +0000
@@ -42,7 +42,7 @@
In addition to the requirements described in :doc:`general`, building Open
vSwitch with DPDK will require the following:
-- DPDK 17.11.3
+- DPDK 17.11.6
- A `DPDK supported NIC`_
@@ -71,9 +71,9 @@
#. Download the `DPDK sources`_, extract the file and set ``DPDK_DIR``::
$ cd /usr/src/
- $ wget http://fast.dpdk.org/rel/dpdk-17.11.3.tar.xz
- $ tar xf dpdk-17.11.3.tar.xz
- $ export DPDK_DIR=/usr/src/dpdk-stable-17.11.3
+ $ wget http://fast.dpdk.org/rel/dpdk-17.11.6.tar.xz
+ $ tar xf dpdk-17.11.6.tar.xz
+ $ export DPDK_DIR=/usr/src/dpdk-stable-17.11.6
$ cd $DPDK_DIR
#. (Optional) Configure DPDK as a shared library
@@ -661,7 +661,6 @@
Limitations
------------
-- Currently DPDK ports does not use HW offload functionality.
- Network Interface Firmware requirements: Each release of DPDK is
validated against a specific firmware version for a supported Network
Interface. New firmware versions introduce bug fixes, performance
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/Documentation/intro/what-is-ovs.rst openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/Documentation/intro/what-is-ovs.rst
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/Documentation/intro/what-is-ovs.rst 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/Documentation/intro/what-is-ovs.rst 2020-03-11 16:15:44.000000000 +0000
@@ -33,9 +33,9 @@
Overview
--------
-.. NOTE(stephenfin): The below line numbers may need to be updated if the
- README is modified
+.. NOTE(stephenfin): The below start-after/end-before may need to be updated
+ if the README is modified.
.. include:: ../../README.rst
- :start-line: 13
- :end-line: 71
+ :start-after: What is Open vSwitch?
+ :end-before: What other documentation is available?
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/Documentation/ref/ovsdb-server.7.rst openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/Documentation/ref/ovsdb-server.7.rst
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/Documentation/ref/ovsdb-server.7.rst 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/Documentation/ref/ovsdb-server.7.rst 2020-03-11 16:15:44.000000000 +0000
@@ -455,9 +455,10 @@
For , RFC 7047 only allows the use of ``!=``, ``==``, ``includes``,
and ``excludes`` operators with set types. Open vSwitch 2.4 and later extend
to allow the use of ``<``, ``<=``, ``>=``, and ``>`` operators with
-columns with type "set of 0 or 1 integer" and "set of 0 or 1 real". These
-conditions evaluate to false when the column is empty, and otherwise as
-described in RFC 7047 for integer and real types.
+a column with type "set of 0 or 1 integer" and an integer argument, and with
+"set of 0 or 1 real" and a real argument. These conditions evaluate to false
+when the column is empty, and otherwise as described in RFC 7047 for integer
+and real types.
is specified in Section 5.1 in the RFC with the following change: A
condition can be either a 3-element JSON array as described in the RFC or a
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/Documentation/topics/dpdk/vhost-user.rst openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/Documentation/topics/dpdk/vhost-user.rst
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/Documentation/topics/dpdk/vhost-user.rst 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/Documentation/topics/dpdk/vhost-user.rst 2020-03-11 16:15:44.000000000 +0000
@@ -320,9 +320,9 @@
DPDK sources to VM and build DPDK::
$ cd /root/dpdk/
- $ wget http://fast.dpdk.org/rel/dpdk-17.11.3.tar.xz
- $ tar xf dpdk-17.11.3.tar.xz
- $ export DPDK_DIR=/root/dpdk/dpdk-stable-17.11.3
+ $ wget http://fast.dpdk.org/rel/dpdk-17.11.6.tar.xz
+ $ tar xf dpdk-17.11.6.tar.xz
+ $ export DPDK_DIR=/root/dpdk/dpdk-stable-17.11.6
$ export DPDK_TARGET=x86_64-native-linuxapp-gcc
$ export DPDK_BUILD=$DPDK_DIR/$DPDK_TARGET
$ cd $DPDK_DIR
@@ -500,12 +500,6 @@
Because of this limitation, this feature is considered 'experimental'.
-The feature currently does not fully work with QEMU >= v2.7 due to a bug in
-DPDK which will be addressed in an upcoming release. The patch to fix this
-issue can be found on
-`Patchwork
-`__
-
Further information can be found in the
`DPDK documentation
`__
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/Documentation/topics/tracing.rst openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/Documentation/topics/tracing.rst
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/Documentation/topics/tracing.rst 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/Documentation/topics/tracing.rst 2020-03-11 16:15:44.000000000 +0000
@@ -39,7 +39,7 @@
--------------
In order to understand the tool, let's use the following flows as an
-example:
+example::
table=3,ip,tcp,tcp_dst=80,action=output:2
table=2,ip,tcp,tcp_dst=22,action=output:1
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/Documentation/tutorials/ovs-conntrack.rst openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/Documentation/tutorials/ovs-conntrack.rst
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/Documentation/tutorials/ovs-conntrack.rst 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/Documentation/tutorials/ovs-conntrack.rst 2020-03-11 16:15:44.000000000 +0000
@@ -325,7 +325,7 @@
(flow #2)
$ ovs-ofctl add-flow br0 \
- "table=0, priority=50, ct_state=+trk,+new, tcp, in_port=veth_l0, actions=ct(commit),veth_r0"
+ "table=0, priority=50, ct_state=+trk+new, tcp, in_port=veth_l0, actions=ct(commit),veth_r0"
Now that the packet is coming back from conntrack, the ct_state would have
the "trk" set.
@@ -364,7 +364,7 @@
"table=0, priority=50, ct_state=-trk, tcp, in_port=veth_r0, actions=ct(table=0)"
(flow #4)
$ ovs-ofctl add-flow br0 \
- "table=0, priority=50, ct_state=+trk,+est, tcp, in_port=veth_r0, actions=veth_l0"
+ "table=0, priority=50, ct_state=+trk+est, tcp, in_port=veth_r0, actions=veth_l0"
flow #3 matches untracked packets coming back from server (10.0.0.2) and sends
@@ -400,7 +400,7 @@
(flow #5)
$ ovs-ofctl add-flow br0 \
- "table=0, priority=50, ct_state=+trk,+est, tcp, in_port=veth_l0, actions=veth_r0"
+ "table=0, priority=50, ct_state=+trk+est, tcp, in_port=veth_l0, actions=veth_r0"
Send the third TCP ack segment using scapy (at the "left" scapy session)
(flags=0x10 is ack)::
@@ -557,7 +557,7 @@
(flow #2)
$ ovs-ofctl add-flow br0 \
- "table=0, priority=50, ct_state=+trk,+new, tcp, in_port=veth_l0, actions=ct(commit),veth_r0"
+ "table=0, priority=50, ct_state=+trk+new, tcp, in_port=veth_l0, actions=ct(commit),veth_r0"
(flow #3)
$ ovs-ofctl add-flow br0 \
@@ -565,8 +565,8 @@
(flow #4)
$ ovs-ofctl add-flow br0 \
- "table=0, priority=50, ct_state=+trk,+est, tcp, in_port=veth_r0, actions=veth_l0"
+ "table=0, priority=50, ct_state=+trk+est, tcp, in_port=veth_r0, actions=veth_l0"
(flow #5)
$ ovs-ofctl add-flow br0 \
- "table=0, priority=50, ct_state=+trk,+est, tcp, in_port=veth_l0, actions=veth_r0"
+ "table=0, priority=50, ct_state=+trk+est, tcp, in_port=veth_l0, actions=veth_r0"
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/include/linux/pkt_cls.h openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/include/linux/pkt_cls.h
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/include/linux/pkt_cls.h 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/include/linux/pkt_cls.h 2020-03-11 16:15:44.000000000 +0000
@@ -64,7 +64,9 @@
__u64 install;
__u64 lastuse;
__u64 expires;
+#ifdef HAVE_STRUCT_TCF_T_FIRSTUSE
__u64 firstuse;
+#endif
};
#define tc_gen \
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/include/openvswitch/compiler.h openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/include/openvswitch/compiler.h
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/include/openvswitch/compiler.h 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/include/openvswitch/compiler.h 2020-03-11 16:15:44.000000000 +0000
@@ -236,6 +236,18 @@
#define OVS_PREFETCH_WRITE(addr)
#endif
+/* Since Visual Studio 2015 there has been an effort to make offsetof a
+ * builtin_offsetof, unfortunately both implementation (the regular define and
+ * the built in one) are buggy and cause issues when using them via
+ * the C compiler.
+ * e.g.: https://bit.ly/2UvWwti
+ */
+#if _MSC_VER >= 1900
+#undef offsetof
+#define offsetof(type, member) \
+ ((size_t)((char *)&(((type *)0)->member) - (char *)0))
+#endif
+
/* Build assertions.
*
* Use BUILD_ASSERT_DECL as a declaration or a statement, or BUILD_ASSERT as
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/include/openvswitch/meta-flow.h openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/include/openvswitch/meta-flow.h
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/include/openvswitch/meta-flow.h 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/include/openvswitch/meta-flow.h 2020-03-11 16:15:44.000000000 +0000
@@ -1454,7 +1454,7 @@
*/
MFF_IP_TTL,
- /* "ip_frag".
+ /* "ip_frag" (aka "nw_frag").
*
* IP fragment information.
*
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/include/openvswitch/nsh.h openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/include/openvswitch/nsh.h
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/include/openvswitch/nsh.h 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/include/openvswitch/nsh.h 2020-03-11 16:15:44.000000000 +0000
@@ -263,10 +263,10 @@
#define NSH_M_TYPE1_LEN 24
/* NSH header maximum Length. */
-#define NSH_HDR_MAX_LEN 256
+#define NSH_HDR_MAX_LEN 252
/* NSH context headers maximum Length. */
-#define NSH_CTX_HDRS_MAX_LEN 248
+#define NSH_CTX_HDRS_MAX_LEN 244
static inline uint16_t
nsh_hdr_len(const struct nsh_hdr *nsh)
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/include/openvswitch/ofp-actions.h openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/include/openvswitch/ofp-actions.h
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/include/openvswitch/ofp-actions.h 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/include/openvswitch/ofp-actions.h 2020-03-11 16:15:44.000000000 +0000
@@ -275,16 +275,20 @@
* Action structure for actions that do not have any extra data beyond the
* action type. */
struct ofpact_null {
- struct ofpact ofpact;
+ OFPACT_PADDED_MEMBERS(
+ struct ofpact ofpact;
+ );
};
/* OFPACT_OUTPUT.
*
* Used for OFPAT10_OUTPUT. */
struct ofpact_output {
- struct ofpact ofpact;
- ofp_port_t port; /* Output port. */
- uint16_t max_len; /* Max send len, for port OFPP_CONTROLLER. */
+ OFPACT_PADDED_MEMBERS(
+ struct ofpact ofpact;
+ ofp_port_t port; /* Output port. */
+ uint16_t max_len; /* Max send len, for port OFPP_CONTROLLER. */
+ );
};
#define NX_CTLR_NO_METER 0
@@ -321,27 +325,33 @@
*
* Used for OFPAT10_ENQUEUE. */
struct ofpact_enqueue {
- struct ofpact ofpact;
- ofp_port_t port;
- uint32_t queue;
+ OFPACT_PADDED_MEMBERS(
+ struct ofpact ofpact;
+ ofp_port_t port;
+ uint32_t queue;
+ );
};
/* OFPACT_OUTPUT_REG.
*
* Used for NXAST_OUTPUT_REG. */
struct ofpact_output_reg {
- struct ofpact ofpact;
- uint16_t max_len;
- struct mf_subfield src;
+ OFPACT_PADDED_MEMBERS(
+ struct ofpact ofpact;
+ uint16_t max_len;
+ struct mf_subfield src;
+ );
};
/* OFPACT_OUTPUT_TRUNC.
*
* Used for NXAST_OUTPUT_TRUNC. */
struct ofpact_output_trunc {
- struct ofpact ofpact;
- ofp_port_t port; /* Output port. */
- uint32_t max_len; /* Max send len. */
+ OFPACT_PADDED_MEMBERS(
+ struct ofpact ofpact;
+ ofp_port_t port; /* Output port. */
+ uint32_t max_len; /* Max send len. */
+ );
};
/* Bundle slave choice algorithm to apply.
@@ -371,19 +381,21 @@
*
* Used for NXAST_BUNDLE. */
struct ofpact_bundle {
- struct ofpact ofpact;
+ OFPACT_PADDED_MEMBERS(
+ struct ofpact ofpact;
- /* Slave choice algorithm to apply to hash value. */
- enum nx_bd_algorithm algorithm;
+ /* Slave choice algorithm to apply to hash value. */
+ enum nx_bd_algorithm algorithm;
- /* What fields to hash and how. */
- enum nx_hash_fields fields;
- uint16_t basis; /* Universal hash parameter. */
+ /* What fields to hash and how. */
+ enum nx_hash_fields fields;
+ uint16_t basis; /* Universal hash parameter. */
- struct mf_subfield dst;
+ struct mf_subfield dst;
- /* Slaves for output. */
- unsigned int n_slaves;
+ /* Slaves for output. */
+ unsigned int n_slaves;
+ );
ofp_port_t slaves[];
};
@@ -396,10 +408,12 @@
*
* Used for OFPAT10_SET_VLAN_VID and OFPAT11_SET_VLAN_VID. */
struct ofpact_vlan_vid {
- struct ofpact ofpact;
- uint16_t vlan_vid; /* VLAN VID in low 12 bits, 0 in other bits. */
- bool push_vlan_if_needed; /* OF 1.0 semantics if true. */
- bool flow_has_vlan; /* VLAN present at action validation time? */
+ OFPACT_PADDED_MEMBERS(
+ struct ofpact ofpact;
+ uint16_t vlan_vid; /* VLAN VID in low 12 bits, other bits 0. */
+ bool push_vlan_if_needed; /* OF 1.0 semantics if true. */
+ bool flow_has_vlan; /* VLAN present at action validation time? */
+ );
};
/* OFPACT_SET_VLAN_PCP.
@@ -411,84 +425,104 @@
*
* Used for OFPAT10_SET_VLAN_PCP and OFPAT11_SET_VLAN_PCP. */
struct ofpact_vlan_pcp {
- struct ofpact ofpact;
- uint8_t vlan_pcp; /* VLAN PCP in low 3 bits, 0 in other bits. */
- bool push_vlan_if_needed; /* OF 1.0 semantics if true. */
- bool flow_has_vlan; /* VLAN present at action validation time? */
+ OFPACT_PADDED_MEMBERS(
+ struct ofpact ofpact;
+ uint8_t vlan_pcp; /* VLAN PCP in low 3 bits, other bits 0. */
+ bool push_vlan_if_needed; /* OF 1.0 semantics if true. */
+ bool flow_has_vlan; /* VLAN present at action validation? */
+ );
};
/* OFPACT_PUSH_VLAN.
*
* Used for OFPAT11_PUSH_VLAN. */
struct ofpact_push_vlan {
- struct ofpact ofpact;
- ovs_be16 ethertype;
+ OFPACT_PADDED_MEMBERS(
+ struct ofpact ofpact;
+ ovs_be16 ethertype;
+ );
};
/* OFPACT_SET_ETH_SRC, OFPACT_SET_ETH_DST.
*
* Used for OFPAT10_SET_DL_SRC, OFPAT10_SET_DL_DST. */
struct ofpact_mac {
- struct ofpact ofpact;
- struct eth_addr mac;
+ OFPACT_PADDED_MEMBERS(
+ struct ofpact ofpact;
+ struct eth_addr mac;
+ );
};
/* OFPACT_SET_IPV4_SRC, OFPACT_SET_IPV4_DST.
*
* Used for OFPAT10_SET_NW_SRC, OFPAT10_SET_NW_DST. */
struct ofpact_ipv4 {
- struct ofpact ofpact;
- ovs_be32 ipv4;
+ OFPACT_PADDED_MEMBERS(
+ struct ofpact ofpact;
+ ovs_be32 ipv4;
+ );
};
/* OFPACT_SET_IP_DSCP.
*
* Used for OFPAT10_SET_NW_TOS. */
struct ofpact_dscp {
- struct ofpact ofpact;
- uint8_t dscp; /* DSCP in high 6 bits, rest ignored. */
+ OFPACT_PADDED_MEMBERS(
+ struct ofpact ofpact;
+ uint8_t dscp; /* DSCP in high 6 bits, rest ignored. */
+ );
};
/* OFPACT_SET_IP_ECN.
*
* Used for OFPAT11_SET_NW_ECN. */
struct ofpact_ecn {
- struct ofpact ofpact;
- uint8_t ecn; /* ECN in low 2 bits, rest ignored. */
+ OFPACT_PADDED_MEMBERS(
+ struct ofpact ofpact;
+ uint8_t ecn; /* ECN in low 2 bits, rest ignored. */
+ );
};
/* OFPACT_SET_IP_TTL.
*
* Used for OFPAT11_SET_NW_TTL. */
struct ofpact_ip_ttl {
- struct ofpact ofpact;
- uint8_t ttl;
+ OFPACT_PADDED_MEMBERS(
+ struct ofpact ofpact;
+ uint8_t ttl;
+ );
};
/* OFPACT_SET_L4_SRC_PORT, OFPACT_SET_L4_DST_PORT.
*
* Used for OFPAT10_SET_TP_SRC, OFPAT10_SET_TP_DST. */
struct ofpact_l4_port {
- struct ofpact ofpact;
- uint16_t port; /* TCP, UDP or SCTP port number. */
- uint8_t flow_ip_proto; /* IP proto from corresponding match, or 0 */
+ OFPACT_PADDED_MEMBERS(
+ struct ofpact ofpact;
+ uint16_t port; /* TCP, UDP or SCTP port number. */
+ uint8_t flow_ip_proto; /* IP proto from corresponding match, or 0 */
+ );
};
/* OFPACT_REG_MOVE.
*
* Used for NXAST_REG_MOVE. */
struct ofpact_reg_move {
- struct ofpact ofpact;
- struct mf_subfield src;
- struct mf_subfield dst;
+ OFPACT_PADDED_MEMBERS(
+ struct ofpact ofpact;
+ struct mf_subfield src;
+ struct mf_subfield dst;
+ );
};
/* OFPACT_STACK_PUSH, OFPACT_STACK_POP.
*
* Used for NXAST_STACK_PUSH and NXAST_STACK_POP. */
struct ofpact_stack {
- struct ofpact ofpact;
- struct mf_subfield subfield;
+ OFPACT_PADDED_MEMBERS(
+ struct ofpact ofpact;
+ struct mf_subfield subfield;
+ );
};
/* OFPACT_SET_FIELD.
@@ -517,59 +551,73 @@
*
* Used for NXAST_PUSH_MPLS, OFPAT11_PUSH_MPLS. */
struct ofpact_push_mpls {
- struct ofpact ofpact;
- ovs_be16 ethertype;
+ OFPACT_PADDED_MEMBERS(
+ struct ofpact ofpact;
+ ovs_be16 ethertype;
+ );
};
/* OFPACT_POP_MPLS
*
* Used for NXAST_POP_MPLS, OFPAT11_POP_MPLS.. */
struct ofpact_pop_mpls {
- struct ofpact ofpact;
- ovs_be16 ethertype;
+ OFPACT_PADDED_MEMBERS(
+ struct ofpact ofpact;
+ ovs_be16 ethertype;
+ );
};
/* OFPACT_SET_TUNNEL.
*
* Used for NXAST_SET_TUNNEL, NXAST_SET_TUNNEL64. */
struct ofpact_tunnel {
- struct ofpact ofpact;
- uint64_t tun_id;
+ OFPACT_PADDED_MEMBERS(
+ struct ofpact ofpact;
+ uint64_t tun_id;
+ );
};
/* OFPACT_SET_QUEUE.
*
* Used for NXAST_SET_QUEUE. */
struct ofpact_queue {
- struct ofpact ofpact;
- uint32_t queue_id;
+ OFPACT_PADDED_MEMBERS(
+ struct ofpact ofpact;
+ uint32_t queue_id;
+ );
};
/* OFPACT_FIN_TIMEOUT.
*
* Used for NXAST_FIN_TIMEOUT. */
struct ofpact_fin_timeout {
- struct ofpact ofpact;
- uint16_t fin_idle_timeout;
- uint16_t fin_hard_timeout;
+ OFPACT_PADDED_MEMBERS(
+ struct ofpact ofpact;
+ uint16_t fin_idle_timeout;
+ uint16_t fin_hard_timeout;
+ );
};
/* OFPACT_WRITE_METADATA.
*
* Used for NXAST_WRITE_METADATA. */
struct ofpact_metadata {
- struct ofpact ofpact;
- ovs_be64 metadata;
- ovs_be64 mask;
+ OFPACT_PADDED_MEMBERS(
+ struct ofpact ofpact;
+ ovs_be64 metadata;
+ ovs_be64 mask;
+ );
};
/* OFPACT_METER.
*
* Used for OFPIT13_METER. */
struct ofpact_meter {
- struct ofpact ofpact;
- uint32_t meter_id;
- uint32_t provider_meter_id;
+ OFPACT_PADDED_MEMBERS(
+ struct ofpact ofpact;
+ uint32_t meter_id;
+ uint32_t provider_meter_id;
+ );
};
/* OFPACT_WRITE_ACTIONS, OFPACT_CLONE.
@@ -657,25 +705,27 @@
*
* Used for NXAST_NAT. */
struct ofpact_nat {
- struct ofpact ofpact;
- uint8_t range_af; /* AF_UNSPEC, AF_INET, or AF_INET6 */
- uint16_t flags; /* NX_NAT_F_* */
- struct {
+ OFPACT_PADDED_MEMBERS(
+ struct ofpact ofpact;
+ uint8_t range_af; /* AF_UNSPEC, AF_INET, or AF_INET6 */
+ uint16_t flags; /* NX_NAT_F_* */
struct {
- uint16_t min;
- uint16_t max;
- } proto;
- union {
- struct {
- ovs_be32 min;
- ovs_be32 max;
- } ipv4;
struct {
- struct in6_addr min;
- struct in6_addr max;
- } ipv6;
- } addr;
- } range;
+ uint16_t min;
+ uint16_t max;
+ } proto;
+ union {
+ struct {
+ ovs_be32 min;
+ ovs_be32 max;
+ } ipv4;
+ struct {
+ struct in6_addr min;
+ struct in6_addr max;
+ } ipv6;
+ } addr;
+ } range;
+ );
};
@@ -683,11 +733,13 @@
*
* Used for NXAST_RESUBMIT, NXAST_RESUBMIT_TABLE, NXAST_RESUBMIT_TABLE_CT. */
struct ofpact_resubmit {
- struct ofpact ofpact;
- ofp_port_t in_port;
- uint8_t table_id;
- bool with_ct_orig; /* Resubmit with Conntrack original direction tuple
- * fields in place of IP header fields. */
+ OFPACT_PADDED_MEMBERS(
+ struct ofpact ofpact;
+ ofp_port_t in_port;
+ uint8_t table_id;
+ bool with_ct_orig; /* Resubmit with Conntrack original direction tuple
+ * fields in place of IP header fields. */
+ );
};
/* Bits for 'flags' in struct nx_action_learn.
@@ -747,7 +799,7 @@
* NX_LEARN_DST_LOAD only. */
uint16_t src_type; /* One of NX_LEARN_SRC_*. */
uint16_t dst_type; /* One of NX_LEARN_DST_*. */
- uint8_t n_bits; /* Number of bits in source and dest. */
+ uint32_t n_bits; /* Number of bits in source and dest. */
);
/* Followed by 'DIV_ROUND_UP(n_bits, 8)' bytes of immediate data for
* match 'dst_type's NX_LEARN_DST_MATCH and NX_LEARN_DST_LOAD when
@@ -870,37 +922,43 @@
*
* Used for NXAST_CONJUNCTION. */
struct ofpact_conjunction {
- struct ofpact ofpact;
- uint8_t clause;
- uint8_t n_clauses;
- uint32_t id;
+ OFPACT_PADDED_MEMBERS(
+ struct ofpact ofpact;
+ uint8_t clause;
+ uint8_t n_clauses;
+ uint32_t id;
+ );
};
/* OFPACT_MULTIPATH.
*
* Used for NXAST_MULTIPATH. */
struct ofpact_multipath {
- struct ofpact ofpact;
+ OFPACT_PADDED_MEMBERS(
+ struct ofpact ofpact;
- /* What fields to hash and how. */
- enum nx_hash_fields fields;
- uint16_t basis; /* Universal hash parameter. */
-
- /* Multipath link choice algorithm to apply to hash value. */
- enum nx_mp_algorithm algorithm;
- uint16_t max_link; /* Number of output links, minus 1. */
- uint32_t arg; /* Algorithm-specific argument. */
+ /* What fields to hash and how. */
+ enum nx_hash_fields fields;
+ uint16_t basis; /* Universal hash parameter. */
+
+ /* Multipath link choice algorithm to apply to hash value. */
+ enum nx_mp_algorithm algorithm;
+ uint16_t max_link; /* Number of output links, minus 1. */
+ uint32_t arg; /* Algorithm-specific argument. */
- /* Where to store the result. */
- struct mf_subfield dst;
+ /* Where to store the result. */
+ struct mf_subfield dst;
+ );
};
/* OFPACT_NOTE.
*
* Used for NXAST_NOTE. */
struct ofpact_note {
- struct ofpact ofpact;
- size_t length;
+ OFPACT_PADDED_MEMBERS(
+ struct ofpact ofpact;
+ size_t length;
+ );
uint8_t data[];
};
@@ -922,23 +980,25 @@
*
* Used for NXAST_SAMPLE, NXAST_SAMPLE2, and NXAST_SAMPLE3. */
struct ofpact_sample {
- struct ofpact ofpact;
- uint16_t probability; /* Always positive. */
- uint32_t collector_set_id;
- uint32_t obs_domain_id;
- uint32_t obs_point_id;
- ofp_port_t sampling_port;
- enum nx_action_sample_direction direction;
+ OFPACT_PADDED_MEMBERS(
+ struct ofpact ofpact;
+ uint16_t probability; /* Always positive. */
+ uint32_t collector_set_id;
+ uint32_t obs_domain_id;
+ uint32_t obs_point_id;
+ ofp_port_t sampling_port;
+ enum nx_action_sample_direction direction;
+ );
};
/* OFPACT_DEC_TTL.
*
* Used for OFPAT11_DEC_NW_TTL, NXAST_DEC_TTL and NXAST_DEC_TTL_CNT_IDS. */
struct ofpact_cnt_ids {
- struct ofpact ofpact;
-
- /* Controller ids. */
- unsigned int n_controllers;
+ OFPACT_PADDED_MEMBERS(
+ struct ofpact ofpact;
+ unsigned int n_controllers;
+ );
uint16_t cnt_ids[];
};
@@ -946,54 +1006,63 @@
*
* Used for OFPAT11_SET_MPLS_LABEL and NXAST_SET_MPLS_LABEL */
struct ofpact_mpls_label {
- struct ofpact ofpact;
-
- ovs_be32 label;
+ OFPACT_PADDED_MEMBERS(
+ struct ofpact ofpact;
+ ovs_be32 label;
+ );
};
/* OFPACT_SET_MPLS_TC.
*
* Used for OFPAT11_SET_MPLS_TC and NXAST_SET_MPLS_TC */
struct ofpact_mpls_tc {
- struct ofpact ofpact;
-
- uint8_t tc;
+ OFPACT_PADDED_MEMBERS(
+ struct ofpact ofpact;
+ uint8_t tc;
+ );
};
/* OFPACT_SET_MPLS_TTL.
*
* Used for OFPAT11_SET_MPLS_TTL and NXAST_SET_MPLS_TTL */
struct ofpact_mpls_ttl {
- struct ofpact ofpact;
-
- uint8_t ttl;
+ OFPACT_PADDED_MEMBERS(
+ struct ofpact ofpact;
+ uint8_t ttl;
+ );
};
/* OFPACT_GOTO_TABLE
*
* Used for OFPIT11_GOTO_TABLE */
struct ofpact_goto_table {
- struct ofpact ofpact;
- uint8_t table_id;
+ OFPACT_PADDED_MEMBERS(
+ struct ofpact ofpact;
+ uint8_t table_id;
+ );
};
/* OFPACT_GROUP.
*
* Used for OFPAT11_GROUP. */
struct ofpact_group {
- struct ofpact ofpact;
- uint32_t group_id;
+ OFPACT_PADDED_MEMBERS(
+ struct ofpact ofpact;
+ uint32_t group_id;
+ );
};
/* OFPACT_UNROLL_XLATE.
*
* Used only internally. */
struct ofpact_unroll_xlate {
- struct ofpact ofpact;
+ OFPACT_PADDED_MEMBERS(
+ struct ofpact ofpact;
- /* Metadata in xlate context, visible to controller via PACKET_INs. */
- uint8_t rule_table_id; /* 0xFF if none. */
- ovs_be64 rule_cookie; /* OVS_BE64_MAX if none. */
+ /* Metadata in xlate context, visible to controller via PACKET_INs. */
+ uint8_t rule_table_id; /* 0xFF if none. */
+ ovs_be64 rule_cookie; /* OVS_BE64_MAX if none. */
+ );
};
/* OFPACT_ENCAP.
@@ -1001,10 +1070,12 @@
* Used for NXAST_ENCAP. */
struct ofpact_encap {
- struct ofpact ofpact;
- ovs_be32 new_pkt_type; /* Packet type of the header to add. */
- uint16_t hdr_size; /* New header size in bytes. */
- uint16_t n_props; /* Number of encap properties. */
+ OFPACT_PADDED_MEMBERS(
+ struct ofpact ofpact;
+ ovs_be32 new_pkt_type; /* Packet type of the header to add. */
+ uint16_t hdr_size; /* New header size in bytes. */
+ uint16_t n_props; /* Number of encap properties. */
+ );
struct ofpact_ed_prop props[]; /* Properties in internal format. */
};
@@ -1012,15 +1083,17 @@
*
* Used for NXAST_DECAP. */
struct ofpact_decap {
- struct ofpact ofpact;
+ OFPACT_PADDED_MEMBERS(
+ struct ofpact ofpact;
- /* New packet type.
- *
- * The special value (0,0xFFFE) "Use next proto" is used to request OVS to
- * automatically set the new packet type based on the decap'ed header's
- * next protocol.
- */
- ovs_be32 new_pkt_type;
+ /* New packet type.
+ *
+ * The special value (0,0xFFFE) "Use next proto" is used to request OVS
+ * to automatically set the new packet type based on the decap'ed
+ * header's next protocol.
+ */
+ ovs_be32 new_pkt_type;
+ );
};
/* Converting OpenFlow to ofpacts. */
@@ -1094,7 +1167,11 @@
/* Output. */
struct ofpbuf *ofpacts;
enum ofputil_protocol *usable_protocols;
+
+ /* Parse context. */
+ unsigned int depth;
};
+#define MAX_OFPACT_PARSE_DEPTH 100
char *ofpacts_parse_actions(const char *, const struct ofpact_parse_params *)
OVS_WARN_UNUSED_RESULT;
char *ofpacts_parse_instructions(const char *,
@@ -1142,21 +1219,23 @@
*
* Initializes the parts of 'ofpact' that identify it as having type
* OFPACT_ and length OFPACT__SIZE and zeros the rest.
- *
- * _SIZE
- *
- * The size of the action structure. For a fixed-length action, this is
- * sizeof(struct ) rounded up to a multiple of OFPACT_ALIGNTO. For
- * a variable-length action, this is the offset to the variable-length
- * part.
*/
#define OFPACT(ENUM, STRUCT, MEMBER, NAME) \
BUILD_ASSERT_DECL(offsetof(struct STRUCT, ofpact) == 0); \
\
- enum { OFPACT_##ENUM##_SIZE \
- = (offsetof(struct STRUCT, MEMBER) != 0 \
- ? offsetof(struct STRUCT, MEMBER) \
- : OFPACT_ALIGN(sizeof(struct STRUCT))) }; \
+ /* Action structures must be a multiple of OFPACT_ALIGNTO bytes. */ \
+ BUILD_ASSERT_DECL(sizeof(struct STRUCT) % OFPACT_ALIGNTO == 0); \
+ \
+ /* Variable-length data must start at a multiple of OFPACT_ALIGNTO \
+ * bytes. */ \
+ BUILD_ASSERT_DECL(offsetof(struct STRUCT, MEMBER) \
+ % OFPACT_ALIGNTO == 0); \
+ \
+ /* If there is variable-length data, it starts at the end of the \
+ * structure. */ \
+ BUILD_ASSERT_DECL(!offsetof(struct STRUCT, MEMBER) \
+ || (offsetof(struct STRUCT, MEMBER) \
+ == sizeof(struct STRUCT))); \
\
static inline struct STRUCT * \
ofpact_get_##ENUM(const struct ofpact *ofpact) \
@@ -1176,14 +1255,14 @@
ofpact_put_##ENUM(struct ofpbuf *ofpacts) \
{ \
return (struct STRUCT *) ofpact_put(ofpacts, OFPACT_##ENUM, \
- OFPACT_##ENUM##_SIZE); \
+ sizeof(struct STRUCT)); \
} \
\
static inline void \
ofpact_init_##ENUM(struct STRUCT *ofpact) \
{ \
ofpact_init(&ofpact->ofpact, OFPACT_##ENUM, \
- OFPACT_##ENUM##_SIZE); \
+ sizeof(struct STRUCT)); \
} \
\
static inline void \
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/include/openvswitch/ofp-group.h openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/include/openvswitch/ofp-group.h
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/include/openvswitch/ofp-group.h 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/include/openvswitch/ofp-group.h 2020-03-11 16:15:44.000000000 +0000
@@ -103,7 +103,9 @@
void ofputil_uninit_group_mod(struct ofputil_group_mod *gm);
struct ofpbuf *ofputil_encode_group_mod(enum ofp_version ofp_version,
- const struct ofputil_group_mod *gm);
+ const struct ofputil_group_mod *gm,
+ const struct ovs_list *new_buckets,
+ int group_existed);
enum ofperr ofputil_decode_group_mod(const struct ofp_header *,
struct ofputil_group_mod *);
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/include/openvswitch/ofp-monitor.h openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/include/openvswitch/ofp-monitor.h
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/include/openvswitch/ofp-monitor.h 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/include/openvswitch/ofp-monitor.h 2020-03-11 16:15:44.000000000 +0000
@@ -125,7 +125,20 @@
};
/* reason == OFPRFR_GROUP_MOD. */
- struct ofputil_group_mod *group_mod;
+ struct {
+ struct ofputil_group_mod *group_mod;
+
+ /* If nonnull, points to the full set of new buckets that resulted
+ * from a OFPGC15_INSERT_BUCKET or OFPGC15_REMOVE_BUCKET command.
+ * Needed to translate such group_mods into OpenFlow 1.1-1.4
+ * OFPGC11_MODIFY. */
+ const struct ovs_list *new_buckets;
+
+ /* If nonnegative, specifies whether the group existed before the
+ * command was executed. Needed to translate OVS's nonstandard
+ * OFPGC11_ADD_OR_MOD into a standard command. */
+ int group_existed;
+ };
};
};
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/include/sparse/bits/floatn.h openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/include/sparse/bits/floatn.h
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/include/sparse/bits/floatn.h 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/include/sparse/bits/floatn.h 2020-03-11 16:15:44.000000000 +0000
@@ -27,6 +27,9 @@
#define __HAVE_FLOAT128 0
#define __HAVE_FLOAT64X 0
+#ifdef HAVE_BITS_FLOATN_COMMON_H
+/* Introduced in glibc 2.27 */
#include
+#endif
#endif /* for sparse */
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/bfd.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/bfd.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/bfd.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/bfd.c 2020-03-11 16:15:44.000000000 +0000
@@ -672,19 +672,18 @@
if (flow->dl_type == htons(ETH_TYPE_IP)) {
memset(&wc->masks.nw_proto, 0xff, sizeof wc->masks.nw_proto);
- if (flow->nw_proto == IPPROTO_UDP && !(flow->nw_frag & FLOW_NW_FRAG_LATER)) {
- memset(&wc->masks.tp_dst, 0xff, sizeof wc->masks.tp_dst);
- if (flow->tp_dst == htons(BFD_DEST_PORT)) {
- bool check_tnl_key;
+ if (flow->nw_proto == IPPROTO_UDP
+ && !(flow->nw_frag & FLOW_NW_FRAG_LATER)
+ && tp_dst_equals(flow, BFD_DEST_PORT, wc)) {
+ bool check_tnl_key;
- atomic_read_relaxed(&bfd->check_tnl_key, &check_tnl_key);
- if (check_tnl_key) {
- memset(&wc->masks.tunnel.tun_id, 0xff,
- sizeof wc->masks.tunnel.tun_id);
- return flow->tunnel.tun_id == htonll(0);
- }
- return true;
+ atomic_read_relaxed(&bfd->check_tnl_key, &check_tnl_key);
+ if (check_tnl_key) {
+ memset(&wc->masks.tunnel.tun_id, 0xff,
+ sizeof wc->masks.tunnel.tun_id);
+ return flow->tunnel.tun_id == htonll(0);
}
+ return true;
}
}
return false;
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/cmap.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/cmap.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/cmap.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/cmap.c 2020-03-11 16:15:44.000000000 +0000
@@ -568,7 +568,7 @@
{
struct cmap_impl *impl = cmap_get_impl(cmap);
uint32_t h1 = rehash(impl, hash);
- uint32_t h2 = other_hash(hash);
+ uint32_t h2 = other_hash(h1);
struct cmap_node *node;
node = cmap_find_bucket_protected(impl, hash, h1);
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/conntrack.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/conntrack.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/conntrack.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/conntrack.c 2020-03-11 16:15:44.000000000 +0000
@@ -136,7 +136,7 @@
static int
repl_ftp_v4_addr(struct dp_packet *pkt, ovs_be32 v4_addr_rep,
char *ftp_data_v4_start,
- size_t addr_offset_from_ftp_data_start);
+ size_t addr_offset_from_ftp_data_start, size_t addr_size);
static enum ftp_ctl_pkt
process_ftp_ctl_v4(struct conntrack *ct,
@@ -144,7 +144,8 @@
const struct conn *conn_for_expectation,
ovs_be32 *v4_addr_rep,
char **ftp_data_v4_start,
- size_t *addr_offset_from_ftp_data_start);
+ size_t *addr_offset_from_ftp_data_start,
+ size_t *addr_size);
static enum ftp_ctl_pkt
detect_ftp_ctl_type(const struct conn_lookup_ctx *ctx,
@@ -352,7 +353,7 @@
struct conntrack_bucket *ctb = &ct->buckets[i];
struct conn *conn;
- ovs_mutex_destroy(&ctb->cleanup_mutex);
+ ovs_mutex_lock(&ctb->cleanup_mutex);
ct_lock_lock(&ctb->lock);
HMAP_FOR_EACH_POP (conn, node, &ctb->connections) {
if (conn->conn_type == CT_CONN_TYPE_DEFAULT) {
@@ -362,7 +363,9 @@
}
hmap_destroy(&ctb->connections);
ct_lock_unlock(&ctb->lock);
+ ovs_mutex_unlock(&ctb->cleanup_mutex);
ct_lock_destroy(&ctb->lock);
+ ovs_mutex_destroy(&ctb->cleanup_mutex);
}
ct_rwlock_wrlock(&ct->resources_lock);
struct nat_conn_key_node *nat_conn_key_node;
@@ -637,7 +640,7 @@
reverse_nat_packet(struct dp_packet *pkt, const struct conn *conn)
{
char *tail = dp_packet_tail(pkt);
- char pad = dp_packet_l2_pad_size(pkt);
+ uint8_t pad = dp_packet_l2_pad_size(pkt);
struct conn_key inner_key;
const char *inner_l4 = NULL;
uint16_t orig_l3_ofs = pkt->l3_ofs;
@@ -647,6 +650,8 @@
struct ip_header *nh = dp_packet_l3(pkt);
struct icmp_header *icmp = dp_packet_l4(pkt);
struct ip_header *inner_l3 = (struct ip_header *) (icmp + 1);
+ /* This call is already verified to succeed during the code path from
+ * 'conn_key_extract()' which calls 'extract_l4_icmp()'. */
extract_l3_ipv4(&inner_key, inner_l3, tail - ((char *)inner_l3) - pad,
&inner_l4, false);
pkt->l3_ofs += (char *) inner_l3 - (char *) nh;
@@ -668,6 +673,8 @@
struct icmp6_error_header *icmp6 = dp_packet_l4(pkt);
struct ovs_16aligned_ip6_hdr *inner_l3_6 =
(struct ovs_16aligned_ip6_hdr *) (icmp6 + 1);
+ /* This call is already verified to succeed during the code path from
+ * 'conn_key_extract()' which calls 'extract_l4_icmp6()'. */
extract_l3_ipv6(&inner_key, inner_l3_6,
tail - ((char *)inner_l3_6) - pad,
&inner_l4);
@@ -686,10 +693,9 @@
true);
}
reverse_pat_packet(pkt, conn);
- uint32_t icmp6_csum = packet_csum_pseudoheader6(nh6);
icmp6->icmp6_base.icmp6_cksum = 0;
- icmp6->icmp6_base.icmp6_cksum = csum_finish(
- csum_continue(icmp6_csum, icmp6, tail - (char *) icmp6 - pad));
+ icmp6->icmp6_base.icmp6_cksum = packet_csum_upperlayer6(nh6, icmp6,
+ IPPROTO_ICMPV6, tail - (char *) icmp6 - pad);
}
pkt->l3_ofs = orig_l3_ofs;
pkt->l4_ofs = orig_l4_ofs;
@@ -754,6 +760,43 @@
return ctx.conn;
}
+/* Only used when looking up 'CT_CONN_TYPE_DEFAULT' conns. */
+static struct conn *
+conn_lookup_def(const struct conn_key *key,
+ const struct conntrack_bucket *ctb, uint32_t hash)
+ OVS_REQUIRES(ctb->lock)
+{
+ struct conn *conn = NULL;
+
+ HMAP_FOR_EACH_WITH_HASH (conn, node, hash, &ctb->connections) {
+ if (!conn_key_cmp(&conn->key, key)
+ && conn->conn_type == CT_CONN_TYPE_DEFAULT) {
+ break;
+ }
+ if (!conn_key_cmp(&conn->rev_key, key)
+ && conn->conn_type == CT_CONN_TYPE_DEFAULT) {
+ break;
+ }
+ }
+ return conn;
+}
+
+static struct conn *
+conn_lookup_unnat(const struct conn_key *key,
+ const struct conntrack_bucket *ctb, uint32_t hash)
+ OVS_REQUIRES(ctb->lock)
+{
+ struct conn *conn = NULL;
+
+ HMAP_FOR_EACH_WITH_HASH (conn, node, hash, &ctb->connections) {
+ if (!conn_key_cmp(&conn->key, key)
+ && conn->conn_type == CT_CONN_TYPE_UN_NAT) {
+ break;
+ }
+ }
+ return conn;
+}
+
static void
conn_seq_skew_set(struct conntrack *ct, const struct conn_key *key,
long long now, int seq_skew, bool seq_skew_dir)
@@ -777,12 +820,13 @@
nat_conn_keys_remove(&ct->nat_conn_keys, &conn->rev_key, ct->hash_basis);
ct_rwlock_unlock(&ct->resources_lock);
ct_lock_unlock(&ctb->lock);
- unsigned bucket_rev_conn =
- hash_to_bucket(conn_key_hash(&conn->rev_key, ct->hash_basis));
+ uint32_t hash = conn_key_hash(&conn->rev_key, ct->hash_basis);
+ unsigned bucket_rev_conn = hash_to_bucket(hash);
ct_lock_lock(&ct->buckets[bucket_rev_conn].lock);
ct_rwlock_wrlock(&ct->resources_lock);
- long long now = time_msec();
- struct conn *rev_conn = conn_lookup(ct, &conn->rev_key, now);
+ struct conn *rev_conn = conn_lookup_unnat(&conn->rev_key,
+ &ct->buckets[bucket_rev_conn],
+ hash);
struct nat_conn_key_node *nat_conn_key_node =
nat_conn_keys_lookup(&ct->nat_conn_keys, &conn->rev_key,
ct->hash_basis);
@@ -821,6 +865,22 @@
}
}
+/* Only called for 'CT_CONN_TYPE_DEFAULT' conns; must be called with no
+ * locks held and upon return no locks are held. */
+static void
+conn_clean_safe(struct conntrack *ct, struct conn *conn,
+ struct conntrack_bucket *ctb, uint32_t hash)
+{
+ ovs_mutex_lock(&ctb->cleanup_mutex);
+ ct_lock_lock(&ctb->lock);
+ conn = conn_lookup_def(&conn->key, ctb, hash);
+ if (conn) {
+ conn_clean(ct, conn, ctb);
+ }
+ ct_lock_unlock(&ctb->lock);
+ ovs_mutex_unlock(&ctb->cleanup_mutex);
+}
+
static bool
ct_verify_helper(const char *helper, enum ct_alg_ctl_type ct_alg_ctl)
{
@@ -852,6 +912,7 @@
enum ct_alg_ctl_type ct_alg_ctl)
{
struct conn *nc = NULL;
+ struct conn connl;
if (!valid_new(pkt, &ctx->key)) {
pkt->md.ct_state = CS_INVALID;
@@ -874,9 +935,10 @@
}
unsigned bucket = hash_to_bucket(ctx->hash);
- nc = new_conn(&ct->buckets[bucket], pkt, &ctx->key, now);
- ctx->conn = nc;
- nc->rev_key = nc->key;
+ nc = &connl;
+ memset(nc, 0, sizeof *nc);
+ memcpy(&nc->key, &ctx->key, sizeof nc->key);
+ memcpy(&nc->rev_key, &nc->key, sizeof nc->rev_key);
conn_key_reverse(&nc->rev_key);
if (ct_verify_helper(helper, ct_alg_ctl)) {
@@ -919,6 +981,7 @@
ct_rwlock_wrlock(&ct->resources_lock);
bool nat_res = nat_select_range_tuple(ct, nc,
conn_for_un_nat_copy);
+ ct_rwlock_unlock(&ct->resources_lock);
if (!nat_res) {
goto nat_res_exhaustion;
@@ -926,15 +989,25 @@
/* Update nc with nat adjustments made to
* conn_for_un_nat_copy by nat_select_range_tuple(). */
- *nc = *conn_for_un_nat_copy;
- ct_rwlock_unlock(&ct->resources_lock);
+ memcpy(nc, conn_for_un_nat_copy, sizeof *nc);
}
conn_for_un_nat_copy->conn_type = CT_CONN_TYPE_UN_NAT;
conn_for_un_nat_copy->nat_info = NULL;
conn_for_un_nat_copy->alg = NULL;
nat_packet(pkt, nc, ctx->icmp_related);
}
- hmap_insert(&ct->buckets[bucket].connections, &nc->node, ctx->hash);
+ struct conn *nconn = new_conn(&ct->buckets[bucket], pkt, &ctx->key,
+ now);
+ memcpy(&nconn->key, &nc->key, sizeof nconn->key);
+ memcpy(&nconn->rev_key, &nc->rev_key, sizeof nconn->rev_key);
+ memcpy(&nconn->master_key, &nc->master_key, sizeof nconn->master_key);
+ nconn->alg_related = nc->alg_related;
+ nconn->alg = nc->alg;
+ nconn->mark = nc->mark;
+ nconn->label = nc->label;
+ nconn->nat_info = nc->nat_info;
+ ctx->conn = nc = nconn;
+ hmap_insert(&ct->buckets[bucket].connections, &nconn->node, ctx->hash);
atomic_count_inc(&ct->n_conn);
}
@@ -947,13 +1020,8 @@
* against with firewall rules or a separate firewall.
* Also using zone partitioning can limit DoS impact. */
nat_res_exhaustion:
- ovs_list_remove(&nc->exp_node);
- delete_conn(nc);
- /* conn_for_un_nat_copy is a local variable in process_one; this
- * memset() serves to document that conn_for_un_nat_copy is from
- * this point on unused. */
- memset(conn_for_un_nat_copy, 0, sizeof *conn_for_un_nat_copy);
- ct_rwlock_unlock(&ct->resources_lock);
+ free(nc->alg);
+ free(nc->nat_info);
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5);
VLOG_WARN_RL(&rl, "Unable to NAT due to tuple space exhaustion - "
"if DoS attack, use firewalling and/or zone partitioning.");
@@ -967,6 +1035,7 @@
OVS_REQUIRES(ct->buckets[bucket].lock)
{
bool create_new_conn = false;
+ struct conn lconn;
if (ctx->icmp_related) {
pkt->md.ct_state |= CS_RELATED;
@@ -993,7 +1062,10 @@
pkt->md.ct_state = CS_INVALID;
break;
case CT_UPDATE_NEW:
- conn_clean(ct, *conn, &ct->buckets[bucket]);
+ memcpy(&lconn, *conn, sizeof lconn);
+ ct_lock_unlock(&ct->buckets[bucket].lock);
+ conn_clean_safe(ct, &lconn, &ct->buckets[bucket], ctx->hash);
+ ct_lock_lock(&ct->buckets[bucket].lock);
create_new_conn = true;
break;
default:
@@ -1008,8 +1080,8 @@
long long now, bool alg_un_nat)
{
struct conn *nc = xmemdup(conn_for_un_nat_copy, sizeof *nc);
- nc->key = conn_for_un_nat_copy->rev_key;
- nc->rev_key = conn_for_un_nat_copy->key;
+ memcpy(&nc->key, &conn_for_un_nat_copy->rev_key, sizeof nc->key);
+ memcpy(&nc->rev_key, &conn_for_un_nat_copy->key, sizeof nc->rev_key);
uint32_t un_nat_hash = conn_key_hash(&nc->key, ct->hash_basis);
unsigned un_nat_conn_bucket = hash_to_bucket(un_nat_hash);
ct_lock_lock(&ct->buckets[un_nat_conn_bucket].lock);
@@ -1182,8 +1254,12 @@
conn = ctx->conn;
/* Delete found entry if in wrong direction. 'force' implies commit. */
- if (conn && force && ctx->reply) {
- conn_clean(ct, conn, &ct->buckets[bucket]);
+ if (OVS_UNLIKELY(force && ctx->reply && conn)) {
+ struct conn lconn;
+ memcpy(&lconn, conn, sizeof lconn);
+ ct_lock_unlock(&ct->buckets[bucket].lock);
+ conn_clean_safe(ct, &lconn, &ct->buckets[bucket], ctx->hash);
+ ct_lock_lock(&ct->buckets[bucket].lock);
conn = NULL;
}
@@ -1194,7 +1270,7 @@
struct conn_lookup_ctx ctx2;
ctx2.conn = NULL;
- ctx2.key = conn->rev_key;
+ memcpy(&ctx2.key, &conn->rev_key, sizeof ctx2.key);
ctx2.hash = conn_key_hash(&conn->rev_key, ct->hash_basis);
ct_lock_unlock(&ct->buckets[bucket].lock);
@@ -1280,7 +1356,7 @@
struct conn conn_for_expectation;
if (OVS_UNLIKELY((ct_alg_ctl != CT_ALG_CTL_NONE) && conn)) {
- conn_for_expectation = *conn;
+ memcpy(&conn_for_expectation, conn, sizeof conn_for_expectation);
}
ct_lock_unlock(&ct->buckets[bucket].lock);
@@ -1383,19 +1459,17 @@
for (unsigned i = 0; i < N_CT_TM; i++) {
LIST_FOR_EACH_SAFE (conn, next, exp_node, &ctb->exp_lists[i]) {
- if (conn->conn_type == CT_CONN_TYPE_DEFAULT) {
- if (!conn_expired(conn, now) || count >= limit) {
- min_expiration = MIN(min_expiration, conn->expiration);
- if (count >= limit) {
- /* Do not check other lists. */
- COVERAGE_INC(conntrack_long_cleanup);
- return min_expiration;
- }
- break;
+ if (!conn_expired(conn, now) || count >= limit) {
+ min_expiration = MIN(min_expiration, conn->expiration);
+ if (count >= limit) {
+ /* Do not check other lists. */
+ COVERAGE_INC(conntrack_long_cleanup);
+ return min_expiration;
}
- conn_clean(ct, conn, ctb);
- count++;
+ break;
}
+ conn_clean(ct, conn, ctb);
+ count++;
}
}
return min_expiration;
@@ -1413,6 +1487,8 @@
size_t clean_count = 0;
atomic_read_relaxed(&ct->n_conn_limit, &n_conn_limit);
+ size_t clean_min = n_conn_limit > CONNTRACK_BUCKETS * 10
+ ? n_conn_limit / (CONNTRACK_BUCKETS * 10) : 1;
for (unsigned i = 0; i < CONNTRACK_BUCKETS; i++) {
struct conntrack_bucket *ctb = &ct->buckets[i];
@@ -1430,8 +1506,7 @@
* limit to 10% of the global limit equally split among buckets. If
* the bucket is busier than the others, we limit to 10% of its
* current size. */
- min_exp = sweep_bucket(ct, ctb, now,
- MAX(prev_count/10, n_conn_limit/(CONNTRACK_BUCKETS*10)));
+ min_exp = sweep_bucket(ct, ctb, now, MAX(prev_count / 10, clean_min));
clean_count += prev_count - hmap_count(&ctb->connections);
if (min_exp > now) {
@@ -1581,19 +1656,14 @@
checksum_valid(const struct conn_key *key, const void *data, size_t size,
const void *l3)
{
- uint32_t csum = 0;
-
if (key->dl_type == htons(ETH_TYPE_IP)) {
- csum = packet_csum_pseudoheader(l3);
+ uint32_t csum = packet_csum_pseudoheader(l3);
+ return csum_finish(csum_continue(csum, data, size)) == 0;
} else if (key->dl_type == htons(ETH_TYPE_IPV6)) {
- csum = packet_csum_pseudoheader6(l3);
+ return packet_csum_upperlayer6(l3, data, key->nw_proto, size) == 0;
} else {
return false;
}
-
- csum = csum_continue(csum, data, size);
-
- return csum_finish(csum) == 0;
}
static inline bool
@@ -1646,9 +1716,10 @@
}
static inline bool
-extract_l4_tcp(struct conn_key *key, const void *data, size_t size)
+extract_l4_tcp(struct conn_key *key, const void *data, size_t size,
+ size_t *chk_len)
{
- if (OVS_UNLIKELY(size < TCP_HEADER_LEN)) {
+ if (OVS_UNLIKELY(size < (chk_len ? *chk_len : TCP_HEADER_LEN))) {
return false;
}
@@ -1661,9 +1732,10 @@
}
static inline bool
-extract_l4_udp(struct conn_key *key, const void *data, size_t size)
+extract_l4_udp(struct conn_key *key, const void *data, size_t size,
+ size_t *chk_len)
{
- if (OVS_UNLIKELY(size < UDP_HEADER_LEN)) {
+ if (OVS_UNLIKELY(size < (chk_len ? *chk_len : UDP_HEADER_LEN))) {
return false;
}
@@ -1677,7 +1749,7 @@
static inline bool extract_l4(struct conn_key *key, const void *data,
size_t size, bool *related, const void *l3,
- bool validate_checksum);
+ bool validate_checksum, size_t *chk_len);
static uint8_t
reverse_icmp_type(uint8_t type)
@@ -1709,9 +1781,9 @@
* possible */
static inline int
extract_l4_icmp(struct conn_key *key, const void *data, size_t size,
- bool *related)
+ bool *related, size_t *chk_len)
{
- if (OVS_UNLIKELY(size < ICMP_HEADER_LEN)) {
+ if (OVS_UNLIKELY(size < (chk_len ? *chk_len : ICMP_HEADER_LEN))) {
return false;
}
@@ -1762,8 +1834,9 @@
key->src = inner_key.src;
key->dst = inner_key.dst;
key->nw_proto = inner_key.nw_proto;
+ size_t check_len = ICMP_ERROR_DATA_L4_LEN;
- ok = extract_l4(key, l4, tail - l4, NULL, l3, false);
+ ok = extract_l4(key, l4, tail - l4, NULL, l3, false, &check_len);
if (ok) {
conn_key_reverse(key);
*related = true;
@@ -1850,7 +1923,7 @@
key->dst = inner_key.dst;
key->nw_proto = inner_key.nw_proto;
- ok = extract_l4(key, l4, tail - l4, NULL, l3, false);
+ ok = extract_l4(key, l4, tail - l4, NULL, l3, false, NULL);
if (ok) {
conn_key_reverse(key);
*related = true;
@@ -1871,27 +1944,33 @@
* processed, the function will extract the key from the packet nested
* in the ICMP payload and set '*related' to true.
*
+ * 'size' here is the layer 4 size, which can be a nested size if parsing
+ * an ICMP or ICMP6 header.
+ *
* If 'related' is NULL, it means that we're already parsing a header nested
- * in an ICMP error. In this case, we skip checksum and length validation. */
+ * in an ICMP error. In this case, we skip the checksum and some length
+ * validations. */
static inline bool
extract_l4(struct conn_key *key, const void *data, size_t size, bool *related,
- const void *l3, bool validate_checksum)
+ const void *l3, bool validate_checksum, size_t *chk_len)
{
if (key->nw_proto == IPPROTO_TCP) {
return (!related || check_l4_tcp(key, data, size, l3,
- validate_checksum)) && extract_l4_tcp(key, data, size);
+ validate_checksum))
+ && extract_l4_tcp(key, data, size, chk_len);
} else if (key->nw_proto == IPPROTO_UDP) {
return (!related || check_l4_udp(key, data, size, l3,
- validate_checksum)) && extract_l4_udp(key, data, size);
+ validate_checksum))
+ && extract_l4_udp(key, data, size, chk_len);
} else if (key->dl_type == htons(ETH_TYPE_IP)
&& key->nw_proto == IPPROTO_ICMP) {
return (!related || check_l4_icmp(data, size, validate_checksum))
- && extract_l4_icmp(key, data, size, related);
+ && extract_l4_icmp(key, data, size, related, chk_len);
} else if (key->dl_type == htons(ETH_TYPE_IPV6)
&& key->nw_proto == IPPROTO_ICMPV6) {
return (!related || check_l4_icmp6(key, data, size, l3,
- validate_checksum)) && extract_l4_icmp6(key, data, size,
- related);
+ validate_checksum))
+ && extract_l4_icmp6(key, data, size, related);
} else {
return false;
}
@@ -1945,7 +2024,6 @@
* we use a sparse representation (miniflow).
*
*/
- const char *tail = dp_packet_tail(pkt);
bool ok;
ctx->key.dl_type = dl_type;
@@ -1956,11 +2034,11 @@
} else {
bool hwol_good_l3_csum = dp_packet_ip_checksum_valid(pkt);
/* Validate the checksum only when hwol is not supported. */
- ok = extract_l3_ipv4(&ctx->key, l3, tail - (char *) l3, NULL,
+ ok = extract_l3_ipv4(&ctx->key, l3, dp_packet_l3_size(pkt), NULL,
!hwol_good_l3_csum);
}
} else if (ctx->key.dl_type == htons(ETH_TYPE_IPV6)) {
- ok = extract_l3_ipv6(&ctx->key, l3, tail - (char *) l3, NULL);
+ ok = extract_l3_ipv6(&ctx->key, l3, dp_packet_l3_size(pkt), NULL);
} else {
ok = false;
}
@@ -1970,8 +2048,9 @@
if (!hwol_bad_l4_csum) {
bool hwol_good_l4_csum = dp_packet_l4_checksum_valid(pkt);
/* Validate the checksum only when hwol is not supported. */
- if (extract_l4(&ctx->key, l4, tail - l4, &ctx->icmp_related, l3,
- !hwol_good_l4_csum)) {
+ if (extract_l4(&ctx->key, l4, dp_packet_l4_size(pkt),
+ &ctx->icmp_related, l3, !hwol_good_l4_csum,
+ NULL)) {
ctx->hash = conn_key_hash(&ctx->key, ct->hash_basis);
return true;
}
@@ -2172,7 +2251,9 @@
uint16_t port = first_port;
bool all_ports_tried = false;
- bool original_ports_tried = false;
+ /* For DNAT, we don't use ephemeral ports. */
+ bool ephemeral_ports_tried = conn->nat_info->nat_action & NAT_ACTION_DST
+ ? true : false;
struct ct_addr first_addr = ct_addr;
while (true) {
@@ -2218,9 +2299,10 @@
ct_addr = conn->nat_info->min_addr;
}
if (!memcmp(&ct_addr, &first_addr, sizeof ct_addr)) {
- if (!original_ports_tried) {
- original_ports_tried = true;
+ if (!ephemeral_ports_tried) {
+ ephemeral_ports_tried = true;
ct_addr = conn->nat_info->min_addr;
+ first_addr = ct_addr;
min_port = MIN_NAT_EPHEMERAL_PORT;
max_port = MAX_NAT_EPHEMERAL_PORT;
} else {
@@ -2262,8 +2344,10 @@
if (!nat_conn_key_node) {
struct nat_conn_key_node *nat_conn_key = xzalloc(sizeof *nat_conn_key);
- nat_conn_key->key = nat_conn->rev_key;
- nat_conn_key->value = nat_conn->key;
+ memcpy(&nat_conn_key->key, &nat_conn->rev_key,
+ sizeof nat_conn_key->key);
+ memcpy(&nat_conn_key->value, &nat_conn->key,
+ sizeof nat_conn_key->value);
hmap_insert(nat_conn_keys, &nat_conn_key->node,
conn_key_hash(&nat_conn_key->key, basis));
return true;
@@ -2342,12 +2426,7 @@
new_conn(struct conntrack_bucket *ctb, struct dp_packet *pkt,
struct conn_key *key, long long now)
{
- struct conn *newconn = l4_protos[key->nw_proto]->new_conn(ctb, pkt, now);
- if (newconn) {
- newconn->key = *key;
- }
-
- return newconn;
+ return l4_protos[key->nw_proto]->new_conn(ctb, pkt, now);
}
static void
@@ -2540,16 +2619,19 @@
conntrack_flush(struct conntrack *ct, const uint16_t *zone)
{
for (unsigned i = 0; i < CONNTRACK_BUCKETS; i++) {
- struct conn *conn, *next;
-
- ct_lock_lock(&ct->buckets[i].lock);
- HMAP_FOR_EACH_SAFE (conn, next, node, &ct->buckets[i].connections) {
- if ((!zone || *zone == conn->key.zone) &&
- (conn->conn_type == CT_CONN_TYPE_DEFAULT)) {
- conn_clean(ct, conn, &ct->buckets[i]);
+ struct conntrack_bucket *ctb = &ct->buckets[i];
+ ovs_mutex_lock(&ctb->cleanup_mutex);
+ ct_lock_lock(&ctb->lock);
+ for (unsigned j = 0; j < N_CT_TM; j++) {
+ struct conn *conn, *next;
+ LIST_FOR_EACH_SAFE (conn, next, exp_node, &ctb->exp_lists[j]) {
+ if (!zone || *zone == conn->key.zone) {
+ conn_clean(ct, conn, ctb);
+ }
}
}
- ct_lock_unlock(&ct->buckets[i].lock);
+ ct_lock_unlock(&ctb->lock);
+ ovs_mutex_unlock(&ctb->cleanup_mutex);
}
return 0;
@@ -2566,15 +2648,19 @@
tuple_to_conn_key(tuple, zone, &ctx.key);
ctx.hash = conn_key_hash(&ctx.key, ct->hash_basis);
unsigned bucket = hash_to_bucket(ctx.hash);
+ struct conntrack_bucket *ctb = &ct->buckets[bucket];
- ct_lock_lock(&ct->buckets[bucket].lock);
- conn_key_lookup(&ct->buckets[bucket], &ctx, time_msec());
- if (ctx.conn) {
- conn_clean(ct, ctx.conn, &ct->buckets[bucket]);
+ ovs_mutex_lock(&ctb->cleanup_mutex);
+ ct_lock_lock(&ctb->lock);
+ conn_key_lookup(ctb, &ctx, time_msec());
+ if (ctx.conn && ctx.conn->conn_type == CT_CONN_TYPE_DEFAULT) {
+ conn_clean(ct, ctx.conn, ctb);
} else {
+ VLOG_WARN("Must flush tuple using the original pre-NATed tuple");
error = ENOENT;
}
- ct_lock_unlock(&ct->buckets[bucket].lock);
+ ct_lock_unlock(&ctb->lock);
+ ovs_mutex_unlock(&ctb->cleanup_mutex);
return error;
}
@@ -2706,21 +2792,29 @@
if (reply) {
src_addr = master_conn->key.src.addr;
dst_addr = master_conn->key.dst.addr;
+ alg_exp_node->nat_rpl_dst = true;
if (skip_nat) {
alg_nat_repl_addr = dst_addr;
+ } else if (master_conn->nat_info &&
+ master_conn->nat_info->nat_action & NAT_ACTION_DST) {
+ alg_nat_repl_addr = master_conn->rev_key.src.addr;
+ alg_exp_node->nat_rpl_dst = false;
} else {
alg_nat_repl_addr = master_conn->rev_key.dst.addr;
}
- alg_exp_node->nat_rpl_dst = true;
} else {
src_addr = master_conn->rev_key.src.addr;
dst_addr = master_conn->rev_key.dst.addr;
+ alg_exp_node->nat_rpl_dst = false;
if (skip_nat) {
alg_nat_repl_addr = src_addr;
+ } else if (master_conn->nat_info &&
+ master_conn->nat_info->nat_action & NAT_ACTION_DST) {
+ alg_nat_repl_addr = master_conn->key.dst.addr;
+ alg_exp_node->nat_rpl_dst = true;
} else {
alg_nat_repl_addr = master_conn->key.src.addr;
}
- alg_exp_node->nat_rpl_dst = false;
}
if (src_ip_wc) {
memset(&src_addr, 0, sizeof src_addr);
@@ -2735,7 +2829,8 @@
alg_exp_node->key.dst.port = dst_port;
alg_exp_node->master_mark = master_conn->mark;
alg_exp_node->master_label = master_conn->label;
- alg_exp_node->master_key = master_conn->key;
+ memcpy(&alg_exp_node->master_key, &master_conn->key,
+ sizeof alg_exp_node->master_key);
/* Take the write lock here because it is almost 100%
* likely that the lookup will fail and
* expectation_create() will be called below. */
@@ -2756,13 +2851,6 @@
ct_rwlock_unlock(&ct->resources_lock);
}
-static uint8_t
-get_v4_byte_be(ovs_be32 v4_addr, uint8_t index)
-{
- uint8_t *byte_ptr = (OVS_FORCE uint8_t *) &v4_addr;
- return byte_ptr[index];
-}
-
static void
replace_substring(char *substr, uint8_t substr_size,
uint8_t total_size, char *rep_str,
@@ -2773,51 +2861,56 @@
memcpy(substr, rep_str, rep_str_size);
}
+static void
+repl_bytes(char *str, char c1, char c2)
+{
+ while (*str) {
+ if (*str == c1) {
+ *str = c2;
+ }
+ str++;
+ }
+}
+
+static void
+modify_packet(struct dp_packet *pkt, char *pkt_str, size_t size,
+ char *repl_str, size_t repl_size,
+ uint32_t orig_used_size)
+{
+ replace_substring(pkt_str, size,
+ (const char *) dp_packet_tail(pkt) - pkt_str,
+ repl_str, repl_size);
+ dp_packet_set_size(pkt, orig_used_size + (int) repl_size - (int) size);
+}
+
/* Replace IPV4 address in FTP message with NATed address. */
static int
repl_ftp_v4_addr(struct dp_packet *pkt, ovs_be32 v4_addr_rep,
char *ftp_data_start,
- size_t addr_offset_from_ftp_data_start)
+ size_t addr_offset_from_ftp_data_start,
+ size_t addr_size OVS_UNUSED)
{
enum { MAX_FTP_V4_NAT_DELTA = 8 };
/* Do conservative check for pathological MTU usage. */
uint32_t orig_used_size = dp_packet_size(pkt);
- uint16_t allocated_size = dp_packet_get_allocated(pkt);
- if (orig_used_size + MAX_FTP_V4_NAT_DELTA > allocated_size) {
+ if (orig_used_size + MAX_FTP_V4_NAT_DELTA >
+ dp_packet_get_allocated(pkt)) {
+
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5);
- VLOG_WARN_RL(&rl, "Unsupported effective MTU %u used with FTP",
- allocated_size);
+ VLOG_WARN_RL(&rl, "Unsupported effective MTU %u used with FTP V4",
+ dp_packet_get_allocated(pkt));
return 0;
}
- size_t remain_size = tcp_payload_length(pkt) -
- addr_offset_from_ftp_data_start;
- int overall_delta = 0;
- char *byte_str = ftp_data_start + addr_offset_from_ftp_data_start;
-
- /* Replace the existing IPv4 address by the new one. */
- for (uint8_t i = 0; i < 4; i++) {
- /* Find the end of the string for this octet. */
- char *next_delim = memchr(byte_str, ',', 4);
- ovs_assert(next_delim);
- int substr_size = next_delim - byte_str;
- remain_size -= substr_size;
-
- /* Compose the new string for this octet, and replace it. */
- char rep_str[4];
- uint8_t rep_byte = get_v4_byte_be(v4_addr_rep, i);
- int replace_size = sprintf(rep_str, "%d", rep_byte);
- replace_substring(byte_str, substr_size, remain_size,
- rep_str, replace_size);
- overall_delta += replace_size - substr_size;
-
- /* Advance past the octet and the following comma. */
- byte_str += replace_size + 1;
- }
-
- dp_packet_set_size(pkt, orig_used_size + overall_delta);
- return overall_delta;
+ char v4_addr_str[INET_ADDRSTRLEN] = {0};
+ ovs_assert(inet_ntop(AF_INET, &v4_addr_rep, v4_addr_str,
+ sizeof v4_addr_str));
+ repl_bytes(v4_addr_str, '.', ',');
+ modify_packet(pkt, ftp_data_start + addr_offset_from_ftp_data_start,
+ addr_size, v4_addr_str, strlen(v4_addr_str),
+ orig_used_size);
+ return (int) strlen(v4_addr_str) - (int) addr_size;
}
static char *
@@ -2886,7 +2979,8 @@
const struct conn *conn_for_expectation,
ovs_be32 *v4_addr_rep,
char **ftp_data_v4_start,
- size_t *addr_offset_from_ftp_data_start)
+ size_t *addr_offset_from_ftp_data_start,
+ size_t *addr_size)
{
struct tcp_header *th = dp_packet_l4(pkt);
size_t tcp_hdr_len = TCP_OFFSET(th->tcp_ctl) * 4;
@@ -2942,6 +3036,7 @@
return CT_FTP_CTL_INVALID;
}
+ *addr_size = ftp - ip_addr_start - 1;
char *save_ftp = ftp;
ftp = terminate_number_str(ftp, MAX_FTP_PORT_DGTS);
if (!ftp) {
@@ -3134,72 +3229,63 @@
/* Do conservative check for pathological MTU usage. */
uint32_t orig_used_size = dp_packet_size(pkt);
- uint16_t allocated_size = dp_packet_get_allocated(pkt);
- if (orig_used_size + MAX_FTP_V6_NAT_DELTA > allocated_size) {
+ if (orig_used_size + MAX_FTP_V6_NAT_DELTA >
+ dp_packet_get_allocated(pkt)) {
+
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5);
- VLOG_WARN_RL(&rl, "Unsupported effective MTU %u used with FTP",
- allocated_size);
+ VLOG_WARN_RL(&rl, "Unsupported effective MTU %u used with FTP V6",
+ dp_packet_get_allocated(pkt));
return 0;
}
- char v6_addr_str[IPV6_SCAN_LEN] = {0};
+ char v6_addr_str[INET6_ADDRSTRLEN] = {0};
ovs_assert(inet_ntop(AF_INET6, &v6_addr_rep.ipv6_aligned, v6_addr_str,
- IPV6_SCAN_LEN - 1));
-
- size_t replace_addr_size = strlen(v6_addr_str);
-
- size_t remain_size = tcp_payload_length(pkt) -
- addr_offset_from_ftp_data_start;
-
- char *pkt_addr_str = ftp_data_start + addr_offset_from_ftp_data_start;
- replace_substring(pkt_addr_str, addr_size, remain_size,
- v6_addr_str, replace_addr_size);
-
- int overall_delta = (int) replace_addr_size - (int) addr_size;
+ sizeof v6_addr_str));
+ modify_packet(pkt, ftp_data_start + addr_offset_from_ftp_data_start,
+ addr_size, v6_addr_str, strlen(v6_addr_str),
+ orig_used_size);
+ return (int) strlen(v6_addr_str) - (int) addr_size;
+}
- dp_packet_set_size(pkt, orig_used_size + overall_delta);
- return overall_delta;
+/* Increment/decrement a TCP sequence number. */
+static void
+adj_seqnum(ovs_16aligned_be32 *val, int32_t inc)
+{
+ put_16aligned_be32(val, htonl(ntohl(get_16aligned_be32(val)) + inc));
}
static void
handle_ftp_ctl(struct conntrack *ct, const struct conn_lookup_ctx *ctx,
- struct dp_packet *pkt,
- const struct conn *conn_for_expectation,
- long long now, enum ftp_ctl_pkt ftp_ctl, bool nat)
+ struct dp_packet *pkt, const struct conn *ec, long long now,
+ enum ftp_ctl_pkt ftp_ctl, bool nat)
{
struct ip_header *l3_hdr = dp_packet_l3(pkt);
ovs_be32 v4_addr_rep = 0;
struct ct_addr v6_addr_rep;
- size_t addr_offset_from_ftp_data_start;
+ size_t addr_offset_from_ftp_data_start = 0;
size_t addr_size = 0;
char *ftp_data_start;
- bool do_seq_skew_adj = true;
enum ct_alg_mode mode = CT_FTP_MODE_ACTIVE;
if (detect_ftp_ctl_type(ctx, pkt) != ftp_ctl) {
return;
}
- if (!nat || !conn_for_expectation->seq_skew) {
- do_seq_skew_adj = false;
- }
-
struct ovs_16aligned_ip6_hdr *nh6 = dp_packet_l3(pkt);
int64_t seq_skew = 0;
- if (ftp_ctl == CT_FTP_CTL_OTHER) {
- seq_skew = conn_for_expectation->seq_skew;
- } else if (ftp_ctl == CT_FTP_CTL_INTEREST) {
+ if (ftp_ctl == CT_FTP_CTL_INTEREST) {
enum ftp_ctl_pkt rc;
if (ctx->key.dl_type == htons(ETH_TYPE_IPV6)) {
- rc = process_ftp_ctl_v6(ct, pkt, conn_for_expectation,
+ rc = process_ftp_ctl_v6(ct, pkt, ec,
&v6_addr_rep, &ftp_data_start,
&addr_offset_from_ftp_data_start,
&addr_size, &mode);
} else {
- rc = process_ftp_ctl_v4(ct, pkt, conn_for_expectation,
+ rc = process_ftp_ctl_v4(ct, pkt, ec,
&v4_addr_rep, &ftp_data_start,
- &addr_offset_from_ftp_data_start);
+ &addr_offset_from_ftp_data_start,
+ &addr_size);
}
if (rc == CT_FTP_CTL_INVALID) {
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5);
@@ -3210,79 +3296,59 @@
uint16_t ip_len;
if (ctx->key.dl_type == htons(ETH_TYPE_IPV6)) {
- seq_skew = repl_ftp_v6_addr(pkt, v6_addr_rep, ftp_data_start,
- addr_offset_from_ftp_data_start,
- addr_size, mode);
+ if (nat) {
+ seq_skew = repl_ftp_v6_addr(pkt, v6_addr_rep,
+ ftp_data_start,
+ addr_offset_from_ftp_data_start,
+ addr_size, mode);
+ }
+
if (seq_skew) {
- ip_len = ntohs(nh6->ip6_ctlun.ip6_un1.ip6_un1_plen);
- ip_len += seq_skew;
+ ip_len = ntohs(nh6->ip6_ctlun.ip6_un1.ip6_un1_plen) +
+ seq_skew;
nh6->ip6_ctlun.ip6_un1.ip6_un1_plen = htons(ip_len);
- conn_seq_skew_set(ct, &conn_for_expectation->key, now,
- seq_skew, ctx->reply);
}
} else {
- seq_skew = repl_ftp_v4_addr(pkt, v4_addr_rep, ftp_data_start,
- addr_offset_from_ftp_data_start);
- ip_len = ntohs(l3_hdr->ip_tot_len);
+ if (nat) {
+ seq_skew = repl_ftp_v4_addr(pkt, v4_addr_rep,
+ ftp_data_start,
+ addr_offset_from_ftp_data_start,
+ addr_size);
+ }
if (seq_skew) {
- ip_len += seq_skew;
+ ip_len = ntohs(l3_hdr->ip_tot_len) + seq_skew;
l3_hdr->ip_csum = recalc_csum16(l3_hdr->ip_csum,
l3_hdr->ip_tot_len, htons(ip_len));
l3_hdr->ip_tot_len = htons(ip_len);
- conn_seq_skew_set(ct, &conn_for_expectation->key, now,
- seq_skew, ctx->reply);
}
}
} else {
OVS_NOT_REACHED();
}
- } else {
- OVS_NOT_REACHED();
}
struct tcp_header *th = dp_packet_l4(pkt);
- if (do_seq_skew_adj && seq_skew != 0) {
- if (ctx->reply != conn_for_expectation->seq_skew_dir) {
-
- uint32_t tcp_ack = ntohl(get_16aligned_be32(&th->tcp_ack));
-
- if ((seq_skew > 0) && (tcp_ack < seq_skew)) {
- /* Should not be possible; will be marked invalid. */
- tcp_ack = 0;
- } else if ((seq_skew < 0) && (UINT32_MAX - tcp_ack < -seq_skew)) {
- tcp_ack = (-seq_skew) - (UINT32_MAX - tcp_ack);
- } else {
- tcp_ack -= seq_skew;
- }
- ovs_be32 new_tcp_ack = htonl(tcp_ack);
- put_16aligned_be32(&th->tcp_ack, new_tcp_ack);
- } else {
- uint32_t tcp_seq = ntohl(get_16aligned_be32(&th->tcp_seq));
- if ((seq_skew > 0) && (UINT32_MAX - tcp_seq < seq_skew)) {
- tcp_seq = seq_skew - (UINT32_MAX - tcp_seq);
- } else if ((seq_skew < 0) && (tcp_seq < -seq_skew)) {
- /* Should not be possible; will be marked invalid. */
- tcp_seq = 0;
- } else {
- tcp_seq += seq_skew;
- }
- ovs_be32 new_tcp_seq = htonl(tcp_seq);
- put_16aligned_be32(&th->tcp_seq, new_tcp_seq);
- }
+ if (nat && ec->seq_skew != 0) {
+ ctx->reply != ec->seq_skew_dir ?
+ adj_seqnum(&th->tcp_ack, -ec->seq_skew) :
+ adj_seqnum(&th->tcp_seq, ec->seq_skew);
}
th->tcp_csum = 0;
- uint32_t tcp_csum;
if (ctx->key.dl_type == htons(ETH_TYPE_IPV6)) {
- tcp_csum = packet_csum_pseudoheader6(nh6);
+ th->tcp_csum = packet_csum_upperlayer6(nh6, th, ctx->key.nw_proto,
+ dp_packet_l4_size(pkt));
} else {
- tcp_csum = packet_csum_pseudoheader(l3_hdr);
+ uint32_t tcp_csum = packet_csum_pseudoheader(l3_hdr);
+ th->tcp_csum = csum_finish(
+ csum_continue(tcp_csum, th, dp_packet_l4_size(pkt)));
+ }
+
+ if (seq_skew) {
+ conn_seq_skew_set(ct, &ec->key, now, seq_skew + ec->seq_skew,
+ ctx->reply);
}
- const char *tail = dp_packet_tail(pkt);
- uint8_t pad = dp_packet_l2_pad_size(pkt);
- th->tcp_csum = csum_finish(
- csum_continue(tcp_csum, th, tail - (char *) th - pad));
}
static void
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/daemon.h openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/daemon.h
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/daemon.h 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/daemon.h 2020-03-11 16:15:44.000000000 +0000
@@ -121,6 +121,7 @@
#define DAEMON_OPTION_HANDLERS \
case OPT_DETACH: \
+ set_detach(); \
break; \
\
case OPT_NO_SELF_CONFINEMENT: \
@@ -139,6 +140,7 @@
break; \
\
case OPT_SERVICE: \
+ set_detach(); \
break; \
\
case OPT_SERVICE_MONITOR: \
@@ -159,6 +161,7 @@
void control_handler(DWORD request);
void set_pipe_handle(const char *pipe_handle);
+void set_detach(void);
#endif /* _WIN32 */
bool get_detach(void);
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/daemon-unix.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/daemon-unix.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/daemon-unix.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/daemon-unix.c 2020-03-11 16:15:44.000000000 +0000
@@ -428,7 +428,7 @@
/* Running in new daemon process. */
ovs_cmdl_proctitle_restore();
- set_subprogram_name("");
+ set_subprogram_name(program_name);
}
/* If daemonization is configured, then starts daemonization, by forking and
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/daemon-windows.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/daemon-windows.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/daemon-windows.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/daemon-windows.c 2020-03-11 16:15:44.000000000 +0000
@@ -82,6 +82,14 @@
"unexpected failure. \n");
}
+/* Sets up a following call to service_start() to detach from the foreground
+ * session, running this process in the background. */
+void
+set_detach(void)
+{
+ detach = true;
+}
+
/* Registers the call-back and configures the actions in case of a failure
* with the Windows services manager. */
void
@@ -357,7 +365,7 @@
/* We are only interested in the '--detach' and '--pipe-handle'. */
for (i = 0; i < argc; i ++) {
- if (!strcmp(argv[i], "--detach")) {
+ if (!detach && !strcmp(argv[i], "--detach")) {
detach = true;
} else if (!strncmp(argv[i], "--pipe-handle", 13)) {
/* If running as a child, return. */
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/dpctl.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/dpctl.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/dpctl.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/dpctl.c 2020-03-11 16:15:44.000000000 +0000
@@ -51,8 +51,6 @@
#include "util.h"
#include "openvswitch/ofp-flow.h"
#include "openvswitch/ofp-port.h"
-#include "openvswitch/vlog.h"
-VLOG_DEFINE_THIS_MODULE(dpctl);
typedef int dpctl_command_handler(int argc, const char *argv[],
struct dpctl_params *);
@@ -2304,8 +2302,6 @@
if (!set_names) {
dpctl_p.names = dpctl_p.verbosity > 0;
}
- VLOG_INFO("set_names=%d verbosity=%d names=%d", set_names,
- dpctl_p.verbosity, dpctl_p.names);
if (!error) {
dpctl_command_handler *handler = (dpctl_command_handler *) aux;
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/dpctl.man openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/dpctl.man
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/dpctl.man 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/dpctl.man 2020-03-11 16:15:44.000000000 +0000
@@ -231,6 +231,8 @@
.IP
If \fIct-tuple\fR is provided, flushes the connection entry specified by
\fIct-tuple\fR in \fIzone\fR. The zone defaults to 0 if it is not provided.
+The userspace connection tracker requires flushing with the original pre-NATed
+tuple and a warning log will be otherwise generated.
An example of an IPv4 ICMP \fIct-tuple\fR:
.IP
"ct_nw_src=10.1.1.1,ct_nw_dst=10.1.1.2,ct_nw_proto=1,icmp_type=8,icmp_code=0,icmp_id=10"
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/dpdk.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/dpdk.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/dpdk.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/dpdk.c 2020-03-11 16:15:44.000000000 +0000
@@ -474,7 +474,23 @@
return false;
}
- rte_memzone_dump(stdout);
+ if (VLOG_IS_DBG_ENABLED()) {
+ size_t size;
+ char *response = NULL;
+ FILE *stream = open_memstream(&response, &size);
+
+ if (stream) {
+ rte_memzone_dump(stream);
+ fclose(stream);
+ if (size) {
+ VLOG_DBG("rte_memzone_dump:\n%s", response);
+ }
+ free(response);
+ } else {
+ VLOG_DBG("Could not dump memzone. Unable to open memstream: %s.",
+ ovs_strerror(errno));
+ }
+ }
/* We are called from the main thread here */
RTE_PER_LCORE(_lcore_id) = NON_PMD_CORE_ID;
@@ -512,8 +528,8 @@
const char *dpdk_init_val = smap_get_def(ovs_other_config, "dpdk-init",
"false");
- bool try_only = !strcmp(dpdk_init_val, "try");
- if (!strcmp(dpdk_init_val, "true") || try_only) {
+ bool try_only = !strcasecmp(dpdk_init_val, "try");
+ if (!strcasecmp(dpdk_init_val, "true") || try_only) {
static struct ovsthread_once once_enable = OVSTHREAD_ONCE_INITIALIZER;
if (ovsthread_once_start(&once_enable)) {
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/dpif.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/dpif.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/dpif.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/dpif.c 2020-03-11 16:15:44.000000000 +0000
@@ -591,13 +591,8 @@
netdev_ports_insert(netdev, dpif->dpif_class, &dpif_port);
}
} else {
- if (error != EEXIST) {
- VLOG_WARN_RL(&error_rl, "%s: failed to add %s as port: %s",
- dpif_name(dpif), netdev_name, ovs_strerror(error));
- } else {
- /* It's fairly common for upper layers to try to add a duplicate
- * port, and they know how to handle it properly. */
- }
+ VLOG_WARN_RL(&error_rl, "%s: failed to add %s as port: %s",
+ dpif_name(dpif), netdev_name, ovs_strerror(error));
port_no = ODPP_NONE;
}
if (port_nop) {
@@ -737,16 +732,7 @@
/* Returns the Netlink PID value to supply in OVS_ACTION_ATTR_USERSPACE
* actions as the OVS_USERSPACE_ATTR_PID attribute's value, for use in
- * flows whose packets arrived on port 'port_no'. In the case where the
- * provider allocates multiple Netlink PIDs to a single port, it may use
- * 'hash' to spread load among them. The caller need not use a particular
- * hash function; a 5-tuple hash is suitable.
- *
- * (The datapath implementation might use some different hash function for
- * distributing packets received via flow misses among PIDs. This means
- * that packets received via flow misses might be reordered relative to
- * packets received via userspace actions. This is not ordinarily a
- * problem.)
+ * flows whose packets arrived on port 'port_no'.
*
* A 'port_no' of ODPP_NONE is a special case: it returns a reserved PID, not
* allocated to any port, that the client may use for special purposes.
@@ -757,10 +743,10 @@
* update all of the flows that it installed that contain
* OVS_ACTION_ATTR_USERSPACE actions. */
uint32_t
-dpif_port_get_pid(const struct dpif *dpif, odp_port_t port_no, uint32_t hash)
+dpif_port_get_pid(const struct dpif *dpif, odp_port_t port_no)
{
return (dpif->dpif_class->port_get_pid
- ? (dpif->dpif_class->port_get_pid)(dpif, port_no, hash)
+ ? (dpif->dpif_class->port_get_pid)(dpif, port_no)
: 0);
}
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/dpif.h openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/dpif.h
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/dpif.h 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/dpif.h 2020-03-11 16:15:44.000000000 +0000
@@ -274,18 +274,6 @@
*
* - Upcalls that specify the "special" Netlink PID are queued separately.
*
- * Multiple threads may want to read upcalls simultaneously from a single
- * datapath. To support multiple threads well, one extends the above preferred
- * behavior:
- *
- * - Each port has multiple PIDs. The datapath distributes "miss" upcalls
- * across the PIDs, ensuring that a given flow is mapped in a stable way
- * to a single PID.
- *
- * - For "action" upcalls, the thread can specify its own Netlink PID or
- * other threads' Netlink PID of the same port for offloading purpose
- * (e.g. in a "round robin" manner).
- *
*
* Packet Format
* =============
@@ -470,8 +458,7 @@
struct dpif_port *);
int dpif_port_get_name(struct dpif *, odp_port_t port_no,
char *name, size_t name_size);
-uint32_t dpif_port_get_pid(const struct dpif *, odp_port_t port_no,
- uint32_t hash);
+uint32_t dpif_port_get_pid(const struct dpif *, odp_port_t port_no);
struct dpif_port_dump {
const struct dpif *dpif;
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/dpif-netdev.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/dpif-netdev.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/dpif-netdev.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/dpif-netdev.c 2020-03-11 16:15:44.000000000 +0000
@@ -1077,6 +1077,7 @@
static void
sorted_poll_list(struct dp_netdev_pmd_thread *pmd, struct rxq_poll **list,
size_t *n)
+ OVS_REQUIRES(pmd->port_mutex)
{
struct rxq_poll *ret, *poll;
size_t i;
@@ -2126,7 +2127,7 @@
if (ovs_u128_equals(*mega_ufid, data->mega_ufid)) {
cmap_remove(&flow_mark.megaflow_to_mark,
CONST_CAST(struct cmap_node *, &data->node), hash);
- free(data);
+ ovsrcu_postpone(free, data);
return;
}
}
@@ -2345,9 +2346,9 @@
ovs_mutex_lock(&pmd->dp->port_mutex);
port = dp_netdev_lookup_port(pmd->dp, in_port);
- if (!port) {
+ if (!port || netdev_vport_is_vport_class(port->netdev->netdev_class)) {
ovs_mutex_unlock(&pmd->dp->port_mutex);
- return -1;
+ goto err_free;
}
ret = netdev_flow_put(port->netdev, &offload->match,
CONST_CAST(struct nlattr *, offload->actions),
@@ -2356,20 +2357,22 @@
ovs_mutex_unlock(&pmd->dp->port_mutex);
if (ret) {
- if (!modification) {
- flow_mark_free(mark);
- } else {
- mark_to_flow_disassociate(pmd, flow);
- }
- return -1;
+ goto err_free;
}
if (!modification) {
megaflow_to_mark_associate(&flow->mega_ufid, mark);
mark_to_flow_associate(mark, flow);
}
-
return 0;
+
+err_free:
+ if (!modification) {
+ flow_mark_free(mark);
+ } else {
+ mark_to_flow_disassociate(pmd, flow);
+ }
+ return -1;
}
static void *
@@ -2386,6 +2389,7 @@
ovsrcu_quiesce_start();
ovs_mutex_cond_wait(&dp_flow_offload.cond,
&dp_flow_offload.mutex);
+ ovsrcu_quiesce_end();
}
list = ovs_list_pop_front(&dp_flow_offload.list);
offload = CONTAINER_OF(list, struct dp_flow_offload_item, node);
@@ -3361,6 +3365,16 @@
dpif_flow_hash(dpif, &match.flow, sizeof match.flow, &ufid);
}
+ /* The Netlink encoding of datapath flow keys cannot express
+ * wildcarding the presence of a VLAN tag. Instead, a missing VLAN
+ * tag is interpreted as exact match on the fact that there is no
+ * VLAN. Unless we refactor a lot of code that translates between
+ * Netlink and struct flow representations, we have to do the same
+ * here. This must be in sync with 'match' in handle_packet_upcall(). */
+ if (!match.wc.masks.vlans[0].tci) {
+ match.wc.masks.vlans[0].tci = htons(0xffff);
+ }
+
/* Must produce a netdev_flow_key for lookup.
* Use the same method as employed to create the key when adding
* the flow to the dplcs to make sure they match. */
@@ -5050,7 +5064,15 @@
memset(exceeded_rate, 0, cnt * sizeof *exceeded_rate);
/* All packets will hit the meter at the same time. */
- long_delta_t = (now - meter->used) / 1000; /* msec */
+ long_delta_t = now / 1000 - meter->used / 1000; /* msec */
+
+ if (long_delta_t < 0) {
+ /* This condition means that we have several threads fighting for a
+ meter lock, and the one who received the packets a bit later wins.
+ Assuming that all racing threads received packets at the same time
+ to avoid overflow. */
+ long_delta_t = 0;
+ }
/* Make sure delta_t will not be too large, so that bucket will not
* wrap around below. */
@@ -5238,20 +5260,22 @@
struct ofputil_meter_stats *stats, uint16_t n_bands)
{
const struct dp_netdev *dp = get_dp_netdev(dpif);
- const struct dp_meter *meter;
uint32_t meter_id = meter_id_.uint32;
+ int retval = 0;
if (meter_id >= MAX_METERS) {
return EFBIG;
}
- meter = dp->meters[meter_id];
+
+ meter_lock(dp, meter_id);
+ const struct dp_meter *meter = dp->meters[meter_id];
if (!meter) {
- return ENOENT;
+ retval = ENOENT;
+ goto done;
}
if (stats) {
int i = 0;
- meter_lock(dp, meter_id);
stats->packet_in_count = meter->packet_count;
stats->byte_in_count = meter->byte_count;
@@ -5259,11 +5283,13 @@
stats->bands[i].packet_count = meter->bands[i].packet_count;
stats->bands[i].byte_count = meter->bands[i].byte_count;
}
- meter_unlock(dp, meter_id);
stats->n_bands = i;
}
- return 0;
+
+done:
+ meter_unlock(dp, meter_id);
+ return retval;
}
static int
@@ -5698,7 +5724,6 @@
recirc_depth = *recirc_depth_get_unsafe();
if (OVS_UNLIKELY(recirc_depth)) {
hash = hash_finish(hash, recirc_depth);
- dp_packet_set_rss_hash(packet, hash);
}
return hash;
}
@@ -5898,20 +5923,13 @@
miniflow_extract(packet, &key->mf);
key->len = 0; /* Not computed yet. */
- /* If EMC and SMC disabled skip hash computation */
- if (smc_enable_db == true || cur_min != 0) {
- if (!md_is_valid) {
- key->hash = dpif_netdev_packet_get_rss_hash_orig_pkt(packet,
- &key->mf);
- } else {
- key->hash = dpif_netdev_packet_get_rss_hash(packet, &key->mf);
- }
- }
- if (cur_min) {
- flow = emc_lookup(&cache->emc_cache, key);
- } else {
- flow = NULL;
- }
+ key->hash =
+ (md_is_valid == false)
+ ? dpif_netdev_packet_get_rss_hash_orig_pkt(packet, &key->mf)
+ : dpif_netdev_packet_get_rss_hash(packet, &key->mf);
+
+ /* If EMC is disabled skip emc_lookup */
+ flow = (cur_min != 0) ? emc_lookup(&cache->emc_cache, key) : NULL;
if (OVS_LIKELY(flow)) {
tcp_flags = miniflow_get_tcp_flags(&key->mf);
dp_netdev_queue_batches(packet, flow, tcp_flags, batches,
@@ -5977,7 +5995,7 @@
* tag is interpreted as exact match on the fact that there is no
* VLAN. Unless we refactor a lot of code that translates between
* Netlink and struct flow representations, we have to do the same
- * here. */
+ * here. This must be in sync with 'match' in dpif_netdev_flow_put(). */
if (!match.wc.masks.vlans[0].tci) {
match.wc.masks.vlans[0].tci = htons(0xffff);
}
@@ -5997,8 +6015,7 @@
* could have already been installed since we last did the flow
* lookup before upcall. This could be solved by moving the
* mutex lock outside the loop, but that's an awful long time
- * to be locking everyone out of making flow installs. If we
- * move to a per-core classifier, it would be reasonable. */
+ * to be locking revalidators out of making flow modifications. */
ovs_mutex_lock(&pmd->flow_mutex);
netdev_flow = dp_netdev_pmd_lookup_flow(pmd, key, NULL);
if (OVS_LIKELY(!netdev_flow)) {
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/dpif-netdev-perf.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/dpif-netdev-perf.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/dpif-netdev-perf.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/dpif-netdev-perf.c 2020-03-11 16:15:44.000000000 +0000
@@ -206,6 +206,7 @@
" Rx packets: %12"PRIu64" (%.0f Kpps, %.0f cycles/pkt)\n"
" Datapath passes: %12"PRIu64" (%.2f passes/pkt)\n"
" - EMC hits: %12"PRIu64" (%4.1f %%)\n"
+ " - SMC hits: %12"PRIu64" (%4.1f %%)\n"
" - Megaflow hits: %12"PRIu64" (%4.1f %%, %.2f subtbl lookups/"
"hit)\n"
" - Upcalls: %12"PRIu64" (%4.1f %%, %.1f us/upcall)\n"
@@ -215,6 +216,8 @@
passes, rx_packets ? 1.0 * passes / rx_packets : 0,
stats[PMD_STAT_EXACT_HIT],
100.0 * stats[PMD_STAT_EXACT_HIT] / passes,
+ stats[PMD_STAT_SMC_HIT],
+ 100.0 * stats[PMD_STAT_SMC_HIT] / passes,
stats[PMD_STAT_MASKED_HIT],
100.0 * stats[PMD_STAT_MASKED_HIT] / passes,
stats[PMD_STAT_MASKED_HIT]
@@ -495,15 +498,7 @@
cycles_per_pkt = cycles / rx_packets;
histogram_add_sample(&s->cycles_per_pkt, cycles_per_pkt);
}
- if (s->current.batches > 0) {
- histogram_add_sample(&s->pkts_per_batch,
- rx_packets / s->current.batches);
- }
histogram_add_sample(&s->upcalls, s->current.upcalls);
- if (s->current.upcalls > 0) {
- histogram_add_sample(&s->cycles_per_upcall,
- s->current.upcall_cycles / s->current.upcalls);
- }
histogram_add_sample(&s->max_vhost_qfill, s->current.max_vhost_qfill);
/* Add iteration samples to millisecond stats. */
@@ -559,8 +554,8 @@
cum_ms = history_next(&s->milliseconds);
cum_ms->timestamp = now;
}
- /* Do the next check after 10K cycles (4 us at 2.5 GHz TSC clock). */
- s->next_check_tsc = cycles_counter_update(s) + 10000;
+ /* Do the next check after 4 us (10K cycles at 2.5 GHz TSC clock). */
+ s->next_check_tsc = cycles_counter_update(s) + get_tsc_hz() / 250000;
}
}
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/dpif-netdev-perf.h openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/dpif-netdev-perf.h
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/dpif-netdev-perf.h 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/dpif-netdev-perf.h 2020-03-11 16:15:44.000000000 +0000
@@ -56,7 +56,7 @@
enum pmd_stat_type {
PMD_STAT_EXACT_HIT, /* Packets that had an exact match (emc). */
- PMD_STAT_SMC_HIT, /* Packets that had a sig match hit (SMC). */
+ PMD_STAT_SMC_HIT, /* Packets that had a sig match hit (SMC). */
PMD_STAT_MASKED_HIT, /* Packets that matched in the flow table. */
PMD_STAT_MISS, /* Packets that did not match and upcall was ok. */
PMD_STAT_LOST, /* Packets that did not match and upcall failed. */
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/dpif-netdev-unixctl.man openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/dpif-netdev-unixctl.man
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/dpif-netdev-unixctl.man 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/dpif-netdev-unixctl.man 2020-03-11 16:15:44.000000000 +0000
@@ -11,7 +11,7 @@
\fIdp\fR. The special thread "main" sums up the statistics of every non pmd
thread.
-The sum of "emc hits", "masked hits" and "miss" is the number of
+The sum of "emc hits", "smc hits", "megaflow hits" and "miss" is the number of
packet lookups performed by the datapath. Beware that a recirculated packet
experiences one additional lookup per recirculation, so there may be
more lookups than forwarded packets in the datapath.
@@ -135,6 +135,7 @@
Rx packets: 2399607 (2381 Kpps, 848 cycles/pkt)
Datapath passes: 3599415 (1.50 passes/pkt)
- EMC hits: 336472 ( 9.3 %)
+ - SMC hits: 0 ( 0.0 %)
- Megaflow hits: 3262943 (90.7 %, 1.00 subtbl lookups/hit)
- Upcalls: 0 ( 0.0 %, 0.0 us/upcall)
- Lost upcalls: 0 ( 0.0 %)
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/dpif-netlink.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/dpif-netlink.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/dpif-netlink.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/dpif-netlink.c 2020-03-11 16:15:44.000000000 +0000
@@ -78,6 +78,10 @@
#define FLOW_DUMP_MAX_BATCH 50
#define OPERATE_MAX_OPS 50
+#ifndef EPOLLEXCLUSIVE
+#define EPOLLEXCLUSIVE (1u << 28)
+#endif
+
struct dpif_netlink_dp {
/* Generic Netlink header. */
uint8_t cmd;
@@ -170,7 +174,6 @@
#endif
struct dpif_handler {
- struct dpif_channel *channels;/* Array of channels for each handler. */
struct epoll_event *epoll_events;
int epoll_fd; /* epoll fd that includes channel socks. */
int n_events; /* Num events returned by epoll_wait(). */
@@ -193,6 +196,7 @@
struct fat_rwlock upcall_lock;
struct dpif_handler *handlers;
uint32_t n_handlers; /* Num of upcall handlers. */
+ struct dpif_channel *channels; /* Array of channels for each port. */
int uc_array_size; /* Size of 'handler->channels' and */
/* 'handler->epoll_events'. */
@@ -230,7 +234,7 @@
static int dpif_netlink_init(void);
static int open_dpif(const struct dpif_netlink_dp *, struct dpif **);
static uint32_t dpif_netlink_port_get_pid(const struct dpif *,
- odp_port_t port_no, uint32_t hash);
+ odp_port_t port_no);
static void dpif_netlink_handler_uninit(struct dpif_handler *handler);
static int dpif_netlink_refresh_channels(struct dpif_netlink *,
uint32_t n_handlers);
@@ -242,6 +246,42 @@
odp_port_t port_no, const char *port_name,
struct dpif_port *dpif_port);
+static int
+create_nl_sock(struct dpif_netlink *dpif OVS_UNUSED, struct nl_sock **socksp)
+ OVS_REQ_WRLOCK(dpif->upcall_lock)
+{
+#ifndef _WIN32
+ return nl_sock_create(NETLINK_GENERIC, socksp);
+#else
+ /* Pick netlink sockets to use in a round-robin fashion from each
+ * handler's pool of sockets. */
+ struct dpif_handler *handler = &dpif->handlers[0];
+ struct dpif_windows_vport_sock *sock_pool = handler->vport_sock_pool;
+ size_t index = handler->last_used_pool_idx;
+
+ /* A pool of sockets is allocated when the handler is initialized. */
+ if (sock_pool == NULL) {
+ *socksp = NULL;
+ return EINVAL;
+ }
+
+ ovs_assert(index < VPORT_SOCK_POOL_SIZE);
+ *socksp = sock_pool[index].nl_sock;
+ ovs_assert(*socksp);
+ index = (index == VPORT_SOCK_POOL_SIZE - 1) ? 0 : index + 1;
+ handler->last_used_pool_idx = index;
+ return 0;
+#endif
+}
+
+static void
+close_nl_sock(struct nl_sock *socksp)
+{
+#ifndef _WIN32
+ nl_sock_destroy(socksp);
+#endif
+}
+
static struct dpif_netlink *
dpif_netlink_cast(const struct dpif *dpif)
{
@@ -331,43 +371,6 @@
return 0;
}
-/* Destroys the netlink sockets pointed by the elements in 'socksp'
- * and frees the 'socksp'. */
-static void
-vport_del_socksp__(struct nl_sock **socksp, uint32_t n_socks)
-{
- size_t i;
-
- for (i = 0; i < n_socks; i++) {
- nl_sock_destroy(socksp[i]);
- }
-
- free(socksp);
-}
-
-/* Creates an array of netlink sockets. Returns an array of the
- * corresponding pointers. Records the error in 'error'. */
-static struct nl_sock **
-vport_create_socksp__(uint32_t n_socks, int *error)
-{
- struct nl_sock **socksp = xzalloc(n_socks * sizeof *socksp);
- size_t i;
-
- for (i = 0; i < n_socks; i++) {
- *error = nl_sock_create(NETLINK_GENERIC, &socksp[i]);
- if (*error) {
- goto error;
- }
- }
-
- return socksp;
-
-error:
- vport_del_socksp__(socksp, n_socks);
-
- return NULL;
-}
-
#ifdef _WIN32
static void
vport_delete_sock_pool(struct dpif_handler *handler)
@@ -422,138 +425,44 @@
vport_delete_sock_pool(handler);
return error;
}
-
-/* Returns an array pointers to netlink sockets. The sockets are picked from a
- * pool. Records the error in 'error'. */
-static struct nl_sock **
-vport_create_socksp_windows(struct dpif_netlink *dpif, int *error)
- OVS_REQ_WRLOCK(dpif->upcall_lock)
-{
- uint32_t n_socks = dpif->n_handlers;
- struct nl_sock **socksp;
- size_t i;
-
- ovs_assert(n_socks <= 1);
- socksp = xzalloc(n_socks * sizeof *socksp);
-
- /* Pick netlink sockets to use in a round-robin fashion from each
- * handler's pool of sockets. */
- for (i = 0; i < n_socks; i++) {
- struct dpif_handler *handler = &dpif->handlers[i];
- struct dpif_windows_vport_sock *sock_pool = handler->vport_sock_pool;
- size_t index = handler->last_used_pool_idx;
-
- /* A pool of sockets is allocated when the handler is initialized. */
- if (sock_pool == NULL) {
- free(socksp);
- *error = EINVAL;
- return NULL;
- }
-
- ovs_assert(index < VPORT_SOCK_POOL_SIZE);
- socksp[i] = sock_pool[index].nl_sock;
- socksp[i] = sock_pool[index].nl_sock;
- ovs_assert(socksp[i]);
- index = (index == VPORT_SOCK_POOL_SIZE - 1) ? 0 : index + 1;
- handler->last_used_pool_idx = index;
- }
-
- return socksp;
-}
-
-static void
-vport_del_socksp_windows(struct dpif_netlink *dpif, struct nl_sock **socksp)
-{
- free(socksp);
-}
#endif /* _WIN32 */
-static struct nl_sock **
-vport_create_socksp(struct dpif_netlink *dpif, int *error)
-{
-#ifdef _WIN32
- return vport_create_socksp_windows(dpif, error);
-#else
- return vport_create_socksp__(dpif->n_handlers, error);
-#endif
-}
-
-static void
-vport_del_socksp(struct dpif_netlink *dpif, struct nl_sock **socksp)
-{
-#ifdef _WIN32
- vport_del_socksp_windows(dpif, socksp);
-#else
- vport_del_socksp__(socksp, dpif->n_handlers);
-#endif
-}
-
-/* Given the array of pointers to netlink sockets 'socksp', returns
- * the array of corresponding pids. If the 'socksp' is NULL, returns
- * a single-element array of value 0. */
-static uint32_t *
-vport_socksp_to_pids(struct nl_sock **socksp, uint32_t n_socks)
-{
- uint32_t *pids;
-
- if (!socksp) {
- pids = xzalloc(sizeof *pids);
- } else {
- size_t i;
-
- pids = xzalloc(n_socks * sizeof *pids);
- for (i = 0; i < n_socks; i++) {
- pids[i] = nl_sock_pid(socksp[i]);
- }
- }
-
- return pids;
-}
-
-/* Given the port number 'port_idx', extracts the pids of netlink sockets
- * associated to the port and assigns it to 'upcall_pids'. */
+/* Given the port number 'port_idx', extracts the pid of netlink socket
+ * associated to the port and assigns it to 'upcall_pid'. */
static bool
-vport_get_pids(struct dpif_netlink *dpif, uint32_t port_idx,
- uint32_t **upcall_pids)
+vport_get_pid(struct dpif_netlink *dpif, uint32_t port_idx,
+ uint32_t *upcall_pid)
{
- uint32_t *pids;
- size_t i;
-
/* Since the nl_sock can only be assigned in either all
- * or none "dpif->handlers" channels, the following check
+ * or none "dpif" channels, the following check
* would suffice. */
- if (!dpif->handlers[0].channels[port_idx].sock) {
+ if (!dpif->channels[port_idx].sock) {
return false;
}
ovs_assert(!WINDOWS || dpif->n_handlers <= 1);
- pids = xzalloc(dpif->n_handlers * sizeof *pids);
-
- for (i = 0; i < dpif->n_handlers; i++) {
- pids[i] = nl_sock_pid(dpif->handlers[i].channels[port_idx].sock);
- }
-
- *upcall_pids = pids;
+ *upcall_pid = nl_sock_pid(dpif->channels[port_idx].sock);
return true;
}
static int
-vport_add_channels(struct dpif_netlink *dpif, odp_port_t port_no,
- struct nl_sock **socksp)
+vport_add_channel(struct dpif_netlink *dpif, odp_port_t port_no,
+ struct nl_sock *socksp)
{
struct epoll_event event;
uint32_t port_idx = odp_to_u32(port_no);
- size_t i, j;
+ size_t i;
int error;
if (dpif->handlers == NULL) {
+ close_nl_sock(socksp);
return 0;
}
/* We assume that the datapath densely chooses port numbers, which can
* therefore be used as an index into 'channels' and 'epoll_events' of
- * 'dpif->handler'. */
+ * 'dpif'. */
if (port_idx >= dpif->uc_array_size) {
uint32_t new_size = port_idx + 1;
@@ -563,15 +472,15 @@
return EFBIG;
}
- for (i = 0; i < dpif->n_handlers; i++) {
- struct dpif_handler *handler = &dpif->handlers[i];
+ dpif->channels = xrealloc(dpif->channels,
+ new_size * sizeof *dpif->channels);
- handler->channels = xrealloc(handler->channels,
- new_size * sizeof *handler->channels);
+ for (i = dpif->uc_array_size; i < new_size; i++) {
+ dpif->channels[i].sock = NULL;
+ }
- for (j = dpif->uc_array_size; j < new_size; j++) {
- handler->channels[j].sock = NULL;
- }
+ for (i = 0; i < dpif->n_handlers; i++) {
+ struct dpif_handler *handler = &dpif->handlers[i];
handler->epoll_events = xrealloc(handler->epoll_events,
new_size * sizeof *handler->epoll_events);
@@ -581,33 +490,33 @@
}
memset(&event, 0, sizeof event);
- event.events = EPOLLIN;
+ event.events = EPOLLIN | EPOLLEXCLUSIVE;
event.data.u32 = port_idx;
for (i = 0; i < dpif->n_handlers; i++) {
struct dpif_handler *handler = &dpif->handlers[i];
#ifndef _WIN32
- if (epoll_ctl(handler->epoll_fd, EPOLL_CTL_ADD, nl_sock_fd(socksp[i]),
+ if (epoll_ctl(handler->epoll_fd, EPOLL_CTL_ADD, nl_sock_fd(socksp),
&event) < 0) {
error = errno;
goto error;
}
#endif
- dpif->handlers[i].channels[port_idx].sock = socksp[i];
- dpif->handlers[i].channels[port_idx].last_poll = LLONG_MIN;
}
+ dpif->channels[port_idx].sock = socksp;
+ dpif->channels[port_idx].last_poll = LLONG_MIN;
return 0;
error:
- for (j = 0; j < i; j++) {
#ifndef _WIN32
- epoll_ctl(dpif->handlers[j].epoll_fd, EPOLL_CTL_DEL,
- nl_sock_fd(socksp[j]), NULL);
-#endif
- dpif->handlers[j].channels[port_idx].sock = NULL;
+ while (i--) {
+ epoll_ctl(dpif->handlers[i].epoll_fd, EPOLL_CTL_DEL,
+ nl_sock_fd(socksp), NULL);
}
+#endif
+ dpif->channels[port_idx].sock = NULL;
return error;
}
@@ -618,14 +527,8 @@
uint32_t port_idx = odp_to_u32(port_no);
size_t i;
- if (!dpif->handlers || port_idx >= dpif->uc_array_size) {
- return;
- }
-
- /* Since the sock can only be assigned in either all or none
- * of "dpif->handlers" channels, the following check would
- * suffice. */
- if (!dpif->handlers[0].channels[port_idx].sock) {
+ if (!dpif->handlers || port_idx >= dpif->uc_array_size
+ || !dpif->channels[port_idx].sock) {
return;
}
@@ -633,12 +536,14 @@
struct dpif_handler *handler = &dpif->handlers[i];
#ifndef _WIN32
epoll_ctl(handler->epoll_fd, EPOLL_CTL_DEL,
- nl_sock_fd(handler->channels[port_idx].sock), NULL);
- nl_sock_destroy(handler->channels[port_idx].sock);
+ nl_sock_fd(dpif->channels[port_idx].sock), NULL);
#endif
- handler->channels[port_idx].sock = NULL;
handler->event_offset = handler->n_events = 0;
}
+#ifndef _WIN32
+ nl_sock_destroy(dpif->channels[port_idx].sock);
+#endif
+ dpif->channels[port_idx].sock = NULL;
}
static void
@@ -655,10 +560,7 @@
struct dpif_netlink_vport vport_request;
uint32_t upcall_pids = 0;
- /* Since the sock can only be assigned in either all or none
- * of "dpif->handlers" channels, the following check would
- * suffice. */
- if (!dpif->handlers[0].channels[i].sock) {
+ if (!dpif->channels[i].sock) {
continue;
}
@@ -679,11 +581,11 @@
dpif_netlink_handler_uninit(handler);
free(handler->epoll_events);
- free(handler->channels);
}
-
+ free(dpif->channels);
free(dpif->handlers);
dpif->handlers = NULL;
+ dpif->channels = NULL;
dpif->n_handlers = 0;
dpif->uc_array_size = 0;
}
@@ -846,13 +748,13 @@
{
struct dpif_netlink_vport request, reply;
struct ofpbuf *buf;
- struct nl_sock **socksp = NULL;
- uint32_t *upcall_pids;
+ struct nl_sock *socksp = NULL;
+ uint32_t upcall_pids = 0;
int error = 0;
if (dpif->handlers) {
- socksp = vport_create_socksp(dpif, &error);
- if (!socksp) {
+ error = create_nl_sock(dpif, &socksp);
+ if (error) {
return error;
}
}
@@ -864,9 +766,11 @@
request.name = name;
request.port_no = *port_nop;
- upcall_pids = vport_socksp_to_pids(socksp, dpif->n_handlers);
- request.n_upcall_pids = socksp ? dpif->n_handlers : 1;
- request.upcall_pids = upcall_pids;
+ if (socksp) {
+ upcall_pids = nl_sock_pid(socksp);
+ }
+ request.n_upcall_pids = 1;
+ request.upcall_pids = &upcall_pids;
if (options) {
request.options = options->data;
@@ -882,31 +786,27 @@
dpif_name(&dpif->dpif), *port_nop);
}
- vport_del_socksp(dpif, socksp);
+ close_nl_sock(socksp);
goto exit;
}
- if (socksp) {
- error = vport_add_channels(dpif, *port_nop, socksp);
- if (error) {
- VLOG_INFO("%s: could not add channel for port %s",
- dpif_name(&dpif->dpif), name);
+ error = vport_add_channel(dpif, *port_nop, socksp);
+ if (error) {
+ VLOG_INFO("%s: could not add channel for port %s",
+ dpif_name(&dpif->dpif), name);
- /* Delete the port. */
- dpif_netlink_vport_init(&request);
- request.cmd = OVS_VPORT_CMD_DEL;
- request.dp_ifindex = dpif->dp_ifindex;
- request.port_no = *port_nop;
- dpif_netlink_vport_transact(&request, NULL, NULL);
- vport_del_socksp(dpif, socksp);
- goto exit;
- }
+ /* Delete the port. */
+ dpif_netlink_vport_init(&request);
+ request.cmd = OVS_VPORT_CMD_DEL;
+ request.dp_ifindex = dpif->dp_ifindex;
+ request.port_no = *port_nop;
+ dpif_netlink_vport_transact(&request, NULL, NULL);
+ close_nl_sock(socksp);
+ goto exit;
}
- free(socksp);
exit:
ofpbuf_delete(buf);
- free(upcall_pids);
return error;
}
@@ -1131,7 +1031,7 @@
static uint32_t
dpif_netlink_port_get_pid__(const struct dpif_netlink *dpif,
- odp_port_t port_no, uint32_t hash)
+ odp_port_t port_no)
OVS_REQ_RDLOCK(dpif->upcall_lock)
{
uint32_t port_idx = odp_to_u32(port_no);
@@ -1141,14 +1041,13 @@
/* The ODPP_NONE "reserved" port number uses the "ovs-system"'s
* channel, since it is not heavily loaded. */
uint32_t idx = port_idx >= dpif->uc_array_size ? 0 : port_idx;
- struct dpif_handler *h = &dpif->handlers[hash % dpif->n_handlers];
/* Needs to check in case the socket pointer is changed in between
* the holding of upcall_lock. A known case happens when the main
* thread deletes the vport while the handler thread is handling
* the upcall from that port. */
- if (h->channels[idx].sock) {
- pid = nl_sock_pid(h->channels[idx].sock);
+ if (dpif->channels[idx].sock) {
+ pid = nl_sock_pid(dpif->channels[idx].sock);
}
}
@@ -1156,14 +1055,13 @@
}
static uint32_t
-dpif_netlink_port_get_pid(const struct dpif *dpif_, odp_port_t port_no,
- uint32_t hash)
+dpif_netlink_port_get_pid(const struct dpif *dpif_, odp_port_t port_no)
{
const struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
uint32_t ret;
fat_rwlock_rdlock(&dpif->upcall_lock);
- ret = dpif_netlink_port_get_pid__(dpif, port_no, hash);
+ ret = dpif_netlink_port_get_pid__(dpif, port_no);
fat_rwlock_unlock(&dpif->upcall_lock);
return ret;
@@ -2119,11 +2017,6 @@
return err;
}
- /* When we try to install a dummy flow from a probed feature. */
- if (match.flow.dl_type == htons(0x1234)) {
- return EOPNOTSUPP;
- }
-
in_port = match.flow.in_port.odp_port;
dev = netdev_ports_get(in_port, dpif_class);
if (!dev) {
@@ -2382,42 +2275,41 @@
dpif_netlink_port_dump_start__(dpif, &dump);
while (!dpif_netlink_port_dump_next__(dpif, &dump, &vport, &buf)) {
uint32_t port_no = odp_to_u32(vport.port_no);
- uint32_t *upcall_pids = NULL;
+ uint32_t upcall_pid;
int error;
if (port_no >= dpif->uc_array_size
- || !vport_get_pids(dpif, port_no, &upcall_pids)) {
- struct nl_sock **socksp = vport_create_socksp(dpif, &error);
+ || !vport_get_pid(dpif, port_no, &upcall_pid)) {
+ struct nl_sock *socksp;
+ error = create_nl_sock(dpif, &socksp);
- if (!socksp) {
+ if (error) {
goto error;
}
- error = vport_add_channels(dpif, vport.port_no, socksp);
+ error = vport_add_channel(dpif, vport.port_no, socksp);
if (error) {
VLOG_INFO("%s: could not add channels for port %s",
dpif_name(&dpif->dpif), vport.name);
- vport_del_socksp(dpif, socksp);
+ nl_sock_destroy(socksp);
retval = error;
goto error;
}
- upcall_pids = vport_socksp_to_pids(socksp, dpif->n_handlers);
- free(socksp);
+ upcall_pid = nl_sock_pid(socksp);
}
/* Configure the vport to deliver misses to 'sock'. */
if (vport.upcall_pids[0] == 0
- || vport.n_upcall_pids != dpif->n_handlers
- || memcmp(upcall_pids, vport.upcall_pids, n_handlers * sizeof
- *upcall_pids)) {
+ || vport.n_upcall_pids != 1
+ || upcall_pid != vport.upcall_pids[0]) {
struct dpif_netlink_vport vport_request;
dpif_netlink_vport_init(&vport_request);
vport_request.cmd = OVS_VPORT_CMD_SET;
vport_request.dp_ifindex = dpif->dp_ifindex;
vport_request.port_no = vport.port_no;
- vport_request.n_upcall_pids = dpif->n_handlers;
- vport_request.upcall_pids = upcall_pids;
+ vport_request.n_upcall_pids = 1;
+ vport_request.upcall_pids = &upcall_pid;
error = dpif_netlink_vport_transact(&vport_request, NULL, NULL);
if (error) {
VLOG_WARN_RL(&error_rl,
@@ -2438,11 +2330,9 @@
if (port_no < keep_channels_nbits) {
bitmap_set1(keep_channels, port_no);
}
- free(upcall_pids);
continue;
error:
- free(upcall_pids);
vport_del_channels(dpif, vport.port_no);
}
nl_dump_done(&dump);
@@ -2701,7 +2591,7 @@
while (handler->event_offset < handler->n_events) {
int idx = handler->epoll_events[handler->event_offset].data.u32;
- struct dpif_channel *ch = &dpif->handlers[handler_id].channels[idx];
+ struct dpif_channel *ch = &dpif->channels[idx];
handler->event_offset++;
@@ -2803,16 +2693,14 @@
OVS_REQ_WRLOCK(dpif->upcall_lock)
{
if (dpif->handlers) {
- size_t i, j;
+ size_t i;
+ if (!dpif->channels[0].sock) {
+ return;
+ }
for (i = 0; i < dpif->uc_array_size; i++ ) {
- if (!dpif->handlers[0].channels[i].sock) {
- continue;
- }
- for (j = 0; j < dpif->n_handlers; j++) {
- nl_sock_drain(dpif->handlers[j].channels[i].sock);
- }
+ nl_sock_drain(dpif->channels[i].sock);
}
}
}
@@ -2961,7 +2849,7 @@
nl_msg_end_nested(request, opt_offset);
int err = nl_transact(NETLINK_GENERIC, request, NULL);
- ofpbuf_uninit(request);
+ ofpbuf_delete(request);
return err;
}
@@ -3061,8 +2949,8 @@
zone_limits_reply);
out:
- ofpbuf_uninit(request);
- ofpbuf_uninit(reply);
+ ofpbuf_delete(request);
+ ofpbuf_delete(reply);
return err;
}
@@ -3098,7 +2986,7 @@
int err = nl_transact(NETLINK_GENERIC, request, NULL);
- ofpbuf_uninit(request);
+ ofpbuf_delete(request);
return err;
}
@@ -4002,7 +3890,7 @@
ovs_be16 pt = pt_ns_type_be(nl_attr_get_be32(packet_type));
const struct nlattr *nla;
- nla = nl_attr_find(buf, NLA_HDRLEN, OVS_KEY_ATTR_ETHERTYPE);
+ nla = nl_attr_find(buf, ofs + NLA_HDRLEN, OVS_KEY_ATTR_ETHERTYPE);
if (nla) {
ovs_be16 *ethertype;
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/dpif-provider.h openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/dpif-provider.h
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/dpif-provider.h 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/dpif-provider.h 2020-03-11 16:15:44.000000000 +0000
@@ -191,16 +191,7 @@
/* Returns the Netlink PID value to supply in OVS_ACTION_ATTR_USERSPACE
* actions as the OVS_USERSPACE_ATTR_PID attribute's value, for use in
- * flows whose packets arrived on port 'port_no'. In the case where the
- * provider allocates multiple Netlink PIDs to a single port, it may use
- * 'hash' to spread load among them. The caller need not use a particular
- * hash function; a 5-tuple hash is suitable.
- *
- * (The datapath implementation might use some different hash function for
- * distributing packets received via flow misses among PIDs. This means
- * that packets received via flow misses might be reordered relative to
- * packets received via userspace actions. This is not ordinarily a
- * problem.)
+ * flows whose packets arrived on port 'port_no'.
*
* A 'port_no' of UINT32_MAX should be treated as a special case. The
* implementation should return a reserved PID, not allocated to any port,
@@ -212,8 +203,7 @@
*
* A dpif provider that doesn't have meaningful Netlink PIDs can use NULL
* for this function. This is equivalent to always returning 0. */
- uint32_t (*port_get_pid)(const struct dpif *dpif, odp_port_t port_no,
- uint32_t hash);
+ uint32_t (*port_get_pid)(const struct dpif *dpif, odp_port_t port_no);
/* Attempts to begin dumping the ports in a dpif. On success, returns 0
* and initializes '*statep' with any data needed for iteration. On
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/dp-packet.h openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/dp-packet.h
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/dp-packet.h 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/dp-packet.h 2020-03-11 16:15:44.000000000 +0000
@@ -352,10 +352,23 @@
b->l4_ofs = l4 ? (char *) l4 - (char *) dp_packet_data(b) : UINT16_MAX;
}
+/* Returns the size of the packet from the beginning of the L3 header to the
+ * end of the L3 payload. Hence L2 padding is not included. */
+static inline size_t
+dp_packet_l3_size(const struct dp_packet *b)
+{
+ return OVS_LIKELY(b->l3_ofs != UINT16_MAX)
+ ? (const char *)dp_packet_tail(b) - (const char *)dp_packet_l3(b)
+ - dp_packet_l2_pad_size(b)
+ : 0;
+}
+
+/* Returns the size of the packet from the beginning of the L4 header to the
+ * end of the L4 payload. Hence L2 padding is not included. */
static inline size_t
dp_packet_l4_size(const struct dp_packet *b)
{
- return b->l4_ofs != UINT16_MAX
+ return OVS_LIKELY(b->l4_ofs != UINT16_MAX)
? (const char *)dp_packet_tail(b) - (const char *)dp_packet_l4(b)
- dp_packet_l2_pad_size(b)
: 0;
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/flow.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/flow.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/flow.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/flow.c 2020-03-11 16:15:44.000000000 +0000
@@ -681,7 +681,7 @@
return false;
}
/* Jumbo Payload option not supported yet. */
- if (OVS_UNLIKELY(size - plen > UINT8_MAX)) {
+ if (OVS_UNLIKELY(size - (plen + IPV6_HEADER_LEN) > UINT8_MAX)) {
return false;
}
@@ -868,11 +868,6 @@
}
tc_flow = get_16aligned_be32(&nh->ip6_flow);
- {
- ovs_be32 label = tc_flow & htonl(IPV6_LABEL_MASK);
- miniflow_push_be32(mf, ipv6_label, label);
- }
-
nw_tos = ntohl(tc_flow) >> 20;
nw_ttl = nh->ip6_hlim;
nw_proto = nh->ip6_nxt;
@@ -880,6 +875,12 @@
if (!parse_ipv6_ext_hdrs__(&data, &size, &nw_proto, &nw_frag)) {
goto out;
}
+
+ /* This needs to be after the parse_ipv6_ext_hdrs__() call because it
+ * leaves the nw_frag word uninitialized. */
+ ASSERT_SEQUENTIAL(ipv6_label, nw_frag);
+ ovs_be32 label = tc_flow & htonl(IPV6_LABEL_MASK);
+ miniflow_push_be32(mf, ipv6_label, label);
} else {
if (dl_type == htons(ETH_TYPE_ARP) ||
dl_type == htons(ETH_TYPE_RARP)) {
@@ -1008,15 +1009,14 @@
dst->map = mf.map;
}
-ovs_be16
-parse_dl_type(const struct eth_header *data_, size_t size)
+static ovs_be16
+parse_dl_type(const void **datap, size_t *sizep)
{
- const void *data = data_;
union flow_vlan_hdr vlans[FLOW_MAX_VLAN_HEADERS];
- parse_vlan(&data, &size, vlans);
+ parse_vlan(datap, sizep, vlans);
- return parse_ethertype(&data, &size);
+ return parse_ethertype(datap, sizep);
}
uint16_t
@@ -1034,11 +1034,11 @@
dp_packet_reset_offsets(packet);
- data_pull(&data, &size, ETH_ADDR_LEN * 2);
- dl_type = parse_ethertype(&data, &size);
+ dl_type = parse_dl_type(&data, &size);
if (OVS_UNLIKELY(eth_type_mpls(dl_type))) {
packet->l2_5_ofs = (char *)data - frame;
}
+ packet->l3_ofs = (char *)data - frame;
if (OVS_LIKELY(dl_type == htons(ETH_TYPE_IP))) {
const struct ip_header *nh = data;
int ip_len;
@@ -1048,7 +1048,6 @@
return 0;
}
dp_packet_set_l2_pad_size(packet, size - tot_len);
- packet->l3_ofs = (uint16_t)((char *)nh - frame);
nw_proto = nh->ip_proto;
nw_frag = ipv4_get_nw_frag(nh);
@@ -1061,7 +1060,6 @@
if (OVS_UNLIKELY(!ipv6_sanity_check(nh, size))) {
return 0;
}
- packet->l3_ofs = (uint16_t)((char *)nh - frame);
data_pull(&data, &size, sizeof *nh);
plen = ntohs(nh->ip6_plen); /* Never pull padding. */
@@ -1251,6 +1249,7 @@
if (!bit) {
ds_put_format(ds, "%s: unknown connection tracking state flag",
cs);
+ free(state_s);
return false;
}
state |= bit;
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/flow.h openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/flow.h
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/flow.h 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/flow.h 2020-03-11 16:15:44.000000000 +0000
@@ -131,7 +131,6 @@
bool parse_ipv6_ext_hdrs(const void **datap, size_t *sizep, uint8_t *nw_proto,
uint8_t *nw_frag);
-ovs_be16 parse_dl_type(const struct eth_header *data_, size_t size);
bool parse_nsh(const void **datap, size_t *sizep, struct ovs_key_nsh *key);
uint16_t parse_tcp_flags(struct dp_packet *packet);
@@ -1187,4 +1186,26 @@
&& eth_addr_equals(flow->dl_dst, eth_addr_stp));
}
+/* Returns true if flow->tp_dst equals 'port'. If 'wc' is nonnull, sets
+ * appropriate bits in wc->masks.tp_dst to account for the test.
+ *
+ * The caller must already have ensured that 'flow' is a protocol for which
+ * tp_dst is relevant. */
+static inline bool tp_dst_equals(const struct flow *flow, uint16_t port,
+ struct flow_wildcards *wc)
+{
+ uint16_t diff = port ^ ntohs(flow->tp_dst);
+ if (wc) {
+ if (diff) {
+ /* Set mask for the most significant mismatching bit. */
+ int ofs = raw_clz64((uint64_t) diff << 48); /* range [0,15] */
+ wc->masks.tp_dst |= htons(0x8000 >> ofs);
+ } else {
+ /* Must match all bits. */
+ wc->masks.tp_dst = OVS_BE16_MAX;
+ }
+ }
+ return !diff;
+}
+
#endif /* flow.h */
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/netdev-bsd.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/netdev-bsd.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/netdev-bsd.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/netdev-bsd.c 2020-03-11 16:15:44.000000000 +0000
@@ -1479,94 +1479,45 @@
return error;
}
-/* Linux has also different GET_STATS, SET_STATS,
- * GET_STATUS)
- */
-#define NETDEV_BSD_CLASS(NAME, CONSTRUCT, \
- GET_FEATURES) \
-{ \
- NAME, \
- false, /* is_pmd */ \
- \
- NULL, /* init */ \
- netdev_bsd_run, \
- netdev_bsd_wait, \
- netdev_bsd_alloc, \
- CONSTRUCT, \
- netdev_bsd_destruct, \
- netdev_bsd_dealloc, \
- NULL, /* get_config */ \
- NULL, /* set_config */ \
- NULL, /* get_tunnel_config */ \
- NULL, /* build header */ \
- NULL, /* push header */ \
- NULL, /* pop header */ \
- NULL, /* get_numa_id */ \
- NULL, /* set_tx_multiq */ \
- \
- netdev_bsd_send, \
- netdev_bsd_send_wait, \
- \
- netdev_bsd_set_etheraddr, \
- netdev_bsd_get_etheraddr, \
- netdev_bsd_get_mtu, \
- NULL, /* set_mtu */ \
- netdev_bsd_get_ifindex, \
- netdev_bsd_get_carrier, \
- NULL, /* get_carrier_resets */ \
- NULL, /* set_miimon_interval */ \
- netdev_bsd_get_stats, \
- NULL, /* get_custom_stats */ \
- GET_FEATURES, \
- NULL, /* set_advertisement */ \
- NULL, /* get_pt_mode */ \
- NULL, /* set_policing */ \
- NULL, /* get_qos_type */ \
- NULL, /* get_qos_capabilities */ \
- NULL, /* get_qos */ \
- NULL, /* set_qos */ \
- NULL, /* get_queue */ \
- NULL, /* set_queue */ \
- NULL, /* delete_queue */ \
- NULL, /* get_queue_stats */ \
- NULL, /* queue_dump_start */ \
- NULL, /* queue_dump_next */ \
- NULL, /* queue_dump_done */ \
- NULL, /* dump_queue_stats */ \
- \
- netdev_bsd_set_in4, \
- netdev_bsd_get_addr_list, \
- NULL, /* add_router */ \
- netdev_bsd_get_next_hop, \
- NULL, /* get_status */ \
- netdev_bsd_arp_lookup, /* arp_lookup */ \
- \
- netdev_bsd_update_flags, \
- NULL, /* reconfigure */ \
- \
- netdev_bsd_rxq_alloc, \
- netdev_bsd_rxq_construct, \
- netdev_bsd_rxq_destruct, \
- netdev_bsd_rxq_dealloc, \
- netdev_bsd_rxq_recv, \
- netdev_bsd_rxq_wait, \
- netdev_bsd_rxq_drain, \
- \
- NO_OFFLOAD_API, \
- NULL /* get_block_id */ \
-}
+#define NETDEV_BSD_CLASS_COMMON \
+ .run = netdev_bsd_run, \
+ .wait = netdev_bsd_wait, \
+ .alloc = netdev_bsd_alloc, \
+ .destruct = netdev_bsd_destruct, \
+ .dealloc = netdev_bsd_dealloc, \
+ .send = netdev_bsd_send, \
+ .send_wait = netdev_bsd_send_wait, \
+ .set_etheraddr = netdev_bsd_set_etheraddr, \
+ .get_etheraddr = netdev_bsd_get_etheraddr, \
+ .get_mtu = netdev_bsd_get_mtu, \
+ .get_ifindex = netdev_bsd_get_ifindex, \
+ .get_carrier = netdev_bsd_get_carrier, \
+ .get_stats = netdev_bsd_get_stats, \
+ .get_features = netdev_bsd_get_features, \
+ .set_in4 = netdev_bsd_set_in4, \
+ .get_addr_list = netdev_bsd_get_addr_list, \
+ .get_next_hop = netdev_bsd_get_next_hop, \
+ .arp_lookup = netdev_bsd_arp_lookup, \
+ .update_flags = netdev_bsd_update_flags, \
+ .rxq_alloc = netdev_bsd_rxq_alloc, \
+ .rxq_construct = netdev_bsd_rxq_construct, \
+ .rxq_destruct = netdev_bsd_rxq_destruct, \
+ .rxq_dealloc = netdev_bsd_rxq_dealloc, \
+ .rxq_recv = netdev_bsd_rxq_recv, \
+ .rxq_wait = netdev_bsd_rxq_wait, \
+ .rxq_drain = netdev_bsd_rxq_drain
-const struct netdev_class netdev_bsd_class =
- NETDEV_BSD_CLASS(
- "system",
- netdev_bsd_construct_system,
- netdev_bsd_get_features);
+const struct netdev_class netdev_bsd_class = {
+ NETDEV_BSD_CLASS_COMMON,
+ .type = "system",
+ .construct = netdev_bsd_construct_system,
+};
-const struct netdev_class netdev_tap_class =
- NETDEV_BSD_CLASS(
- "tap",
- netdev_bsd_construct_tap,
- netdev_bsd_get_features);
+const struct netdev_class netdev_tap_class = {
+ NETDEV_BSD_CLASS_COMMON,
+ .type = "tap",
+ .construct = netdev_bsd_construct_tap,
+};
static void
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/netdev.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/netdev.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/netdev.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/netdev.c 2020-03-11 16:15:44.000000000 +0000
@@ -1801,8 +1801,9 @@
netdev_queue_dump_next(struct netdev_queue_dump *dump,
unsigned int *queue_id, struct smap *details)
{
- const struct netdev *netdev = dump->netdev;
+ smap_clear(details);
+ const struct netdev *netdev = dump->netdev;
if (dump->error) {
return false;
}
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/netdev-dpdk.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/netdev-dpdk.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/netdev-dpdk.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/netdev-dpdk.c 2020-03-11 16:15:44.000000000 +0000
@@ -1678,6 +1678,7 @@
{
struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
bool rx_fc_en, tx_fc_en, autoneg, lsc_interrupt_mode;
+ bool flow_control_requested = true;
enum rte_eth_fc_mode fc_mode;
static const enum rte_eth_fc_mode fc_mode_set[2][2] = {
{RTE_FC_NONE, RTE_FC_TX_PAUSE},
@@ -1700,7 +1701,7 @@
new_devargs = smap_get(args, "dpdk-devargs");
- if (dev->devargs && strcmp(new_devargs, dev->devargs)) {
+ if (dev->devargs && new_devargs && strcmp(new_devargs, dev->devargs)) {
/* The user requested a new device. If we return error, the caller
* will delete this netdev and try to recreate it. */
err = EAGAIN;
@@ -1765,15 +1766,34 @@
autoneg = smap_get_bool(args, "flow-ctrl-autoneg", false);
fc_mode = fc_mode_set[tx_fc_en][rx_fc_en];
+
+ if (!smap_get(args, "rx-flow-ctrl") && !smap_get(args, "tx-flow-ctrl")
+ && !smap_get(args, "flow-ctrl-autoneg")) {
+ /* FIXME: User didn't ask for flow control configuration.
+ * For now we'll not print a warning if flow control is not
+ * supported by the DPDK port. */
+ flow_control_requested = false;
+ }
+
+ /* Get the Flow control configuration. */
+ err = -rte_eth_dev_flow_ctrl_get(dev->port_id, &dev->fc_conf);
+ if (err) {
+ if (err == ENOTSUP) {
+ if (flow_control_requested) {
+ VLOG_WARN("%s: Flow control is not supported.",
+ netdev_get_name(netdev));
+ }
+ err = 0; /* Not fatal. */
+ } else {
+ VLOG_WARN("%s: Cannot get flow control parameters: %s",
+ netdev_get_name(netdev), rte_strerror(err));
+ }
+ goto out;
+ }
+
if (dev->fc_conf.mode != fc_mode || autoneg != dev->fc_conf.autoneg) {
dev->fc_conf.mode = fc_mode;
dev->fc_conf.autoneg = autoneg;
- /* Get the Flow control configuration for DPDK-ETH */
- err = rte_eth_dev_flow_ctrl_get(dev->port_id, &dev->fc_conf);
- if (err) {
- VLOG_WARN("Cannot get flow control parameters on port "
- DPDK_PORT_ID_FMT", err=%d", dev->port_id, err);
- }
dpdk_eth_flow_ctrl_setup(dev);
}
@@ -2254,7 +2274,7 @@
/* No packets sent - do not retry.*/
break;
}
- } while (cnt && (retries++ <= VHOST_ENQ_RETRY_NUM));
+ } while (cnt && (retries++ < VHOST_ENQ_RETRY_NUM));
rte_spinlock_unlock(&dev->tx_q[qid].tx_lock);
@@ -2707,43 +2727,57 @@
{
struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
struct rte_eth_link link;
+ uint32_t feature = 0;
ovs_mutex_lock(&dev->mutex);
link = dev->link;
ovs_mutex_unlock(&dev->mutex);
- if (link.link_duplex == ETH_LINK_HALF_DUPLEX) {
- if (link.link_speed == ETH_SPEED_NUM_10M) {
- *current = NETDEV_F_10MB_HD;
- }
- if (link.link_speed == ETH_SPEED_NUM_100M) {
- *current = NETDEV_F_100MB_HD;
- }
- if (link.link_speed == ETH_SPEED_NUM_1G) {
- *current = NETDEV_F_1GB_HD;
- }
- } else if (link.link_duplex == ETH_LINK_FULL_DUPLEX) {
- if (link.link_speed == ETH_SPEED_NUM_10M) {
- *current = NETDEV_F_10MB_FD;
- }
- if (link.link_speed == ETH_SPEED_NUM_100M) {
- *current = NETDEV_F_100MB_FD;
- }
- if (link.link_speed == ETH_SPEED_NUM_1G) {
- *current = NETDEV_F_1GB_FD;
- }
- if (link.link_speed == ETH_SPEED_NUM_10G) {
- *current = NETDEV_F_10GB_FD;
+ /* Match against OpenFlow defined link speed values. */
+ if (link.link_duplex == ETH_LINK_FULL_DUPLEX) {
+ switch (link.link_speed) {
+ case ETH_SPEED_NUM_10M:
+ feature |= NETDEV_F_10MB_FD;
+ break;
+ case ETH_SPEED_NUM_100M:
+ feature |= NETDEV_F_100MB_FD;
+ break;
+ case ETH_SPEED_NUM_1G:
+ feature |= NETDEV_F_1GB_FD;
+ break;
+ case ETH_SPEED_NUM_10G:
+ feature |= NETDEV_F_10GB_FD;
+ break;
+ case ETH_SPEED_NUM_40G:
+ feature |= NETDEV_F_40GB_FD;
+ break;
+ case ETH_SPEED_NUM_100G:
+ feature |= NETDEV_F_100GB_FD;
+ break;
+ default:
+ feature |= NETDEV_F_OTHER;
}
- if (link.link_speed == ETH_SPEED_NUM_40G) {
- *current = NETDEV_F_40GB_FD;
+ } else if (link.link_duplex == ETH_LINK_HALF_DUPLEX) {
+ switch (link.link_speed) {
+ case ETH_SPEED_NUM_10M:
+ feature |= NETDEV_F_10MB_HD;
+ break;
+ case ETH_SPEED_NUM_100M:
+ feature |= NETDEV_F_100MB_HD;
+ break;
+ case ETH_SPEED_NUM_1G:
+ feature |= NETDEV_F_1GB_HD;
+ break;
+ default:
+ feature |= NETDEV_F_OTHER;
}
}
if (link.link_autoneg) {
- *current |= NETDEV_F_AUTONEG;
+ feature |= NETDEV_F_AUTONEG;
}
+ *current = feature;
*advertised = *supported = *peer = 0;
return 0;
@@ -2909,6 +2943,26 @@
}
if (dev->type == DPDK_DEV_ETH) {
+
+ if ((dev->flags ^ *old_flagsp) & NETDEV_UP) {
+ int err;
+
+ if (dev->flags & NETDEV_UP) {
+ err = rte_eth_dev_set_link_up(dev->port_id);
+ } else {
+ err = rte_eth_dev_set_link_down(dev->port_id);
+ }
+ if (err == -ENOTSUP) {
+ VLOG_INFO("Interface %s does not support link state "
+ "configuration", netdev_get_name(&dev->up));
+ } else if (err < 0) {
+ VLOG_ERR("Interface %s link change error: %s",
+ netdev_get_name(&dev->up), rte_strerror(-err));
+ dev->flags = *old_flagsp;
+ return -err;
+ }
+ }
+
if (dev->flags & NETDEV_PROMISC) {
rte_eth_promiscuous_enable(dev->port_id);
}
@@ -3253,9 +3307,17 @@
}
}
- VLOG_DBG("TX queue mapping for %s\n", dev->vhost_id);
- for (i = 0; i < total_txqs; i++) {
- VLOG_DBG("%2d --> %2d", i, dev->tx_q[i].map);
+ if (VLOG_IS_DBG_ENABLED()) {
+ struct ds mapping = DS_EMPTY_INITIALIZER;
+
+ ds_put_format(&mapping, "TX queue mapping for port '%s':\n",
+ netdev_get_name(&dev->up));
+ for (i = 0; i < total_txqs; i++) {
+ ds_put_format(&mapping, "%2d --> %2d\n", i, dev->tx_q[i].map);
+ }
+
+ VLOG_DBG("%s", ds_cstr(&mapping));
+ ds_destroy(&mapping);
}
free(enabled_queues);
@@ -3423,7 +3485,7 @@
ovs_mutex_unlock(&dpdk_mutex);
if (exists) {
- VLOG_INFO("State of queue %d ( tx_qid %d ) of vhost device '%s'"
+ VLOG_INFO("State of queue %d ( tx_qid %d ) of vhost device '%s' "
"changed to \'%s\'", queue_id, qid, ifname,
(enable == 1) ? "enabled" : "disabled");
} else {
@@ -4043,7 +4105,7 @@
if (ovs_u128_equals(*ufid, data->ufid)) {
cmap_remove(&ufid_to_rte_flow,
CONST_CAST(struct cmap_node *, &data->node), hash);
- free(data);
+ ovsrcu_postpone(free, data);
return;
}
}
@@ -4072,28 +4134,38 @@
static void
dump_flow_pattern(struct rte_flow_item *item)
{
+ struct ds s;
+
+ if (!VLOG_IS_DBG_ENABLED() || item->type == RTE_FLOW_ITEM_TYPE_END) {
+ return;
+ }
+
+ ds_init(&s);
+
if (item->type == RTE_FLOW_ITEM_TYPE_ETH) {
const struct rte_flow_item_eth *eth_spec = item->spec;
const struct rte_flow_item_eth *eth_mask = item->mask;
- VLOG_DBG("rte flow eth pattern:\n");
+ ds_put_cstr(&s, "rte flow eth pattern:\n");
if (eth_spec) {
- VLOG_DBG(" Spec: src="ETH_ADDR_FMT", dst="ETH_ADDR_FMT", "
+ ds_put_format(&s,
+ " Spec: src="ETH_ADDR_FMT", dst="ETH_ADDR_FMT", "
"type=0x%04" PRIx16"\n",
ETH_ADDR_BYTES_ARGS(eth_spec->src.addr_bytes),
ETH_ADDR_BYTES_ARGS(eth_spec->dst.addr_bytes),
ntohs(eth_spec->type));
} else {
- VLOG_DBG(" Spec = null\n");
+ ds_put_cstr(&s, " Spec = null\n");
}
if (eth_mask) {
- VLOG_DBG(" Mask: src="ETH_ADDR_FMT", dst="ETH_ADDR_FMT", "
+ ds_put_format(&s,
+ " Mask: src="ETH_ADDR_FMT", dst="ETH_ADDR_FMT", "
"type=0x%04"PRIx16"\n",
ETH_ADDR_BYTES_ARGS(eth_mask->src.addr_bytes),
ETH_ADDR_BYTES_ARGS(eth_mask->dst.addr_bytes),
- eth_mask->type);
+ ntohs(eth_mask->type));
} else {
- VLOG_DBG(" Mask = null\n");
+ ds_put_cstr(&s, " Mask = null\n");
}
}
@@ -4101,19 +4173,21 @@
const struct rte_flow_item_vlan *vlan_spec = item->spec;
const struct rte_flow_item_vlan *vlan_mask = item->mask;
- VLOG_DBG("rte flow vlan pattern:\n");
+ ds_put_cstr(&s, "rte flow vlan pattern:\n");
if (vlan_spec) {
- VLOG_DBG(" Spec: tpid=0x%"PRIx16", tci=0x%"PRIx16"\n",
+ ds_put_format(&s,
+ " Spec: tpid=0x%"PRIx16", tci=0x%"PRIx16"\n",
ntohs(vlan_spec->tpid), ntohs(vlan_spec->tci));
} else {
- VLOG_DBG(" Spec = null\n");
+ ds_put_cstr(&s, " Spec = null\n");
}
if (vlan_mask) {
- VLOG_DBG(" Mask: tpid=0x%"PRIx16", tci=0x%"PRIx16"\n",
+ ds_put_format(&s,
+ " Mask: tpid=0x%"PRIx16", tci=0x%"PRIx16"\n",
vlan_mask->tpid, vlan_mask->tci);
} else {
- VLOG_DBG(" Mask = null\n");
+ ds_put_cstr(&s, " Mask = null\n");
}
}
@@ -4121,9 +4195,10 @@
const struct rte_flow_item_ipv4 *ipv4_spec = item->spec;
const struct rte_flow_item_ipv4 *ipv4_mask = item->mask;
- VLOG_DBG("rte flow ipv4 pattern:\n");
+ ds_put_cstr(&s, "rte flow ipv4 pattern:\n");
if (ipv4_spec) {
- VLOG_DBG(" Spec: tos=0x%"PRIx8", ttl=%"PRIx8", proto=0x%"PRIx8
+ ds_put_format(&s,
+ " Spec: tos=0x%"PRIx8", ttl=%"PRIx8", proto=0x%"PRIx8
", src="IP_FMT", dst="IP_FMT"\n",
ipv4_spec->hdr.type_of_service,
ipv4_spec->hdr.time_to_live,
@@ -4131,10 +4206,11 @@
IP_ARGS(ipv4_spec->hdr.src_addr),
IP_ARGS(ipv4_spec->hdr.dst_addr));
} else {
- VLOG_DBG(" Spec = null\n");
+ ds_put_cstr(&s, " Spec = null\n");
}
if (ipv4_mask) {
- VLOG_DBG(" Mask: tos=0x%"PRIx8", ttl=%"PRIx8", proto=0x%"PRIx8
+ ds_put_format(&s,
+ " Mask: tos=0x%"PRIx8", ttl=%"PRIx8", proto=0x%"PRIx8
", src="IP_FMT", dst="IP_FMT"\n",
ipv4_mask->hdr.type_of_service,
ipv4_mask->hdr.time_to_live,
@@ -4142,7 +4218,7 @@
IP_ARGS(ipv4_mask->hdr.src_addr),
IP_ARGS(ipv4_mask->hdr.dst_addr));
} else {
- VLOG_DBG(" Mask = null\n");
+ ds_put_cstr(&s, " Mask = null\n");
}
}
@@ -4150,20 +4226,22 @@
const struct rte_flow_item_udp *udp_spec = item->spec;
const struct rte_flow_item_udp *udp_mask = item->mask;
- VLOG_DBG("rte flow udp pattern:\n");
+ ds_put_cstr(&s, "rte flow udp pattern:\n");
if (udp_spec) {
- VLOG_DBG(" Spec: src_port=%"PRIu16", dst_port=%"PRIu16"\n",
+ ds_put_format(&s,
+ " Spec: src_port=%"PRIu16", dst_port=%"PRIu16"\n",
ntohs(udp_spec->hdr.src_port),
ntohs(udp_spec->hdr.dst_port));
} else {
- VLOG_DBG(" Spec = null\n");
+ ds_put_cstr(&s, " Spec = null\n");
}
if (udp_mask) {
- VLOG_DBG(" Mask: src_port=0x%"PRIx16", dst_port=0x%"PRIx16"\n",
- udp_mask->hdr.src_port,
- udp_mask->hdr.dst_port);
+ ds_put_format(&s,
+ " Mask: src_port=0x%"PRIx16", dst_port=0x%"PRIx16"\n",
+ ntohs(udp_mask->hdr.src_port),
+ ntohs(udp_mask->hdr.dst_port));
} else {
- VLOG_DBG(" Mask = null\n");
+ ds_put_cstr(&s, " Mask = null\n");
}
}
@@ -4171,20 +4249,22 @@
const struct rte_flow_item_sctp *sctp_spec = item->spec;
const struct rte_flow_item_sctp *sctp_mask = item->mask;
- VLOG_DBG("rte flow sctp pattern:\n");
+ ds_put_cstr(&s, "rte flow sctp pattern:\n");
if (sctp_spec) {
- VLOG_DBG(" Spec: src_port=%"PRIu16", dst_port=%"PRIu16"\n",
+ ds_put_format(&s,
+ " Spec: src_port=%"PRIu16", dst_port=%"PRIu16"\n",
ntohs(sctp_spec->hdr.src_port),
ntohs(sctp_spec->hdr.dst_port));
} else {
- VLOG_DBG(" Spec = null\n");
+ ds_put_cstr(&s, " Spec = null\n");
}
if (sctp_mask) {
- VLOG_DBG(" Mask: src_port=0x%"PRIx16", dst_port=0x%"PRIx16"\n",
- sctp_mask->hdr.src_port,
- sctp_mask->hdr.dst_port);
+ ds_put_format(&s,
+ " Mask: src_port=0x%"PRIx16", dst_port=0x%"PRIx16"\n",
+ ntohs(sctp_mask->hdr.src_port),
+ ntohs(sctp_mask->hdr.dst_port));
} else {
- VLOG_DBG(" Mask = null\n");
+ ds_put_cstr(&s, " Mask = null\n");
}
}
@@ -4192,20 +4272,22 @@
const struct rte_flow_item_icmp *icmp_spec = item->spec;
const struct rte_flow_item_icmp *icmp_mask = item->mask;
- VLOG_DBG("rte flow icmp pattern:\n");
+ ds_put_cstr(&s, "rte flow icmp pattern:\n");
if (icmp_spec) {
- VLOG_DBG(" Spec: icmp_type=%"PRIu8", icmp_code=%"PRIu8"\n",
+ ds_put_format(&s,
+ " Spec: icmp_type=%"PRIu8", icmp_code=%"PRIu8"\n",
icmp_spec->hdr.icmp_type,
icmp_spec->hdr.icmp_code);
} else {
- VLOG_DBG(" Spec = null\n");
+ ds_put_cstr(&s, " Spec = null\n");
}
if (icmp_mask) {
- VLOG_DBG(" Mask: icmp_type=0x%"PRIx8", icmp_code=0x%"PRIx8"\n",
+ ds_put_format(&s,
+ " Mask: icmp_type=0x%"PRIx8", icmp_code=0x%"PRIx8"\n",
icmp_spec->hdr.icmp_type,
icmp_spec->hdr.icmp_code);
} else {
- VLOG_DBG(" Mask = null\n");
+ ds_put_cstr(&s, " Mask = null\n");
}
}
@@ -4213,28 +4295,33 @@
const struct rte_flow_item_tcp *tcp_spec = item->spec;
const struct rte_flow_item_tcp *tcp_mask = item->mask;
- VLOG_DBG("rte flow tcp pattern:\n");
+ ds_put_cstr(&s, "rte flow tcp pattern:\n");
if (tcp_spec) {
- VLOG_DBG(" Spec: src_port=%"PRIu16", dst_port=%"PRIu16
+ ds_put_format(&s,
+ " Spec: src_port=%"PRIu16", dst_port=%"PRIu16
", data_off=0x%"PRIx8", tcp_flags=0x%"PRIx8"\n",
ntohs(tcp_spec->hdr.src_port),
ntohs(tcp_spec->hdr.dst_port),
tcp_spec->hdr.data_off,
tcp_spec->hdr.tcp_flags);
} else {
- VLOG_DBG(" Spec = null\n");
+ ds_put_cstr(&s, " Spec = null\n");
}
if (tcp_mask) {
- VLOG_DBG(" Mask: src_port=%"PRIx16", dst_port=%"PRIx16
+ ds_put_format(&s,
+ " Mask: src_port=%"PRIx16", dst_port=%"PRIx16
", data_off=0x%"PRIx8", tcp_flags=0x%"PRIx8"\n",
- tcp_mask->hdr.src_port,
- tcp_mask->hdr.dst_port,
+ ntohs(tcp_mask->hdr.src_port),
+ ntohs(tcp_mask->hdr.dst_port),
tcp_mask->hdr.data_off,
tcp_mask->hdr.tcp_flags);
} else {
- VLOG_DBG(" Mask = null\n");
+ ds_put_cstr(&s, " Mask = null\n");
}
}
+
+ VLOG_DBG("%s", ds_cstr(&s));
+ ds_destroy(&s);
}
static void
@@ -4511,25 +4598,31 @@
add_flow_pattern(&patterns, RTE_FLOW_ITEM_TYPE_END, NULL, NULL);
struct rte_flow_action_mark mark;
+ struct rte_flow_action_rss *rss;
+
mark.id = info->flow_mark;
add_flow_action(&actions, RTE_FLOW_ACTION_TYPE_MARK, &mark);
- struct rte_flow_action_rss *rss;
+ ovs_mutex_lock(&dev->mutex);
+
rss = add_flow_rss_action(&actions, netdev);
add_flow_action(&actions, RTE_FLOW_ACTION_TYPE_END, NULL);
flow = rte_flow_create(dev->port_id, &flow_attr, patterns.items,
actions.actions, &error);
+
+ ovs_mutex_unlock(&dev->mutex);
+
free(rss);
if (!flow) {
- VLOG_ERR("rte flow creat error: %u : message : %s\n",
- error.type, error.message);
+ VLOG_ERR("%s: rte flow creat error: %u : message : %s\n",
+ netdev_get_name(netdev), error.type, error.message);
ret = -1;
goto out;
}
ufid_to_rte_flow_associate(ufid, flow);
- VLOG_DBG("installed flow %p by ufid "UUID_FMT"\n",
- flow, UUID_ARGS((struct uuid *)ufid));
+ VLOG_DBG("%s: installed flow %p by ufid "UUID_FMT"\n",
+ netdev_get_name(netdev), flow, UUID_ARGS((struct uuid *)ufid));
out:
free(patterns.items);
@@ -4633,22 +4726,27 @@
}
static int
-netdev_dpdk_destroy_rte_flow(struct netdev_dpdk *dev,
+netdev_dpdk_destroy_rte_flow(struct netdev *netdev,
const ovs_u128 *ufid,
struct rte_flow *rte_flow) {
+ struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
struct rte_flow_error error;
int ret;
+ ovs_mutex_lock(&dev->mutex);
+
ret = rte_flow_destroy(dev->port_id, rte_flow, &error);
if (ret == 0) {
ufid_to_rte_flow_disassociate(ufid);
- VLOG_DBG("removed rte flow %p associated with ufid " UUID_FMT "\n",
- rte_flow, UUID_ARGS((struct uuid *)ufid));
+ VLOG_DBG("%s: removed rte flow %p associated with ufid " UUID_FMT "\n",
+ netdev_get_name(netdev), rte_flow,
+ UUID_ARGS((struct uuid *)ufid));
} else {
- VLOG_ERR("rte flow destroy error: %u : message : %s\n",
- error.type, error.message);
+ VLOG_ERR("%s: rte flow destroy error: %u : message : %s\n",
+ netdev_get_name(netdev), error.type, error.message);
}
+ ovs_mutex_unlock(&dev->mutex);
return ret;
}
@@ -4666,8 +4764,7 @@
*/
rte_flow = ufid_to_rte_flow_find(ufid);
if (rte_flow) {
- ret = netdev_dpdk_destroy_rte_flow(netdev_dpdk_cast(netdev),
- ufid, rte_flow);
+ ret = netdev_dpdk_destroy_rte_flow(netdev, ufid, rte_flow);
if (ret < 0) {
return ret;
}
@@ -4692,165 +4789,92 @@
return -1;
}
- return netdev_dpdk_destroy_rte_flow(netdev_dpdk_cast(netdev),
- ufid, rte_flow);
+ return netdev_dpdk_destroy_rte_flow(netdev, ufid, rte_flow);
}
-#define DPDK_FLOW_OFFLOAD_API \
- NULL, /* flow_flush */ \
- NULL, /* flow_dump_create */ \
- NULL, /* flow_dump_destroy */ \
- NULL, /* flow_dump_next */ \
- netdev_dpdk_flow_put, \
- NULL, /* flow_get */ \
- netdev_dpdk_flow_del, \
- NULL /* init_flow_api */
-
-
-#define NETDEV_DPDK_CLASS(NAME, INIT, CONSTRUCT, DESTRUCT, \
- SET_CONFIG, SET_TX_MULTIQ, SEND, \
- GET_CARRIER, GET_STATS, \
- GET_CUSTOM_STATS, \
- GET_FEATURES, GET_STATUS, \
- RECONFIGURE, RXQ_RECV) \
-{ \
- NAME, \
- true, /* is_pmd */ \
- INIT, /* init */ \
- NULL, /* netdev_dpdk_run */ \
- NULL, /* netdev_dpdk_wait */ \
- \
- netdev_dpdk_alloc, \
- CONSTRUCT, \
- DESTRUCT, \
- netdev_dpdk_dealloc, \
- netdev_dpdk_get_config, \
- SET_CONFIG, \
- NULL, /* get_tunnel_config */ \
- NULL, /* build header */ \
- NULL, /* push header */ \
- NULL, /* pop header */ \
- netdev_dpdk_get_numa_id, /* get_numa_id */ \
- SET_TX_MULTIQ, \
- \
- SEND, /* send */ \
- NULL, /* send_wait */ \
- \
- netdev_dpdk_set_etheraddr, \
- netdev_dpdk_get_etheraddr, \
- netdev_dpdk_get_mtu, \
- netdev_dpdk_set_mtu, \
- netdev_dpdk_get_ifindex, \
- GET_CARRIER, \
- netdev_dpdk_get_carrier_resets, \
- netdev_dpdk_set_miimon, \
- GET_STATS, \
- GET_CUSTOM_STATS, \
- GET_FEATURES, \
- NULL, /* set_advertisements */ \
- NULL, /* get_pt_mode */ \
- \
- netdev_dpdk_set_policing, \
- netdev_dpdk_get_qos_types, \
- NULL, /* get_qos_capabilities */ \
- netdev_dpdk_get_qos, \
- netdev_dpdk_set_qos, \
- NULL, /* get_queue */ \
- NULL, /* set_queue */ \
- NULL, /* delete_queue */ \
- NULL, /* get_queue_stats */ \
- NULL, /* queue_dump_start */ \
- NULL, /* queue_dump_next */ \
- NULL, /* queue_dump_done */ \
- NULL, /* dump_queue_stats */ \
- \
- NULL, /* set_in4 */ \
- NULL, /* get_addr_list */ \
- NULL, /* add_router */ \
- NULL, /* get_next_hop */ \
- GET_STATUS, \
- NULL, /* arp_lookup */ \
- \
- netdev_dpdk_update_flags, \
- RECONFIGURE, \
- \
- netdev_dpdk_rxq_alloc, \
- netdev_dpdk_rxq_construct, \
- netdev_dpdk_rxq_destruct, \
- netdev_dpdk_rxq_dealloc, \
- RXQ_RECV, \
- NULL, /* rx_wait */ \
- NULL, /* rxq_drain */ \
- DPDK_FLOW_OFFLOAD_API, \
- NULL /* get_block_id */ \
-}
-
-static const struct netdev_class dpdk_class =
- NETDEV_DPDK_CLASS(
- "dpdk",
- netdev_dpdk_class_init,
- netdev_dpdk_construct,
- netdev_dpdk_destruct,
- netdev_dpdk_set_config,
- netdev_dpdk_set_tx_multiq,
- netdev_dpdk_eth_send,
- netdev_dpdk_get_carrier,
- netdev_dpdk_get_stats,
- netdev_dpdk_get_custom_stats,
- netdev_dpdk_get_features,
- netdev_dpdk_get_status,
- netdev_dpdk_reconfigure,
- netdev_dpdk_rxq_recv);
-
-static const struct netdev_class dpdk_ring_class =
- NETDEV_DPDK_CLASS(
- "dpdkr",
- netdev_dpdk_class_init,
- netdev_dpdk_ring_construct,
- netdev_dpdk_destruct,
- netdev_dpdk_ring_set_config,
- netdev_dpdk_set_tx_multiq,
- netdev_dpdk_ring_send,
- netdev_dpdk_get_carrier,
- netdev_dpdk_get_stats,
- netdev_dpdk_get_custom_stats,
- netdev_dpdk_get_features,
- netdev_dpdk_get_status,
- netdev_dpdk_reconfigure,
- netdev_dpdk_rxq_recv);
-
-static const struct netdev_class dpdk_vhost_class =
- NETDEV_DPDK_CLASS(
- "dpdkvhostuser",
- NULL,
- netdev_dpdk_vhost_construct,
- netdev_dpdk_vhost_destruct,
- NULL,
- NULL,
- netdev_dpdk_vhost_send,
- netdev_dpdk_vhost_get_carrier,
- netdev_dpdk_vhost_get_stats,
- NULL,
- NULL,
- netdev_dpdk_vhost_user_get_status,
- netdev_dpdk_vhost_reconfigure,
- netdev_dpdk_vhost_rxq_recv);
-static const struct netdev_class dpdk_vhost_client_class =
- NETDEV_DPDK_CLASS(
- "dpdkvhostuserclient",
- NULL,
- netdev_dpdk_vhost_client_construct,
- netdev_dpdk_vhost_destruct,
- netdev_dpdk_vhost_client_set_config,
- NULL,
- netdev_dpdk_vhost_send,
- netdev_dpdk_vhost_get_carrier,
- netdev_dpdk_vhost_get_stats,
- NULL,
- NULL,
- netdev_dpdk_vhost_user_get_status,
- netdev_dpdk_vhost_client_reconfigure,
- netdev_dpdk_vhost_rxq_recv);
+#define DPDK_FLOW_OFFLOAD_API \
+ .flow_put = netdev_dpdk_flow_put, \
+ .flow_del = netdev_dpdk_flow_del
+
+#define NETDEV_DPDK_CLASS_COMMON \
+ .is_pmd = true, \
+ .alloc = netdev_dpdk_alloc, \
+ .dealloc = netdev_dpdk_dealloc, \
+ .get_config = netdev_dpdk_get_config, \
+ .get_numa_id = netdev_dpdk_get_numa_id, \
+ .set_etheraddr = netdev_dpdk_set_etheraddr, \
+ .get_etheraddr = netdev_dpdk_get_etheraddr, \
+ .get_mtu = netdev_dpdk_get_mtu, \
+ .set_mtu = netdev_dpdk_set_mtu, \
+ .get_ifindex = netdev_dpdk_get_ifindex, \
+ .get_carrier_resets = netdev_dpdk_get_carrier_resets, \
+ .set_miimon_interval = netdev_dpdk_set_miimon, \
+ .set_policing = netdev_dpdk_set_policing, \
+ .get_qos_types = netdev_dpdk_get_qos_types, \
+ .get_qos = netdev_dpdk_get_qos, \
+ .set_qos = netdev_dpdk_set_qos, \
+ .update_flags = netdev_dpdk_update_flags, \
+ .rxq_alloc = netdev_dpdk_rxq_alloc, \
+ .rxq_construct = netdev_dpdk_rxq_construct, \
+ .rxq_destruct = netdev_dpdk_rxq_destruct, \
+ .rxq_dealloc = netdev_dpdk_rxq_dealloc
+
+#define NETDEV_DPDK_CLASS_BASE \
+ NETDEV_DPDK_CLASS_COMMON, \
+ .init = netdev_dpdk_class_init, \
+ .destruct = netdev_dpdk_destruct, \
+ .set_tx_multiq = netdev_dpdk_set_tx_multiq, \
+ .get_carrier = netdev_dpdk_get_carrier, \
+ .get_stats = netdev_dpdk_get_stats, \
+ .get_custom_stats = netdev_dpdk_get_custom_stats, \
+ .get_features = netdev_dpdk_get_features, \
+ .get_status = netdev_dpdk_get_status, \
+ .reconfigure = netdev_dpdk_reconfigure, \
+ .rxq_recv = netdev_dpdk_rxq_recv, \
+ DPDK_FLOW_OFFLOAD_API
+
+static const struct netdev_class dpdk_class = {
+ .type = "dpdk",
+ NETDEV_DPDK_CLASS_BASE,
+ .construct = netdev_dpdk_construct,
+ .set_config = netdev_dpdk_set_config,
+ .send = netdev_dpdk_eth_send,
+};
+
+static const struct netdev_class dpdk_ring_class = {
+ .type = "dpdkr",
+ NETDEV_DPDK_CLASS_BASE,
+ .construct = netdev_dpdk_ring_construct,
+ .set_config = netdev_dpdk_ring_set_config,
+ .send = netdev_dpdk_ring_send,
+};
+
+static const struct netdev_class dpdk_vhost_class = {
+ .type = "dpdkvhostuser",
+ NETDEV_DPDK_CLASS_COMMON,
+ .construct = netdev_dpdk_vhost_construct,
+ .destruct = netdev_dpdk_vhost_destruct,
+ .send = netdev_dpdk_vhost_send,
+ .get_carrier = netdev_dpdk_vhost_get_carrier,
+ .get_stats = netdev_dpdk_vhost_get_stats,
+ .get_status = netdev_dpdk_vhost_user_get_status,
+ .reconfigure = netdev_dpdk_vhost_reconfigure,
+ .rxq_recv = netdev_dpdk_vhost_rxq_recv
+};
+
+static const struct netdev_class dpdk_vhost_client_class = {
+ .type = "dpdkvhostuserclient",
+ NETDEV_DPDK_CLASS_COMMON,
+ .construct = netdev_dpdk_vhost_client_construct,
+ .destruct = netdev_dpdk_vhost_destruct,
+ .set_config = netdev_dpdk_vhost_client_set_config,
+ .send = netdev_dpdk_vhost_send,
+ .get_carrier = netdev_dpdk_vhost_get_carrier,
+ .get_stats = netdev_dpdk_vhost_get_stats,
+ .get_status = netdev_dpdk_vhost_user_get_status,
+ .reconfigure = netdev_dpdk_vhost_client_reconfigure,
+ .rxq_recv = netdev_dpdk_vhost_rxq_recv
+};
void
netdev_dpdk_register(void)
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/netdev-dummy.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/netdev-dummy.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/netdev-dummy.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/netdev-dummy.c 2020-03-11 16:15:44.000000000 +0000
@@ -1393,90 +1393,56 @@
/* Helper functions. */
-#define NETDEV_DUMMY_CLASS(NAME, PMD, RECOFIGURE) \
-{ \
- NAME, \
- PMD, /* is_pmd */ \
- NULL, /* init */ \
- netdev_dummy_run, \
- netdev_dummy_wait, \
- \
- netdev_dummy_alloc, \
- netdev_dummy_construct, \
- netdev_dummy_destruct, \
- netdev_dummy_dealloc, \
- netdev_dummy_get_config, \
- netdev_dummy_set_config, \
- NULL, /* get_tunnel_config */ \
- NULL, /* build header */ \
- NULL, /* push header */ \
- NULL, /* pop header */ \
- netdev_dummy_get_numa_id, \
- NULL, /* set_tx_multiq */ \
- \
- netdev_dummy_send, /* send */ \
- NULL, /* send_wait */ \
- \
- netdev_dummy_set_etheraddr, \
- netdev_dummy_get_etheraddr, \
- netdev_dummy_get_mtu, \
- netdev_dummy_set_mtu, \
- netdev_dummy_get_ifindex, \
- NULL, /* get_carrier */ \
- NULL, /* get_carrier_resets */ \
- NULL, /* get_miimon */ \
- netdev_dummy_get_stats, \
- netdev_dummy_get_custom_stats, \
- \
- NULL, /* get_features */ \
- NULL, /* set_advertisements */ \
- NULL, /* get_pt_mode */ \
- \
- NULL, /* set_policing */ \
- NULL, /* get_qos_types */ \
- NULL, /* get_qos_capabilities */ \
- NULL, /* get_qos */ \
- NULL, /* set_qos */ \
- netdev_dummy_get_queue, \
- NULL, /* set_queue */ \
- NULL, /* delete_queue */ \
- netdev_dummy_get_queue_stats, \
- netdev_dummy_queue_dump_start, \
- netdev_dummy_queue_dump_next, \
- netdev_dummy_queue_dump_done, \
- netdev_dummy_dump_queue_stats, \
- \
- NULL, /* set_in4 */ \
- netdev_dummy_get_addr_list, \
- NULL, /* add_router */ \
- NULL, /* get_next_hop */ \
- NULL, /* get_status */ \
- NULL, /* arp_lookup */ \
- \
- netdev_dummy_update_flags, \
- RECOFIGURE, \
- \
- netdev_dummy_rxq_alloc, \
- netdev_dummy_rxq_construct, \
- netdev_dummy_rxq_destruct, \
- netdev_dummy_rxq_dealloc, \
- netdev_dummy_rxq_recv, \
- netdev_dummy_rxq_wait, \
- netdev_dummy_rxq_drain, \
- \
- NO_OFFLOAD_API, \
- NULL /* get_block_id */ \
-}
+#define NETDEV_DUMMY_CLASS_COMMON \
+ .run = netdev_dummy_run, \
+ .wait = netdev_dummy_wait, \
+ .alloc = netdev_dummy_alloc, \
+ .construct = netdev_dummy_construct, \
+ .destruct = netdev_dummy_destruct, \
+ .dealloc = netdev_dummy_dealloc, \
+ .get_config = netdev_dummy_get_config, \
+ .set_config = netdev_dummy_set_config, \
+ .get_numa_id = netdev_dummy_get_numa_id, \
+ .send = netdev_dummy_send, \
+ .set_etheraddr = netdev_dummy_set_etheraddr, \
+ .get_etheraddr = netdev_dummy_get_etheraddr, \
+ .get_mtu = netdev_dummy_get_mtu, \
+ .set_mtu = netdev_dummy_set_mtu, \
+ .get_ifindex = netdev_dummy_get_ifindex, \
+ .get_stats = netdev_dummy_get_stats, \
+ .get_custom_stats = netdev_dummy_get_custom_stats, \
+ .get_queue = netdev_dummy_get_queue, \
+ .get_queue_stats = netdev_dummy_get_queue_stats, \
+ .queue_dump_start = netdev_dummy_queue_dump_start, \
+ .queue_dump_next = netdev_dummy_queue_dump_next, \
+ .queue_dump_done = netdev_dummy_queue_dump_done, \
+ .dump_queue_stats = netdev_dummy_dump_queue_stats, \
+ .get_addr_list = netdev_dummy_get_addr_list, \
+ .update_flags = netdev_dummy_update_flags, \
+ .rxq_alloc = netdev_dummy_rxq_alloc, \
+ .rxq_construct = netdev_dummy_rxq_construct, \
+ .rxq_destruct = netdev_dummy_rxq_destruct, \
+ .rxq_dealloc = netdev_dummy_rxq_dealloc, \
+ .rxq_recv = netdev_dummy_rxq_recv, \
+ .rxq_wait = netdev_dummy_rxq_wait, \
+ .rxq_drain = netdev_dummy_rxq_drain
-static const struct netdev_class dummy_class =
- NETDEV_DUMMY_CLASS("dummy", false, NULL);
+static const struct netdev_class dummy_class = {
+ NETDEV_DUMMY_CLASS_COMMON,
+ .type = "dummy"
+};
-static const struct netdev_class dummy_internal_class =
- NETDEV_DUMMY_CLASS("dummy-internal", false, NULL);
+static const struct netdev_class dummy_internal_class = {
+ NETDEV_DUMMY_CLASS_COMMON,
+ .type = "dummy-internal"
+};
-static const struct netdev_class dummy_pmd_class =
- NETDEV_DUMMY_CLASS("dummy-pmd", true,
- netdev_dummy_reconfigure);
+static const struct netdev_class dummy_pmd_class = {
+ NETDEV_DUMMY_CLASS_COMMON,
+ .type = "dummy-pmd",
+ .is_pmd = true,
+ .reconfigure = netdev_dummy_reconfigure
+};
static void
pkt_list_delete(struct ovs_list *l)
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/netdev-linux.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/netdev-linux.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/netdev-linux.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/netdev-linux.c 2020-03-11 16:15:44.000000000 +0000
@@ -739,11 +739,14 @@
lag->block_id = block_id;
lag->node = shash_add(&lag_shash, change->ifname, lag);
+ /* delete ingress block in case it exists */
+ tc_add_del_ingress_qdisc(change->if_index, false, 0);
/* LAG master is linux netdev so add slave to same block. */
error = tc_add_del_ingress_qdisc(change->if_index, true,
block_id);
if (error) {
- VLOG_WARN("failed to bind LAG slave to master's block");
+ VLOG_WARN("failed to bind LAG slave %s to master's block",
+ change->ifname);
shash_delete(&lag_shash, lag->node);
free(lag);
}
@@ -3158,113 +3161,77 @@
return error;
}
-#define NETDEV_LINUX_CLASS(NAME, CONSTRUCT, GET_STATS, \
- GET_FEATURES, GET_STATUS, \
- FLOW_OFFLOAD_API, GET_BLOCK_ID) \
-{ \
- NAME, \
- false, /* is_pmd */ \
- \
- NULL, \
- netdev_linux_run, \
- netdev_linux_wait, \
- \
- netdev_linux_alloc, \
- CONSTRUCT, \
- netdev_linux_destruct, \
- netdev_linux_dealloc, \
- NULL, /* get_config */ \
- NULL, /* set_config */ \
- NULL, /* get_tunnel_config */ \
- NULL, /* build header */ \
- NULL, /* push header */ \
- NULL, /* pop header */ \
- NULL, /* get_numa_id */ \
- NULL, /* set_tx_multiq */ \
- \
- netdev_linux_send, \
- netdev_linux_send_wait, \
- \
- netdev_linux_set_etheraddr, \
- netdev_linux_get_etheraddr, \
- netdev_linux_get_mtu, \
- netdev_linux_set_mtu, \
- netdev_linux_get_ifindex, \
- netdev_linux_get_carrier, \
- netdev_linux_get_carrier_resets, \
- netdev_linux_set_miimon_interval, \
- GET_STATS, \
- NULL, \
- \
- GET_FEATURES, \
- netdev_linux_set_advertisements, \
- NULL, /* get_pt_mode */ \
- \
- netdev_linux_set_policing, \
- netdev_linux_get_qos_types, \
- netdev_linux_get_qos_capabilities, \
- netdev_linux_get_qos, \
- netdev_linux_set_qos, \
- netdev_linux_get_queue, \
- netdev_linux_set_queue, \
- netdev_linux_delete_queue, \
- netdev_linux_get_queue_stats, \
- netdev_linux_queue_dump_start, \
- netdev_linux_queue_dump_next, \
- netdev_linux_queue_dump_done, \
- netdev_linux_dump_queue_stats, \
- \
- netdev_linux_set_in4, \
- netdev_linux_get_addr_list, \
- netdev_linux_add_router, \
- netdev_linux_get_next_hop, \
- GET_STATUS, \
- netdev_linux_arp_lookup, \
- \
- netdev_linux_update_flags, \
- NULL, /* reconfigure */ \
- \
- netdev_linux_rxq_alloc, \
- netdev_linux_rxq_construct, \
- netdev_linux_rxq_destruct, \
- netdev_linux_rxq_dealloc, \
- netdev_linux_rxq_recv, \
- netdev_linux_rxq_wait, \
- netdev_linux_rxq_drain, \
- \
- FLOW_OFFLOAD_API, \
- GET_BLOCK_ID \
-}
-
-const struct netdev_class netdev_linux_class =
- NETDEV_LINUX_CLASS(
- "system",
- netdev_linux_construct,
- netdev_linux_get_stats,
- netdev_linux_get_features,
- netdev_linux_get_status,
- LINUX_FLOW_OFFLOAD_API,
- netdev_linux_get_block_id);
-
-const struct netdev_class netdev_tap_class =
- NETDEV_LINUX_CLASS(
- "tap",
- netdev_linux_construct_tap,
- netdev_tap_get_stats,
- netdev_linux_get_features,
- netdev_linux_get_status,
- NO_OFFLOAD_API,
- NULL);
-
-const struct netdev_class netdev_internal_class =
- NETDEV_LINUX_CLASS(
- "internal",
- netdev_linux_construct,
- netdev_internal_get_stats,
- NULL, /* get_features */
- netdev_internal_get_status,
- NO_OFFLOAD_API,
- NULL);
+#define NETDEV_LINUX_CLASS_COMMON \
+ .run = netdev_linux_run, \
+ .wait = netdev_linux_wait, \
+ .alloc = netdev_linux_alloc, \
+ .destruct = netdev_linux_destruct, \
+ .dealloc = netdev_linux_dealloc, \
+ .send = netdev_linux_send, \
+ .send_wait = netdev_linux_send_wait, \
+ .set_etheraddr = netdev_linux_set_etheraddr, \
+ .get_etheraddr = netdev_linux_get_etheraddr, \
+ .get_mtu = netdev_linux_get_mtu, \
+ .set_mtu = netdev_linux_set_mtu, \
+ .get_ifindex = netdev_linux_get_ifindex, \
+ .get_carrier = netdev_linux_get_carrier, \
+ .get_carrier_resets = netdev_linux_get_carrier_resets, \
+ .set_miimon_interval = netdev_linux_set_miimon_interval, \
+ .set_advertisements = netdev_linux_set_advertisements, \
+ .set_policing = netdev_linux_set_policing, \
+ .get_qos_types = netdev_linux_get_qos_types, \
+ .get_qos_capabilities = netdev_linux_get_qos_capabilities, \
+ .get_qos = netdev_linux_get_qos, \
+ .set_qos = netdev_linux_set_qos, \
+ .get_queue = netdev_linux_get_queue, \
+ .set_queue = netdev_linux_set_queue, \
+ .delete_queue = netdev_linux_delete_queue, \
+ .get_queue_stats = netdev_linux_get_queue_stats, \
+ .queue_dump_start = netdev_linux_queue_dump_start, \
+ .queue_dump_next = netdev_linux_queue_dump_next, \
+ .queue_dump_done = netdev_linux_queue_dump_done, \
+ .dump_queue_stats = netdev_linux_dump_queue_stats, \
+ .set_in4 = netdev_linux_set_in4, \
+ .get_addr_list = netdev_linux_get_addr_list, \
+ .add_router = netdev_linux_add_router, \
+ .get_next_hop = netdev_linux_get_next_hop, \
+ .arp_lookup = netdev_linux_arp_lookup, \
+ .update_flags = netdev_linux_update_flags, \
+ .rxq_alloc = netdev_linux_rxq_alloc, \
+ .rxq_construct = netdev_linux_rxq_construct, \
+ .rxq_destruct = netdev_linux_rxq_destruct, \
+ .rxq_dealloc = netdev_linux_rxq_dealloc, \
+ .rxq_recv = netdev_linux_rxq_recv, \
+ .rxq_wait = netdev_linux_rxq_wait, \
+ .rxq_drain = netdev_linux_rxq_drain
+
+const struct netdev_class netdev_linux_class = {
+ NETDEV_LINUX_CLASS_COMMON,
+ LINUX_FLOW_OFFLOAD_API,
+ .type = "system",
+ .construct = netdev_linux_construct,
+ .get_stats = netdev_linux_get_stats,
+ .get_features = netdev_linux_get_features,
+ .get_status = netdev_linux_get_status,
+ .get_block_id = netdev_linux_get_block_id
+};
+
+const struct netdev_class netdev_tap_class = {
+ NETDEV_LINUX_CLASS_COMMON,
+ .type = "tap",
+ .construct = netdev_linux_construct_tap,
+ .get_stats = netdev_tap_get_stats,
+ .get_features = netdev_linux_get_features,
+ .get_status = netdev_linux_get_status,
+};
+
+const struct netdev_class netdev_internal_class = {
+ NETDEV_LINUX_CLASS_COMMON,
+ .type = "internal",
+ .construct = netdev_linux_construct,
+ .get_stats = netdev_internal_get_stats,
+ .get_status = netdev_internal_get_status,
+};
#define CODEL_N_QUEUES 0x0000
@@ -3461,19 +3428,14 @@
}
static const struct tc_ops tc_ops_codel = {
- "codel", /* linux_name */
- "linux-codel", /* ovs_name */
- CODEL_N_QUEUES, /* n_queues */
- codel_tc_install,
- codel_tc_load,
- codel_tc_destroy,
- codel_qdisc_get,
- codel_qdisc_set,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL
+ .linux_name = "codel",
+ .ovs_name = "linux-codel",
+ .n_queues = CODEL_N_QUEUES,
+ .tc_install = codel_tc_install,
+ .tc_load = codel_tc_load,
+ .tc_destroy = codel_tc_destroy,
+ .qdisc_get = codel_qdisc_get,
+ .qdisc_set = codel_qdisc_set,
};
/* FQ-CoDel traffic control class. */
@@ -3703,19 +3665,14 @@
}
static const struct tc_ops tc_ops_fqcodel = {
- "fq_codel", /* linux_name */
- "linux-fq_codel", /* ovs_name */
- FQCODEL_N_QUEUES, /* n_queues */
- fqcodel_tc_install,
- fqcodel_tc_load,
- fqcodel_tc_destroy,
- fqcodel_qdisc_get,
- fqcodel_qdisc_set,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL
+ .linux_name = "fq_codel",
+ .ovs_name = "linux-fq_codel",
+ .n_queues = FQCODEL_N_QUEUES,
+ .tc_install = fqcodel_tc_install,
+ .tc_load = fqcodel_tc_load,
+ .tc_destroy = fqcodel_tc_destroy,
+ .qdisc_get = fqcodel_qdisc_get,
+ .qdisc_set = fqcodel_qdisc_set,
};
/* SFQ traffic control class. */
@@ -3845,7 +3802,7 @@
error = tc_parse_qdisc(nlmsg, &kind, &nlattr);
if (error == 0) {
sfq = nl_attr_get(nlattr);
- sfq_install__(netdev, sfq->perturb_period, sfq->quantum);
+ sfq_install__(netdev, sfq->quantum, sfq->perturb_period);
return 0;
}
@@ -3882,19 +3839,14 @@
}
static const struct tc_ops tc_ops_sfq = {
- "sfq", /* linux_name */
- "linux-sfq", /* ovs_name */
- SFQ_N_QUEUES, /* n_queues */
- sfq_tc_install,
- sfq_tc_load,
- sfq_tc_destroy,
- sfq_qdisc_get,
- sfq_qdisc_set,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL
+ .linux_name = "sfq",
+ .ovs_name = "linux-sfq",
+ .n_queues = SFQ_N_QUEUES,
+ .tc_install = sfq_tc_install,
+ .tc_load = sfq_tc_load,
+ .tc_destroy = sfq_tc_destroy,
+ .qdisc_get = sfq_qdisc_get,
+ .qdisc_set = sfq_qdisc_set,
};
/* HTB traffic control class. */
@@ -4364,19 +4316,19 @@
}
static const struct tc_ops tc_ops_htb = {
- "htb", /* linux_name */
- "linux-htb", /* ovs_name */
- HTB_N_QUEUES, /* n_queues */
- htb_tc_install,
- htb_tc_load,
- htb_tc_destroy,
- htb_qdisc_get,
- htb_qdisc_set,
- htb_class_get,
- htb_class_set,
- htb_class_delete,
- htb_class_get_stats,
- htb_class_dump_stats
+ .linux_name = "htb",
+ .ovs_name = "linux-htb",
+ .n_queues = HTB_N_QUEUES,
+ .tc_install = htb_tc_install,
+ .tc_load = htb_tc_load,
+ .tc_destroy = htb_tc_destroy,
+ .qdisc_get = htb_qdisc_get,
+ .qdisc_set = htb_qdisc_set,
+ .class_get = htb_class_get,
+ .class_set = htb_class_set,
+ .class_delete = htb_class_delete,
+ .class_get_stats = htb_class_get_stats,
+ .class_dump_stats = htb_class_dump_stats
};
/* "linux-hfsc" traffic control class. */
@@ -4861,19 +4813,19 @@
}
static const struct tc_ops tc_ops_hfsc = {
- "hfsc", /* linux_name */
- "linux-hfsc", /* ovs_name */
- HFSC_N_QUEUES, /* n_queues */
- hfsc_tc_install, /* tc_install */
- hfsc_tc_load, /* tc_load */
- hfsc_tc_destroy, /* tc_destroy */
- hfsc_qdisc_get, /* qdisc_get */
- hfsc_qdisc_set, /* qdisc_set */
- hfsc_class_get, /* class_get */
- hfsc_class_set, /* class_set */
- hfsc_class_delete, /* class_delete */
- hfsc_class_get_stats, /* class_get_stats */
- hfsc_class_dump_stats /* class_dump_stats */
+ .linux_name = "hfsc",
+ .ovs_name = "linux-hfsc",
+ .n_queues = HFSC_N_QUEUES, /* n_queues */
+ .tc_install = hfsc_tc_install,
+ .tc_load = hfsc_tc_load,
+ .tc_destroy = hfsc_tc_destroy,
+ .qdisc_get = hfsc_qdisc_get,
+ .qdisc_set = hfsc_qdisc_set,
+ .class_get = hfsc_class_get,
+ .class_set = hfsc_class_set,
+ .class_delete = hfsc_class_delete,
+ .class_get_stats = hfsc_class_get_stats,
+ .class_dump_stats = hfsc_class_dump_stats,
};
/* "linux-noop" traffic control class. */
@@ -4903,19 +4855,9 @@
}
static const struct tc_ops tc_ops_noop = {
- NULL, /* linux_name */
- "linux-noop", /* ovs_name */
- 0, /* n_queues */
- noop_tc_install,
- noop_tc_load,
- NULL, /* tc_destroy */
- NULL, /* qdisc_get */
- NULL, /* qdisc_set */
- NULL, /* class_get */
- NULL, /* class_set */
- NULL, /* class_delete */
- NULL, /* class_get_stats */
- NULL /* class_dump_stats */
+ .ovs_name = "linux-noop", /* ovs_name */
+ .tc_install = noop_tc_install,
+ .tc_load = noop_tc_load,
};
/* "linux-default" traffic control class.
@@ -4950,19 +4892,9 @@
}
static const struct tc_ops tc_ops_default = {
- NULL, /* linux_name */
- "", /* ovs_name */
- 0, /* n_queues */
- default_tc_install,
- default_tc_load,
- NULL, /* tc_destroy */
- NULL, /* qdisc_get */
- NULL, /* qdisc_set */
- NULL, /* class_get */
- NULL, /* class_set */
- NULL, /* class_delete */
- NULL, /* class_get_stats */
- NULL /* class_dump_stats */
+ .ovs_name = "", /* ovs_name */
+ .tc_install = default_tc_install,
+ .tc_load = default_tc_load,
};
/* "linux-other" traffic control class.
@@ -4982,19 +4914,8 @@
}
static const struct tc_ops tc_ops_other = {
- NULL, /* linux_name */
- "linux-other", /* ovs_name */
- 0, /* n_queues */
- NULL, /* tc_install */
- other_tc_load,
- NULL, /* tc_destroy */
- NULL, /* qdisc_get */
- NULL, /* qdisc_set */
- NULL, /* class_get */
- NULL, /* class_set */
- NULL, /* class_delete */
- NULL, /* class_get_stats */
- NULL /* class_dump_stats */
+ .ovs_name = "linux-other",
+ .tc_load = other_tc_load,
};
/* Traffic control. */
@@ -5842,7 +5763,7 @@
* and the interface name statically stored in ovsdb. */
nl_msg_put_string(&request, IFLA_IFNAME, netdev_get_name(&netdev->up));
if (netdev_linux_netnsid_is_remote(netdev)) {
- nl_msg_push_u32(&request, IFLA_IF_NETNSID, netdev->netnsid);
+ nl_msg_put_u32(&request, IFLA_IF_NETNSID, netdev->netnsid);
}
error = nl_transact(NETLINK_ROUTE, &request, &reply);
ofpbuf_uninit(&request);
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/netdev-linux.h openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/netdev-linux.h
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/netdev-linux.h 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/netdev-linux.h 2020-03-11 16:15:44.000000000 +0000
@@ -29,14 +29,14 @@
const char *flag_name, bool enable);
int linux_get_ifindex(const char *netdev_name);
-#define LINUX_FLOW_OFFLOAD_API \
- netdev_tc_flow_flush, \
- netdev_tc_flow_dump_create, \
- netdev_tc_flow_dump_destroy, \
- netdev_tc_flow_dump_next, \
- netdev_tc_flow_put, \
- netdev_tc_flow_get, \
- netdev_tc_flow_del, \
- netdev_tc_init_flow_api
+#define LINUX_FLOW_OFFLOAD_API \
+ .flow_flush = netdev_tc_flow_flush, \
+ .flow_dump_create = netdev_tc_flow_dump_create, \
+ .flow_dump_destroy = netdev_tc_flow_dump_destroy, \
+ .flow_dump_next = netdev_tc_flow_dump_next, \
+ .flow_put = netdev_tc_flow_put, \
+ .flow_get = netdev_tc_flow_get, \
+ .flow_del = netdev_tc_flow_del, \
+ .init_flow_api = netdev_tc_init_flow_api
#endif /* netdev-linux.h */
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/netdev-provider.h openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/netdev-provider.h
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/netdev-provider.h 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/netdev-provider.h 2020-03-11 16:15:44.000000000 +0000
@@ -893,6 +893,4 @@
}
#endif
-#define NO_OFFLOAD_API NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
-
#endif /* netdev.h */
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/netdev-tc-offloads.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/netdev-tc-offloads.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/netdev-tc-offloads.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/netdev-tc-offloads.c 2020-03-11 16:15:44.000000000 +0000
@@ -163,8 +163,20 @@
ovs_mutex_unlock(&ufid_lock);
}
-/* Add ufid entry to ufid_tc hashmap.
- * If entry exists already it will be replaced. */
+/* Wrapper function to delete filter and ufid tc mapping */
+static int
+del_filter_and_ufid_mapping(int ifindex, int prio, int handle,
+ uint32_t block_id, const ovs_u128 *ufid)
+{
+ int err;
+
+ err = tc_del_filter(ifindex, prio, handle, block_id);
+ del_ufid_tc_mapping(ufid);
+
+ return err;
+}
+
+/* Add ufid entry to ufid_tc hashmap. */
static void
add_ufid_tc_mapping(const ovs_u128 *ufid, int prio, int handle,
struct netdev *netdev, int ifindex)
@@ -173,8 +185,6 @@
size_t tc_hash = hash_int(hash_int(prio, handle), ifindex);
struct ufid_tc_data *new_data = xzalloc(sizeof *new_data);
- del_ufid_tc_mapping(ufid);
-
new_data->ufid = *ufid;
new_data->prio = prio;
new_data->handle = handle;
@@ -877,14 +887,18 @@
key->nw_proto == IPPROTO_ICMPV6) {
if (mask->tp_src) {
VLOG_DBG_RL(&rl,
- "offloading attribute icmp_type isn't supported");
+ "offloading attribute icmpv6_type isn't supported");
return EOPNOTSUPP;
}
if (mask->tp_dst) {
VLOG_DBG_RL(&rl,
- "offloading attribute icmp_code isn't supported");
+ "offloading attribute icmpv6_code isn't supported");
return EOPNOTSUPP;
}
+ } else if (key->dl_type == htons(OFP_DL_TYPE_NOT_ETH_TYPE)) {
+ VLOG_DBG_RL(&rl,
+ "offloading of non-ethernet packets isn't supported");
+ return EOPNOTSUPP;
}
if (!is_all_zeros(mask, sizeof *mask)) {
@@ -956,10 +970,12 @@
&& (vid_mask || pcp_mask)) {
if (vid_mask) {
flower.key.vlan_id = vlan_tci_to_vid(key->vlans[0].tci);
+ flower.mask.vlan_id = vlan_tci_to_vid(mask->vlans[0].tci);
VLOG_DBG_RL(&rl, "vlan_id: %d\n", flower.key.vlan_id);
}
if (pcp_mask) {
flower.key.vlan_prio = vlan_tci_to_pcp(key->vlans[0].tci);
+ flower.mask.vlan_prio = vlan_tci_to_pcp(mask->vlans[0].tci);
VLOG_DBG_RL(&rl, "vlan_prio: %d\n", flower.key.vlan_prio);
}
flower.key.encap_eth_type = flower.key.eth_type;
@@ -1057,14 +1073,19 @@
}
}
+ /* ignore exact match on skb_mark of 0. */
+ if (mask->pkt_mark == UINT32_MAX && !key->pkt_mark) {
+ mask->pkt_mark = 0;
+ }
+
err = test_key_and_mask(match);
if (err) {
return err;
}
NL_ATTR_FOR_EACH(nla, left, actions, actions_len) {
- if (flower.action_count >= TCA_ACT_MAX_PRIO) {
- VLOG_DBG_RL(&rl, "Can only support %d actions", flower.action_count);
+ if (flower.action_count >= TCA_ACT_MAX_NUM) {
+ VLOG_DBG_RL(&rl, "Can only support %d actions", TCA_ACT_MAX_NUM);
return EOPNOTSUPP;
}
action = &flower.actions[flower.action_count];
@@ -1072,6 +1093,10 @@
odp_port_t port = nl_attr_get_odp_port(nla);
struct netdev *outdev = netdev_ports_get(port, info->dpif_class);
+ if (!outdev) {
+ VLOG_DBG_RL(&rl, "Can't find netdev for output port %d", port);
+ return ENODEV;
+ }
action->ifindex_out = netdev_get_ifindex(outdev);
action->type = TC_ACT_OUTPUT;
flower.action_count++;
@@ -1117,7 +1142,7 @@
handle = get_ufid_tc_mapping(ufid, &prio, NULL);
if (handle && prio) {
VLOG_DBG_RL(&rl, "updating old handle: %d prio: %d", handle, prio);
- tc_del_filter(ifindex, prio, handle, block_id);
+ del_filter_and_ufid_mapping(ifindex, prio, handle, block_id, ufid);
}
if (!prio) {
@@ -1171,9 +1196,9 @@
return -ifindex;
}
- VLOG_DBG_RL(&rl, "flow get (dev %s prio %d handle %d)",
- netdev_get_name(dev), prio, handle);
- block_id = get_block_id_from_netdev(netdev);
+ block_id = get_block_id_from_netdev(dev);
+ VLOG_DBG_RL(&rl, "flow get (dev %s prio %d handle %d block_id %d)",
+ netdev_get_name(dev), prio, handle, block_id);
err = tc_get_flower(ifindex, prio, handle, &flower, block_id);
netdev_close(dev);
if (err) {
@@ -1217,7 +1242,7 @@
return -ifindex;
}
- block_id = get_block_id_from_netdev(netdev);
+ block_id = get_block_id_from_netdev(dev);
if (stats) {
memset(stats, 0, sizeof *stats);
@@ -1228,8 +1253,7 @@
}
}
- error = tc_del_filter(ifindex, prio, handle, block_id);
- del_ufid_tc_mapping(ufid);
+ error = del_filter_and_ufid_mapping(ifindex, prio, handle, block_id, ufid);
netdev_close(dev);
@@ -1282,6 +1306,7 @@
static void
probe_tc_block_support(int ifindex)
{
+ struct tc_flower flower;
uint32_t block_id = 1;
int error;
@@ -1290,10 +1315,21 @@
return;
}
+ memset(&flower, 0, sizeof flower);
+
+ flower.key.eth_type = htons(ETH_P_IP);
+ flower.mask.eth_type = OVS_BE16_MAX;
+ memset(&flower.key.dst_mac, 0x11, sizeof flower.key.dst_mac);
+ memset(&flower.mask.dst_mac, 0xff, sizeof flower.mask.dst_mac);
+
+ error = tc_replace_flower(ifindex, 1, 1, &flower, block_id);
+
tc_add_del_ingress_qdisc(ifindex, false, block_id);
- block_support = true;
- VLOG_INFO("probe tc: block offload is supported.");
+ if (!error) {
+ block_support = true;
+ VLOG_INFO("probe tc: block offload is supported.");
+ }
}
int
@@ -1312,6 +1348,9 @@
return -ifindex;
}
+ /* make sure there is no ingress qdisc */
+ tc_add_del_ingress_qdisc(ifindex, false, 0);
+
if (ovsthread_once_start(&block_once)) {
probe_tc_block_support(ifindex);
ovsthread_once_done(&block_once);
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/netdev-vport.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/netdev-vport.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/netdev-vport.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/netdev-vport.c 2020-03-11 16:15:44.000000000 +0000
@@ -936,7 +936,7 @@
}
static int
-get_stats(const struct netdev *netdev, struct netdev_stats *stats)
+netdev_vport_get_stats(const struct netdev *netdev, struct netdev_stats *stats)
{
struct netdev_vport *dev = netdev_vport_cast(netdev);
@@ -952,7 +952,7 @@
}
static enum netdev_pt_mode
-get_pt_mode(const struct netdev *netdev)
+netdev_vport_get_pt_mode(const struct netdev *netdev)
{
struct netdev_vport *dev = netdev_vport_cast(netdev);
@@ -972,98 +972,32 @@
}
#define NETDEV_VPORT_GET_IFINDEX netdev_vport_get_ifindex
-#define NETDEV_FLOW_OFFLOAD_API LINUX_FLOW_OFFLOAD_API
+#define NETDEV_FLOW_OFFLOAD_API , LINUX_FLOW_OFFLOAD_API
#else /* !__linux__ */
#define NETDEV_VPORT_GET_IFINDEX NULL
-#define NETDEV_FLOW_OFFLOAD_API NO_OFFLOAD_API
+#define NETDEV_FLOW_OFFLOAD_API
#endif /* __linux__ */
-#define VPORT_FUNCTIONS(GET_CONFIG, SET_CONFIG, \
- GET_TUNNEL_CONFIG, GET_STATUS, \
- BUILD_HEADER, \
- PUSH_HEADER, POP_HEADER, \
- GET_IFINDEX) \
- NULL, \
- netdev_vport_run, \
- netdev_vport_wait, \
- \
- netdev_vport_alloc, \
- netdev_vport_construct, \
- netdev_vport_destruct, \
- netdev_vport_dealloc, \
- GET_CONFIG, \
- SET_CONFIG, \
- GET_TUNNEL_CONFIG, \
- BUILD_HEADER, \
- PUSH_HEADER, \
- POP_HEADER, \
- NULL, /* get_numa_id */ \
- NULL, /* set_tx_multiq */ \
- \
- NULL, /* send */ \
- NULL, /* send_wait */ \
- \
- netdev_vport_set_etheraddr, \
- netdev_vport_get_etheraddr, \
- NULL, /* get_mtu */ \
- NULL, /* set_mtu */ \
- GET_IFINDEX, \
- NULL, /* get_carrier */ \
- NULL, /* get_carrier_resets */ \
- NULL, /* get_miimon */ \
- get_stats, \
- NULL, /* get_custom_stats */ \
- \
- NULL, /* get_features */ \
- NULL, /* set_advertisements */ \
- get_pt_mode, \
- \
- NULL, /* set_policing */ \
- NULL, /* get_qos_types */ \
- NULL, /* get_qos_capabilities */ \
- NULL, /* get_qos */ \
- NULL, /* set_qos */ \
- NULL, /* get_queue */ \
- NULL, /* set_queue */ \
- NULL, /* delete_queue */ \
- NULL, /* get_queue_stats */ \
- NULL, /* queue_dump_start */ \
- NULL, /* queue_dump_next */ \
- NULL, /* queue_dump_done */ \
- NULL, /* dump_queue_stats */ \
- \
- NULL, /* set_in4 */ \
- NULL, /* get_addr_list */ \
- NULL, /* add_router */ \
- NULL, /* get_next_hop */ \
- GET_STATUS, \
- NULL, /* arp_lookup */ \
- \
- netdev_vport_update_flags, \
- NULL, /* reconfigure */ \
- \
- NULL, /* rx_alloc */ \
- NULL, /* rx_construct */ \
- NULL, /* rx_destruct */ \
- NULL, /* rx_dealloc */ \
- NULL, /* rx_recv */ \
- NULL, /* rx_wait */ \
- NULL, /* rx_drain */ \
- \
- NETDEV_FLOW_OFFLOAD_API, \
- NULL /* get_block_id */
-
-
-#define TUNNEL_CLASS(NAME, DPIF_PORT, BUILD_HEADER, PUSH_HEADER, POP_HEADER, \
- GET_IFINDEX) \
- { DPIF_PORT, \
- { NAME, false, \
- VPORT_FUNCTIONS(get_tunnel_config, \
- set_tunnel_config, \
- get_netdev_tunnel_config, \
- tunnel_get_status, \
- BUILD_HEADER, PUSH_HEADER, POP_HEADER, \
- GET_IFINDEX) }}
+#define VPORT_FUNCTIONS_COMMON \
+ .run = netdev_vport_run, \
+ .wait = netdev_vport_wait, \
+ .alloc = netdev_vport_alloc, \
+ .construct = netdev_vport_construct, \
+ .destruct = netdev_vport_destruct, \
+ .dealloc = netdev_vport_dealloc, \
+ .set_etheraddr = netdev_vport_set_etheraddr, \
+ .get_etheraddr = netdev_vport_get_etheraddr, \
+ .get_stats = netdev_vport_get_stats, \
+ .get_pt_mode = netdev_vport_get_pt_mode, \
+ .update_flags = netdev_vport_update_flags \
+ NETDEV_FLOW_OFFLOAD_API
+
+#define TUNNEL_FUNCTIONS_COMMON \
+ VPORT_FUNCTIONS_COMMON, \
+ .get_config = get_tunnel_config, \
+ .set_config = set_tunnel_config, \
+ .get_tunnel_config = get_netdev_tunnel_config, \
+ .get_status = tunnel_get_status
void
netdev_vport_tunnel_register(void)
@@ -1071,32 +1005,74 @@
/* The name of the dpif_port should be short enough to accomodate adding
* a port number to the end if one is necessary. */
static const struct vport_class vport_classes[] = {
- TUNNEL_CLASS("geneve", "genev_sys", netdev_geneve_build_header,
- netdev_tnl_push_udp_header,
- netdev_geneve_pop_header,
- NETDEV_VPORT_GET_IFINDEX),
- TUNNEL_CLASS("gre", "gre_sys", netdev_gre_build_header,
- netdev_gre_push_header,
- netdev_gre_pop_header,
- NULL),
- TUNNEL_CLASS("vxlan", "vxlan_sys", netdev_vxlan_build_header,
- netdev_tnl_push_udp_header,
- netdev_vxlan_pop_header,
- NETDEV_VPORT_GET_IFINDEX),
- TUNNEL_CLASS("lisp", "lisp_sys", NULL, NULL, NULL, NULL),
- TUNNEL_CLASS("stt", "stt_sys", NULL, NULL, NULL, NULL),
- TUNNEL_CLASS("erspan", "erspan_sys", netdev_erspan_build_header,
- netdev_erspan_push_header,
- netdev_erspan_pop_header,
- NULL),
- TUNNEL_CLASS("ip6erspan", "ip6erspan_sys", netdev_erspan_build_header,
- netdev_erspan_push_header,
- netdev_erspan_pop_header,
- NULL),
- TUNNEL_CLASS("ip6gre", "ip6gre_sys", netdev_gre_build_header,
- netdev_gre_push_header,
- netdev_gre_pop_header,
- NULL),
+ { "genev_sys",
+ {
+ TUNNEL_FUNCTIONS_COMMON,
+ .type = "geneve",
+ .build_header = netdev_geneve_build_header,
+ .push_header = netdev_tnl_push_udp_header,
+ .pop_header = netdev_geneve_pop_header,
+ .get_ifindex = NETDEV_VPORT_GET_IFINDEX,
+ }
+ },
+ { "gre_sys",
+ {
+ TUNNEL_FUNCTIONS_COMMON,
+ .type = "gre",
+ .build_header = netdev_gre_build_header,
+ .push_header = netdev_gre_push_header,
+ .pop_header = netdev_gre_pop_header
+ }
+ },
+ { "vxlan_sys",
+ {
+ TUNNEL_FUNCTIONS_COMMON,
+ .type = "vxlan",
+ .build_header = netdev_vxlan_build_header,
+ .push_header = netdev_tnl_push_udp_header,
+ .pop_header = netdev_vxlan_pop_header,
+ .get_ifindex = NETDEV_VPORT_GET_IFINDEX
+ }
+ },
+ { "lisp_sys",
+ {
+ TUNNEL_FUNCTIONS_COMMON,
+ .type = "lisp"
+ }
+ },
+ { "stt_sys",
+ {
+ TUNNEL_FUNCTIONS_COMMON,
+ .type = "stt"
+ }
+ },
+ { "erspan_sys",
+ {
+ TUNNEL_FUNCTIONS_COMMON,
+ .type = "erspan",
+ .build_header = netdev_erspan_build_header,
+ .push_header = netdev_erspan_push_header,
+ .pop_header = netdev_erspan_pop_header
+ }
+ },
+ { "ip6erspan_sys",
+ {
+ TUNNEL_FUNCTIONS_COMMON,
+ .type = "ip6erspan",
+ .build_header = netdev_erspan_build_header,
+ .push_header = netdev_erspan_push_header,
+ .pop_header = netdev_erspan_pop_header
+ }
+ },
+ { "ip6gre_sys",
+ {
+ TUNNEL_FUNCTIONS_COMMON,
+ .type = "ip6gre",
+ .build_header = netdev_gre_build_header,
+ .push_header = netdev_gre_push_header,
+ .pop_header = netdev_gre_pop_header
+ }
+ },
};
static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
@@ -1117,12 +1093,13 @@
void
netdev_vport_patch_register(void)
{
- static const struct vport_class patch_class =
- { NULL,
- { "patch", false,
- VPORT_FUNCTIONS(get_patch_config,
- set_patch_config,
- NULL,
- NULL, NULL, NULL, NULL, NULL) }};
+ static const struct vport_class patch_class = {
+ NULL,
+ { VPORT_FUNCTIONS_COMMON,
+ .type = "patch",
+ .get_config = get_patch_config,
+ .set_config = set_patch_config,
+ }
+ };
netdev_register_provider(&patch_class.netdev_class);
}
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/netlink-socket.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/netlink-socket.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/netlink-socket.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/netlink-socket.c 2020-03-11 16:15:44.000000000 +0000
@@ -1571,6 +1571,11 @@
family_name = OVS_WIN_NETDEV_FAMILY;
family_version = OVS_WIN_NETDEV_VERSION;
family_attrmax = OVS_WIN_NETDEV_ATTR_MAX;
+ } else if (!strcmp(name, OVS_CT_LIMIT_FAMILY)) {
+ family_id = OVS_WIN_NL_CTLIMIT_FAMILY_ID;
+ family_name = OVS_CT_LIMIT_FAMILY;
+ family_version = OVS_CT_LIMIT_VERSION;
+ family_attrmax = OVS_CT_LIMIT_ATTR_MAX;
} else {
ofpbuf_delete(reply);
return EINVAL;
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/odp-util.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/odp-util.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/odp-util.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/odp-util.c 2020-03-11 16:15:44.000000000 +0000
@@ -1915,8 +1915,8 @@
s += n;
retval = scan_u128(s, &ct_label.value, &ct_label.mask);
- if (retval < 0) {
- return retval;
+ if (retval == 0) {
+ return -EINVAL;
}
s += retval;
continue;
@@ -2104,14 +2104,14 @@
struct ofpbuf b;
char buf[512];
size_t mdlen, padding;
- if (ovs_scan_len(s, &n, "md2=0x%511[0-9a-fA-F]", buf)) {
- ofpbuf_use_stub(&b, metadata,
- NSH_CTX_HDRS_MAX_LEN);
+ if (ovs_scan_len(s, &n, "md2=0x%511[0-9a-fA-F]", buf)
+ && n/2 <= sizeof metadata) {
+ ofpbuf_use_stub(&b, metadata, sizeof metadata);
ofpbuf_put_hex(&b, buf, &mdlen);
/* Pad metadata to 4 bytes. */
padding = PAD_SIZE(mdlen, 4);
if (padding > 0) {
- ofpbuf_push_zeros(&b, padding);
+ ofpbuf_put_zeros(&b, padding);
}
md_size = mdlen + padding;
ofpbuf_uninit(&b);
@@ -2153,6 +2153,10 @@
n += retval;
}
+ if (actions->size > UINT16_MAX) {
+ return -EFBIG;
+ }
+
return n;
}
@@ -2242,13 +2246,14 @@
key->nla_len += size;
ofpbuf_put(actions, mask + 1, size);
- /* Add new padding as needed */
- ofpbuf_put_zeros(actions, NLA_ALIGN(key->nla_len) -
- key->nla_len);
-
/* 'actions' may have been reallocated by ofpbuf_put(). */
nested = ofpbuf_at_assert(actions, start_ofs, sizeof *nested);
nested->nla_type = OVS_ACTION_ATTR_SET_MASKED;
+
+ key = nested + 1;
+ /* Add new padding as needed */
+ ofpbuf_put_zeros(actions, NLA_ALIGN(key->nla_len) -
+ key->nla_len);
}
}
ofpbuf_uninit(&maskbuf);
@@ -2558,6 +2563,8 @@
bool has_md1 = false;
bool has_md2 = false;
+ memset(nsh_hdr, 0, size);
+
NL_NESTED_FOR_EACH (a, left, attr) {
uint16_t type = nl_attr_type(a);
size_t len = nl_attr_get_size(a);
@@ -2695,7 +2702,7 @@
return ODP_FIT_TOO_MUCH;
}
- if (has_md1 && nsh->mdtype != NSH_M_TYPE1) {
+ if (has_md1 && nsh->mdtype != NSH_M_TYPE1 && !nsh_mask) {
return ODP_FIT_ERROR;
}
@@ -4803,10 +4810,15 @@
const char *s_base = s;
ovs_be16 id = 0, id_mask = 0;
uint8_t flags = 0, flags_mask = 0;
+ int len;
if (!strncmp(s, "id=", 3)) {
s += 3;
- s += scan_be16(s, &id, mask ? &id_mask : NULL);
+ len = scan_be16(s, &id, mask ? &id_mask : NULL);
+ if (len == 0) {
+ return -EINVAL;
+ }
+ s += len;
}
if (s[0] == ',') {
@@ -4814,7 +4826,11 @@
}
if (!strncmp(s, "flags=", 6)) {
s += 6;
- s += scan_u8(s, &flags, mask ? &flags_mask : NULL);
+ len = scan_u8(s, &flags, mask ? &flags_mask : NULL);
+ if (len == 0) {
+ return -EINVAL;
+ }
+ s += len;
}
if (!strncmp(s, "))", 2)) {
@@ -4840,10 +4856,15 @@
uint32_t idx = 0, idx_mask = 0;
uint8_t ver = 0, dir = 0, hwid = 0;
uint8_t ver_mask = 0, dir_mask = 0, hwid_mask = 0;
+ int len;
if (!strncmp(s, "ver=", 4)) {
s += 4;
- s += scan_u8(s, &ver, mask ? &ver_mask : NULL);
+ len = scan_u8(s, &ver, mask ? &ver_mask : NULL);
+ if (len == 0) {
+ return -EINVAL;
+ }
+ s += len;
}
if (s[0] == ',') {
@@ -4853,7 +4874,11 @@
if (ver == 1) {
if (!strncmp(s, "idx=", 4)) {
s += 4;
- s += scan_u32(s, &idx, mask ? &idx_mask : NULL);
+ len = scan_u32(s, &idx, mask ? &idx_mask : NULL);
+ if (len == 0) {
+ return -EINVAL;
+ }
+ s += len;
}
if (!strncmp(s, ")", 1)) {
@@ -4869,14 +4894,22 @@
} else if (ver == 2) {
if (!strncmp(s, "dir=", 4)) {
s += 4;
- s += scan_u8(s, &dir, mask ? &dir_mask : NULL);
+ len = scan_u8(s, &dir, mask ? &dir_mask : NULL);
+ if (len == 0) {
+ return -EINVAL;
+ }
+ s += len;
}
if (s[0] == ',') {
s++;
}
if (!strncmp(s, "hwid=", 5)) {
s += 5;
- s += scan_u8(s, &hwid, mask ? &hwid_mask : NULL);
+ len = scan_u8(s, &hwid, mask ? &hwid_mask : NULL);
+ if (len == 0) {
+ return -EINVAL;
+ }
+ s += len;
}
if (!strncmp(s, ")", 1)) {
@@ -4902,6 +4935,7 @@
struct geneve_opt *opt = key->d;
struct geneve_opt *opt_mask = mask ? mask->d : NULL;
int len_remain = sizeof key->d;
+ int len;
while (s[0] == '{' && len_remain >= sizeof *opt) {
int data_len = 0;
@@ -4911,8 +4945,12 @@
if (!strncmp(s, "class=", 6)) {
s += 6;
- s += scan_be16(s, &opt->opt_class,
- mask ? &opt_mask->opt_class : NULL);
+ len = scan_be16(s, &opt->opt_class,
+ mask ? &opt_mask->opt_class : NULL);
+ if (len == 0) {
+ return -EINVAL;
+ }
+ s += len;
} else if (mask) {
memset(&opt_mask->opt_class, 0, sizeof opt_mask->opt_class);
}
@@ -4922,7 +4960,11 @@
}
if (!strncmp(s, "type=", 5)) {
s += 5;
- s += scan_u8(s, &opt->type, mask ? &opt_mask->type : NULL);
+ len = scan_u8(s, &opt->type, mask ? &opt_mask->type : NULL);
+ if (len == 0) {
+ return -EINVAL;
+ }
+ s += len;
} else if (mask) {
memset(&opt_mask->type, 0, sizeof opt_mask->type);
}
@@ -4933,7 +4975,11 @@
if (!strncmp(s, "len=", 4)) {
uint8_t opt_len, opt_len_mask;
s += 4;
- s += scan_u8(s, &opt_len, mask ? &opt_len_mask : NULL);
+ len = scan_u8(s, &opt_len, mask ? &opt_len_mask : NULL);
+ if (len == 0) {
+ return -EINVAL;
+ }
+ s += len;
if (opt_len > 124 || opt_len % 4 || opt_len > len_remain) {
return 0;
@@ -4978,7 +5024,7 @@
}
if (s[0] == ')') {
- int len = sizeof key->d - len_remain;
+ len = sizeof key->d - len_remain;
s++;
key->len = len;
@@ -5363,13 +5409,6 @@
parse_odp_key_mask_attr(const char *s, const struct simap *port_names,
struct ofpbuf *key, struct ofpbuf *mask)
{
- /* Skip UFID. */
- ovs_u128 ufid;
- int ufid_len = odp_ufid_from_string(s, &ufid);
- if (ufid_len) {
- return ufid_len;
- }
-
SCAN_SINGLE("skb_priority(", uint32_t, u32, OVS_KEY_ATTR_PRIORITY);
SCAN_SINGLE("skb_mark(", uint32_t, u32, OVS_KEY_ATTR_SKB_MARK);
SCAN_SINGLE_FULLY_MASKED("recirc_id(", uint32_t, u32,
@@ -5540,6 +5579,10 @@
if (retval < 0) {
return retval;
}
+
+ if (nl_attr_oversized(key->size - encap - NLA_HDRLEN)) {
+ return -E2BIG;
+ }
s += retval;
}
s++;
@@ -5582,6 +5625,17 @@
return 0;
}
+ /* Skip UFID. */
+ ovs_u128 ufid;
+ retval = odp_ufid_from_string(s, &ufid);
+ if (retval < 0) {
+ key->size = old_size;
+ return -retval;
+ } else if (retval > 0) {
+ s += retval;
+ s += s[0] == ' ' ? 1 : 0;
+ }
+
retval = parse_odp_key_mask_attr(s, port_names, key, mask);
if (retval < 0) {
key->size = old_size;
@@ -5675,26 +5729,28 @@
if (flow->ct_nw_proto) {
if (parms->support.ct_orig_tuple
&& flow->dl_type == htons(ETH_TYPE_IP)) {
- struct ovs_key_ct_tuple_ipv4 ct = {
- data->ct_nw_src,
- data->ct_nw_dst,
- data->ct_tp_src,
- data->ct_tp_dst,
- data->ct_nw_proto,
- };
- nl_msg_put_unspec(buf, OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4, &ct,
- sizeof ct);
+ struct ovs_key_ct_tuple_ipv4 *ct;
+
+ /* 'struct ovs_key_ct_tuple_ipv4' has padding, clear it. */
+ ct = nl_msg_put_unspec_zero(buf, OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4,
+ sizeof *ct);
+ ct->ipv4_src = data->ct_nw_src;
+ ct->ipv4_dst = data->ct_nw_dst;
+ ct->src_port = data->ct_tp_src;
+ ct->dst_port = data->ct_tp_dst;
+ ct->ipv4_proto = data->ct_nw_proto;
} else if (parms->support.ct_orig_tuple6
&& flow->dl_type == htons(ETH_TYPE_IPV6)) {
- struct ovs_key_ct_tuple_ipv6 ct = {
- data->ct_ipv6_src,
- data->ct_ipv6_dst,
- data->ct_tp_src,
- data->ct_tp_dst,
- data->ct_nw_proto,
- };
- nl_msg_put_unspec(buf, OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6, &ct,
- sizeof ct);
+ struct ovs_key_ct_tuple_ipv6 *ct;
+
+ /* 'struct ovs_key_ct_tuple_ipv6' has padding, clear it. */
+ ct = nl_msg_put_unspec_zero(buf, OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6,
+ sizeof *ct);
+ ct->ipv6_src = data->ct_ipv6_src;
+ ct->ipv6_dst = data->ct_ipv6_dst;
+ ct->src_port = data->ct_tp_src;
+ ct->dst_port = data->ct_tp_dst;
+ ct->ipv6_proto = data->ct_nw_proto;
}
}
if (parms->support.recirc) {
@@ -6700,6 +6756,9 @@
flow->packet_type
= nl_attr_get_be32(attrs[OVS_KEY_ATTR_PACKET_TYPE]);
expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_PACKET_TYPE;
+ if (pt_ns(src_flow->packet_type) == OFPHTN_ETHERTYPE) {
+ flow->dl_type = pt_ns_type_be(flow->packet_type);
+ }
} else if (!is_mask) {
flow->packet_type = htonl(PT_ETH);
}
@@ -7260,6 +7319,7 @@
get_ipv6_key(&wc->masks, &mask, true);
mask.ipv6_proto = 0; /* Not writeable. */
mask.ipv6_frag = 0; /* Not writable. */
+ mask.ipv6_label &= htonl(IPV6_LABEL_MASK); /* Not writable. */
if (flow_tnl_dst_is_set(&base_flow->tunnel) &&
((base_flow->nw_tos ^ flow->nw_tos) & IP_ECN_MASK) == 0) {
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/ofp-actions.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/ofp-actions.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/ofp-actions.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/ofp-actions.c 2020-03-11 16:15:44.000000000 +0000
@@ -824,7 +824,7 @@
}
case NXAC2PT_USERDATA:
- out->size = start_ofs + OFPACT_CONTROLLER_SIZE;
+ out->size = start_ofs + sizeof(struct ofpact_controller);
ofpbuf_put(out, payload.msg, ofpbuf_msgsize(&payload));
oc = ofpbuf_at_assert(out, start_ofs, sizeof *oc);
oc->userdata_len = ofpbuf_msgsize(&payload);
@@ -8792,11 +8792,16 @@
ofpacts_parse(char *str, const struct ofpact_parse_params *pp,
bool allow_instructions, enum ofpact_type outer_action)
{
+ if (pp->depth >= MAX_OFPACT_PARSE_DEPTH) {
+ return xstrdup("Action nested too deeply");
+ }
+ CONST_CAST(struct ofpact_parse_params *, pp)->depth++;
uint32_t orig_size = pp->ofpacts->size;
char *error = ofpacts_parse__(str, pp, allow_instructions, outer_action);
if (error) {
pp->ofpacts->size = orig_size;
}
+ CONST_CAST(struct ofpact_parse_params *, pp)->depth--;
return error;
}
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/ofpbuf.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/ofpbuf.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/ofpbuf.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/ofpbuf.c 2020-03-11 16:15:44.000000000 +0000
@@ -469,9 +469,9 @@
ofpbuf_insert(struct ofpbuf *b, size_t offset, const void *data, size_t n)
{
if (offset < b->size) {
- ofpbuf_put_uninit(b, n);
+ ofpbuf_put_uninit(b, n); /* b->size gets increased. */
memmove((char *) b->data + offset + n, (char *) b->data + offset,
- b->size - offset);
+ b->size - offset - n);
memcpy((char *) b->data + offset, data, n);
} else {
ovs_assert(offset == b->size);
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/ofp-bundle.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/ofp-bundle.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/ofp-bundle.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/ofp-bundle.c 2020-03-11 16:15:44.000000000 +0000
@@ -65,7 +65,7 @@
request = ofputil_encode_flow_mod(&bms[i].fm, protocol);
break;
case OFPTYPE_GROUP_MOD:
- request = ofputil_encode_group_mod(version, &bms[i].gm);
+ request = ofputil_encode_group_mod(version, &bms[i].gm, NULL, -1);
break;
case OFPTYPE_PACKET_OUT:
request = ofputil_encode_packet_out(&bms[i].po, protocol);
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/ofp-group.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/ofp-group.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/ofp-group.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/ofp-group.c 2020-03-11 16:15:44.000000000 +0000
@@ -1043,7 +1043,8 @@
}
ovs_list_push_back(&gm->buckets, &bucket->list_node);
- if (gm->type != OFPGT11_SELECT && bucket->weight) {
+ if (gm->command != OFPGC15_INSERT_BUCKET
+ && gm->type != OFPGT11_SELECT && bucket->weight) {
error = xstrdup("Only select groups can have bucket weights.");
goto out;
}
@@ -1189,7 +1190,7 @@
openflow, ofp_version);
actions_len = openflow->size - actions_start;
- if (group_type == OFPGT11_SELECT) {
+ if (group_type == OFPGT11_SELECT || bucket->weight) {
ofpprop_put_u16(openflow, OFPGBPT15_WEIGHT, bucket->weight);
}
if (bucket->watch_port != OFPP_ANY) {
@@ -1916,9 +1917,68 @@
ofputil_group_properties_destroy(&gm->props);
}
+static void
+bad_group_cmd(enum ofp15_group_mod_command cmd)
+{
+ const char *opt_version;
+ const char *version;
+ const char *cmd_str;
+
+ switch (cmd) {
+ case OFPGC15_ADD:
+ case OFPGC15_MODIFY:
+ case OFPGC15_ADD_OR_MOD:
+ case OFPGC15_DELETE:
+ version = "1.1";
+ opt_version = "11";
+ break;
+
+ case OFPGC15_INSERT_BUCKET:
+ case OFPGC15_REMOVE_BUCKET:
+ version = "1.5";
+ opt_version = "15";
+ break;
+
+ default:
+ OVS_NOT_REACHED();
+ }
+
+ switch (cmd) {
+ case OFPGC15_ADD:
+ cmd_str = "add-group";
+ break;
+
+ case OFPGC15_MODIFY:
+ case OFPGC15_ADD_OR_MOD:
+ cmd_str = "mod-group";
+ break;
+
+ case OFPGC15_DELETE:
+ cmd_str = "del-group";
+ break;
+
+ case OFPGC15_INSERT_BUCKET:
+ cmd_str = "insert-bucket";
+ break;
+
+ case OFPGC15_REMOVE_BUCKET:
+ cmd_str = "remove-bucket";
+ break;
+
+ default:
+ OVS_NOT_REACHED();
+ }
+
+ ovs_fatal(0, "%s needs OpenFlow %s or later (\'-O OpenFlow%s\')",
+ cmd_str, version, opt_version);
+
+}
+
static struct ofpbuf *
ofputil_encode_ofp11_group_mod(enum ofp_version ofp_version,
- const struct ofputil_group_mod *gm)
+ const struct ofputil_group_mod *gm,
+ const struct ovs_list *new_buckets,
+ int group_existed)
{
struct ofpbuf *b;
struct ofp11_group_mod *ogm;
@@ -1929,11 +1989,32 @@
start_ogm = b->size;
ofpbuf_put_zeros(b, sizeof *ogm);
- LIST_FOR_EACH (bucket, list_node, &gm->buckets) {
+ uint16_t command = gm->command;
+ const struct ovs_list *buckets = &gm->buckets;
+ switch (gm->command) {
+ case OFPGC15_INSERT_BUCKET:
+ case OFPGC15_REMOVE_BUCKET:
+ if (!new_buckets) {
+ bad_group_cmd(gm->command);
+ }
+ command = OFPGC11_MODIFY;
+ buckets = new_buckets;
+ break;
+
+ case OFPGC11_ADD_OR_MOD:
+ if (group_existed >= 0) {
+ command = group_existed ? OFPGC11_MODIFY : OFPGC11_ADD;
+ }
+ break;
+
+ default:
+ break;
+ }
+ LIST_FOR_EACH (bucket, list_node, buckets) {
ofputil_put_ofp11_bucket(bucket, b, ofp_version);
}
ogm = ofpbuf_at_assert(b, start_ogm, sizeof *ogm);
- ogm->command = htons(gm->command);
+ ogm->command = htons(command);
ogm->type = gm->type;
ogm->group_id = htonl(gm->group_id);
@@ -1942,7 +2023,8 @@
static struct ofpbuf *
ofputil_encode_ofp15_group_mod(enum ofp_version ofp_version,
- const struct ofputil_group_mod *gm)
+ const struct ofputil_group_mod *gm,
+ int group_existed)
{
struct ofpbuf *b;
struct ofp15_group_mod *ogm;
@@ -1988,7 +2070,9 @@
ofputil_put_ofp15_bucket(bucket, bucket_id, gm->type, b, ofp_version);
}
ogm = ofpbuf_at_assert(b, start_ogm, sizeof *ogm);
- ogm->command = htons(gm->command);
+ ogm->command = htons(gm->command != OFPGC11_ADD_OR_MOD || group_existed < 0
+ ? gm->command
+ : group_existed ? OFPGC11_MODIFY : OFPGC11_ADD);
ogm->type = gm->type;
ogm->group_id = htonl(gm->group_id);
ogm->command_bucket_id = htonl(gm->command_bucket_id);
@@ -2003,68 +2087,24 @@
return b;
}
-static void
-bad_group_cmd(enum ofp15_group_mod_command cmd)
-{
- const char *opt_version;
- const char *version;
- const char *cmd_str;
-
- switch (cmd) {
- case OFPGC15_ADD:
- case OFPGC15_MODIFY:
- case OFPGC15_ADD_OR_MOD:
- case OFPGC15_DELETE:
- version = "1.1";
- opt_version = "11";
- break;
-
- case OFPGC15_INSERT_BUCKET:
- case OFPGC15_REMOVE_BUCKET:
- version = "1.5";
- opt_version = "15";
- break;
-
- default:
- OVS_NOT_REACHED();
- }
-
- switch (cmd) {
- case OFPGC15_ADD:
- cmd_str = "add-group";
- break;
-
- case OFPGC15_MODIFY:
- case OFPGC15_ADD_OR_MOD:
- cmd_str = "mod-group";
- break;
-
- case OFPGC15_DELETE:
- cmd_str = "del-group";
- break;
-
- case OFPGC15_INSERT_BUCKET:
- cmd_str = "insert-bucket";
- break;
-
- case OFPGC15_REMOVE_BUCKET:
- cmd_str = "remove-bucket";
- break;
-
- default:
- OVS_NOT_REACHED();
- }
-
- ovs_fatal(0, "%s needs OpenFlow %s or later (\'-O OpenFlow%s\')",
- cmd_str, version, opt_version);
-
-}
-
/* Converts abstract group mod 'gm' into a message for OpenFlow version
- * 'ofp_version' and returns the message. */
+ * 'ofp_version' and returns the message.
+ *
+ * If 'new_buckets' is nonnull, it should point to the full set of new buckets
+ * that resulted from a OFPGC15_INSERT_BUCKET or OFPGC15_REMOVE_BUCKET command.
+ * It is needed to translate such group_mods into OpenFlow 1.1-1.4
+ * OFPGC11_MODIFY. If it is null but needed for translation, then encoding the
+ * group_mod will print an error on stderr and exit().
+ *
+ * If 'group_existed' is nonnegative, it should specify whether the group
+ * existed before the command was executed. If it is nonnegative, then it is
+ * used to translate OVS's nonstandard OFPGC11_ADD_OR_MOD into a standard
+ * command. If it is negative, then OFPGC11_ADD_OR_MOD will be left as is. */
struct ofpbuf *
ofputil_encode_group_mod(enum ofp_version ofp_version,
- const struct ofputil_group_mod *gm)
+ const struct ofputil_group_mod *gm,
+ const struct ovs_list *new_buckets,
+ int group_existed)
{
switch (ofp_version) {
@@ -2072,15 +2112,13 @@
case OFP12_VERSION:
case OFP13_VERSION:
case OFP14_VERSION:
- if (gm->command > OFPGC11_DELETE && gm->command != OFPGC11_ADD_OR_MOD) {
- bad_group_cmd(gm->command);
- }
- return ofputil_encode_ofp11_group_mod(ofp_version, gm);
+ return ofputil_encode_ofp11_group_mod(ofp_version, gm,
+ new_buckets, group_existed);
case OFP10_VERSION:
case OFP15_VERSION:
case OFP16_VERSION:
- return ofputil_encode_ofp15_group_mod(ofp_version, gm);
+ return ofputil_encode_ofp15_group_mod(ofp_version, gm, group_existed);
default:
OVS_NOT_REACHED();
@@ -2214,7 +2252,8 @@
struct ofputil_bucket *bucket;
LIST_FOR_EACH (bucket, list_node, &gm->buckets) {
- if (bucket->weight && gm->type != OFPGT11_SELECT) {
+ if (bucket->weight && gm->type != OFPGT11_SELECT
+ && gm->command != OFPGC15_INSERT_BUCKET) {
return OFPERR_OFPGMFC_INVALID_GROUP;
}
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/ofp-monitor.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/ofp-monitor.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/ofp-monitor.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/ofp-monitor.c 2020-03-11 16:15:44.000000000 +0000
@@ -796,7 +796,8 @@
switch (rf->reason) {
case OFPRFR_GROUP_MOD:
- inner = ofputil_encode_group_mod(ofp_version, rf->group_mod);
+ inner = ofputil_encode_group_mod(ofp_version, rf->group_mod,
+ rf->new_buckets, rf->group_existed);
break;
case OFPRFR_METER_MOD:
@@ -829,6 +830,9 @@
ofputil_decode_requestforward(const struct ofp_header *outer,
struct ofputil_requestforward *rf)
{
+ rf->new_buckets = NULL;
+ rf->group_existed = -1;
+
struct ofpbuf b = ofpbuf_const_initializer(outer, ntohs(outer->length));
/* Skip past outer message. */
@@ -920,6 +924,7 @@
case OFPRFR_GROUP_MOD:
ofputil_uninit_group_mod(rf->group_mod);
free(rf->group_mod);
+ /* 'rf' does not own rf->new_buckets. */
break;
case OFPRFR_METER_MOD:
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/ofp-packet.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/ofp-packet.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/ofp-packet.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/ofp-packet.c 2020-03-11 16:15:44.000000000 +0000
@@ -160,6 +160,7 @@
error = oxm_decode_match(payload.msg, ofpbuf_msgsize(&payload),
loose, tun_table, vl_mff_map,
&pin->flow_metadata);
+ pin->flow_metadata.flow.tunnel.metadata.tab = tun_table;
break;
case NXPINT_USERDATA:
@@ -244,6 +245,7 @@
: NULL);
enum ofperr error = oxm_pull_match_loose(&b, false, tun_table,
&pin->flow_metadata);
+ pin->flow_metadata.flow.tunnel.metadata.tab = tun_table;
if (error) {
return error;
}
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/ofp-port.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/ofp-port.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/ofp-port.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/ofp-port.c 2020-03-11 16:15:44.000000000 +0000
@@ -1698,6 +1698,7 @@
error = ofpprop_pull(&properties, &payload, &type);
if (error) {
+ netdev_free_custom_stats_counters(&ops->custom_stats);
return error;
}
switch (type) {
@@ -1720,6 +1721,7 @@
}
if (error) {
+ netdev_free_custom_stats_counters(&ops->custom_stats);
return error;
}
}
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/ovsdb-data.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/ovsdb-data.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/ovsdb-data.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/ovsdb-data.c 2020-03-11 16:15:44.000000000 +0000
@@ -1234,9 +1234,16 @@
n = inner->array.n;
if (n < type->n_min || n > type->n_max) {
- return ovsdb_syntax_error(json, NULL, "%s must have %u to "
- "%u members but %"PRIuSIZE" are present",
- class, type->n_min, type->n_max, n);
+ if (type->n_min == 1 && type->n_max == 1) {
+ return ovsdb_syntax_error(json, NULL, "%s must have exactly "
+ "one member but %"PRIuSIZE" "
+ "are present", class, n);
+ } else {
+ return ovsdb_syntax_error(json, NULL, "%s must have %u to "
+ "%u members but %"PRIuSIZE" are "
+ "present",
+ class, type->n_min, type->n_max, n);
+ }
}
datum->n = 0;
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/ovsdb-idl.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/ovsdb-idl.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/ovsdb-idl.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/ovsdb-idl.c 2020-03-11 16:15:44.000000000 +0000
@@ -3806,6 +3806,13 @@
goto coverage_out;
}
+ /* If we're still connecting or re-connecting, don't bother sending a
+ * transaction. */
+ if (txn->db->idl->state != IDL_S_MONITORING) {
+ txn->status = TXN_TRY_AGAIN;
+ goto disassemble_out;
+ }
+
/* If we need a lock but don't have it, give up quickly. */
if (txn->db->lock_name && !txn->db->has_lock) {
txn->status = TXN_NOT_LOCKED;
@@ -4617,6 +4624,10 @@
if (error->type == JSON_STRING) {
if (!strcmp(error->string, "timed out")) {
soft_errors++;
+ } else if (!strcmp(error->string,
+ "unknown database")) {
+ ovsdb_idl_retry(db->idl);
+ soft_errors++;
} else if (!strcmp(error->string, "not owner")) {
lock_errors++;
} else if (!strcmp(error->string, "not allowed")) {
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/ovsdb-types.h openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/ovsdb-types.h
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/ovsdb-types.h 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/ovsdb-types.h 2020-03-11 16:15:44.000000000 +0000
@@ -53,6 +53,27 @@
OVSDB_REF_WEAK /* Delete reference if target disappears. */
};
+struct ovsdb_integer_constraints {
+ int64_t min; /* minInteger or INT64_MIN. */
+ int64_t max; /* maxInteger or INT64_MAX. */
+};
+
+struct ovsdb_real_constraints {
+ double min; /* minReal or -DBL_MAX. */
+ double max; /* minReal or DBL_MAX. */
+};
+
+struct ovsdb_string_constraints {
+ unsigned int minLen; /* minLength or 0. */
+ unsigned int maxLen; /* maxLength or UINT_MAX. */
+};
+
+struct ovsdb_uuid_constraints {
+ char *refTableName; /* Name of referenced table, or NULL. */
+ struct ovsdb_table *refTable; /* Referenced table, if available. */
+ enum ovsdb_ref_type refType; /* Reference type. */
+};
+
struct ovsdb_base_type {
enum ovsdb_atomic_type type;
@@ -61,28 +82,11 @@
struct ovsdb_datum *enum_;
union {
- struct ovsdb_integer_constraints {
- int64_t min; /* minInteger or INT64_MIN. */
- int64_t max; /* maxInteger or INT64_MAX. */
- } integer;
-
- struct ovsdb_real_constraints {
- double min; /* minReal or -DBL_MAX. */
- double max; /* minReal or DBL_MAX. */
- } real;
-
+ struct ovsdb_integer_constraints integer;
+ struct ovsdb_real_constraints real;
/* No constraints for Boolean types. */
-
- struct ovsdb_string_constraints {
- unsigned int minLen; /* minLength or 0. */
- unsigned int maxLen; /* maxLength or UINT_MAX. */
- } string;
-
- struct ovsdb_uuid_constraints {
- char *refTableName; /* Name of referenced table, or NULL. */
- struct ovsdb_table *refTable; /* Referenced table, if available. */
- enum ovsdb_ref_type refType; /* Reference type. */
- } uuid;
+ struct ovsdb_string_constraints string;
+ struct ovsdb_uuid_constraints uuid;
};
};
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/packets.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/packets.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/packets.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/packets.c 2020-03-11 16:15:44.000000000 +0000
@@ -1613,7 +1613,6 @@
struct ip6_hdr *nh = dp_packet_l3(b);
nh->ip6_plen = htons(prev_l4_size + ND_PREFIX_OPT_LEN);
- struct ovs_ra_msg *ra = dp_packet_l4(b);
struct ovs_nd_prefix_opt *prefix_opt =
dp_packet_put_uninit(b, sizeof *prefix_opt);
prefix_opt->type = ND_OPT_PREFIX_INFORMATION;
@@ -1625,6 +1624,7 @@
put_16aligned_be32(&prefix_opt->reserved, 0);
memcpy(prefix_opt->prefix.be32, prefix.be32, sizeof(ovs_be32[4]));
+ struct ovs_ra_msg *ra = dp_packet_l4(b);
ra->icmph.icmp6_cksum = 0;
uint32_t icmp_csum = packet_csum_pseudoheader6(dp_packet_l3(b));
ra->icmph.icmp6_cksum = csum_finish(csum_continue(
@@ -1662,7 +1662,7 @@
/* Calculate the IPv6 upper layer checksum according to RFC2460. We pass the
ip6_nxt and ip6_plen values, so it will also work if extension headers
are present. */
-uint16_t
+ovs_be16
packet_csum_upperlayer6(const struct ovs_16aligned_ip6_hdr *ip6,
const void *data, uint8_t l4_protocol,
uint16_t l4_size)
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/packets.h openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/packets.h
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/packets.h 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/packets.h 2020-03-11 16:15:44.000000000 +0000
@@ -744,6 +744,9 @@
};
BUILD_ASSERT_DECL(ICMP_HEADER_LEN == sizeof(struct icmp_header));
+/* ICMPV4 */
+#define ICMP_ERROR_DATA_L4_LEN 8
+
#define IGMP_HEADER_LEN 8
struct igmp_header {
uint8_t igmp_type;
@@ -951,7 +954,7 @@
BUILD_ASSERT_DECL(ICMP6_ERROR_HEADER_LEN == sizeof(struct icmp6_error_header));
uint32_t packet_csum_pseudoheader6(const struct ovs_16aligned_ip6_hdr *);
-uint16_t packet_csum_upperlayer6(const struct ovs_16aligned_ip6_hdr *,
+ovs_be16 packet_csum_upperlayer6(const struct ovs_16aligned_ip6_hdr *,
const void *, uint8_t, uint16_t);
/* Neighbor Discovery option field.
@@ -978,9 +981,6 @@
};
BUILD_ASSERT_DECL(ND_PREFIX_OPT_LEN == sizeof(struct ovs_nd_prefix_opt));
-#define ND_PREFIX_ON_LINK 0x80
-#define ND_PREFIX_AUTONOMOUS_ADDRESS 0x40
-
/* Neighbor Discovery option: MTU. */
#define ND_MTU_OPT_LEN 8
#define ND_MTU_DEFAULT 0
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/rconn.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/rconn.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/rconn.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/rconn.c 2020-03-11 16:15:44.000000000 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Nicira, Inc.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2019 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -502,7 +502,7 @@
timeout_CONNECTING(const struct rconn *rc)
OVS_REQUIRES(rc->mutex)
{
- return MAX(1, rc->backoff);
+ return MAX(2, rc->backoff);
}
static void
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/reconnect.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/reconnect.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/reconnect.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/reconnect.c 2020-03-11 16:15:44.000000000 +0000
@@ -495,7 +495,7 @@
void
reconnect_activity(struct reconnect *fsm, long long int now)
{
- if (fsm->state != S_ACTIVE) {
+ if (fsm->state == S_IDLE) {
reconnect_transition__(fsm, now, S_ACTIVE);
}
fsm->last_activity = now;
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/socket-util.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/socket-util.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/socket-util.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/socket-util.c 2020-03-11 16:15:44.000000000 +0000
@@ -285,7 +285,7 @@
}
#endif
if (retval == 1) {
- if (pfd.revents & POLLERR) {
+ if (pfd.revents & (POLLERR | POLLHUP)) {
ssize_t n = send(fd, "", 1, 0);
if (n < 0) {
return sock_errno();
@@ -518,12 +518,13 @@
* is optional and defaults to 'default_port' (use 0 to make the kernel choose
* an available port, although this isn't usually appropriate for active
* connections). If 'default_port' is negative, then is required.
+ * It resolves the host if 'resolve_host' is true.
*
* On success, returns true and stores the parsed remote address into '*ss'.
* On failure, logs an error, stores zeros into '*ss', and returns false. */
bool
inet_parse_active(const char *target_, int default_port,
- struct sockaddr_storage *ss)
+ struct sockaddr_storage *ss, bool resolve_host)
{
char *target = xstrdup(target_);
char *port, *host;
@@ -538,7 +539,7 @@
ok = false;
} else {
ok = parse_sockaddr_components(ss, host, port, default_port,
- target_, true);
+ target_, resolve_host);
}
if (!ok) {
memset(ss, 0, sizeof *ss);
@@ -575,7 +576,7 @@
int error;
/* Parse. */
- if (!inet_parse_active(target, default_port, &ss)) {
+ if (!inet_parse_active(target, default_port, &ss, true)) {
error = EAFNOSUPPORT;
goto exit;
}
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/socket-util.h openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/socket-util.h
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/socket-util.h 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/socket-util.h 2020-03-11 16:15:44.000000000 +0000
@@ -49,7 +49,7 @@
void inet_parse_host_port_tokens(char *s, char **hostp, char **portp);
void inet_parse_port_host_tokens(char *s, char **portp, char **hostp);
bool inet_parse_active(const char *target, int default_port,
- struct sockaddr_storage *ssp);
+ struct sockaddr_storage *ssp, bool resolve_host);
int inet_open_active(int style, const char *target, int default_port,
struct sockaddr_storage *ssp, int *fdp, uint8_t dscp);
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/stopwatch.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/stopwatch.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/stopwatch.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/stopwatch.c 2020-03-11 16:15:44.000000000 +0000
@@ -450,6 +450,7 @@
should_exit = true;
break;
}
+ free(pkt);
}
ovs_mutex_unlock(&stopwatches_lock);
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/stream.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/stream.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/stream.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/stream.c 2020-03-11 16:15:44.000000000 +0000
@@ -751,7 +751,7 @@
struct sockaddr_storage *ss)
{
return ((!strncmp(target, "tcp:", 4) || !strncmp(target, "ssl:", 4))
- && inet_parse_active(target + 4, default_port, ss));
+ && inet_parse_active(target + 4, default_port, ss, true));
}
/* Attempts to guess the content type of a stream whose first few bytes were
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/stream-ssl.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/stream-ssl.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/stream-ssl.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/stream-ssl.c 2020-03-11 16:15:44.000000000 +0000
@@ -425,6 +425,7 @@
static char *
get_peer_common_name(const struct ssl_stream *sslv)
{
+ char *peer_name = NULL;
X509 *peer_cert = SSL_get_peer_certificate(sslv->ssl);
if (!peer_cert) {
return NULL;
@@ -433,18 +434,18 @@
int cn_index = X509_NAME_get_index_by_NID(X509_get_subject_name(peer_cert),
NID_commonName, -1);
if (cn_index < 0) {
- return NULL;
+ goto error;
}
X509_NAME_ENTRY *cn_entry = X509_NAME_get_entry(
X509_get_subject_name(peer_cert), cn_index);
if (!cn_entry) {
- return NULL;
+ goto error;
}
ASN1_STRING *cn_data = X509_NAME_ENTRY_get_data(cn_entry);
if (!cn_data) {
- return NULL;
+ goto error;
}
const char *cn;
@@ -454,7 +455,11 @@
#else
cn = (const char *)ASN1_STRING_get0_data(cn_data);
#endif
- return xstrdup(cn);
+ peer_name = xstrdup(cn);
+
+error:
+ X509_free(peer_cert);
+ return peer_name;
}
static int
@@ -1157,7 +1162,7 @@
const char *certificate_file)
{
if (update_ssl_config(&private_key, private_key_file)
- || update_ssl_config(&certificate, certificate_file)) {
+ && update_ssl_config(&certificate, certificate_file)) {
stream_ssl_set_certificate_file__(certificate_file);
stream_ssl_set_private_key_file__(private_key_file);
}
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/table.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/table.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/table.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/table.c 2020-03-11 16:15:44.000000000 +0000
@@ -236,15 +236,18 @@
}
}
+static bool first_table = true;
+
static void
table_print_table__(const struct table *table, const struct table_style *style,
struct ds *s)
{
- static int n = 0;
int *widths;
size_t x, y;
- if (n++ > 0) {
+ if (first_table) {
+ first_table = false;
+ } else {
ds_put_char(s, '\n');
}
@@ -318,10 +321,11 @@
table_print_list__(const struct table *table, const struct table_style *style,
struct ds *s)
{
- static int n = 0;
size_t x, y;
- if (n++ > 0) {
+ if (first_table) {
+ first_table = false;
+ } else {
ds_put_char(s, '\n');
}
@@ -469,10 +473,11 @@
table_print_csv__(const struct table *table, const struct table_style *style,
struct ds *s)
{
- static int n = 0;
size_t x, y;
- if (n++ > 0) {
+ if (first_table) {
+ first_table = false;
+ } else {
ds_put_char(s, '\n');
}
@@ -614,6 +619,12 @@
}
}
+void
+table_format_reset(void)
+{
+ first_table = true;
+}
+
/* Outputs 'table' on stdout in the specified 'style'. */
void
table_print(const struct table *table, const struct table_style *style)
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/table.h openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/table.h
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/table.h 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/table.h 2020-03-11 16:15:44.000000000 +0000
@@ -133,6 +133,7 @@
void table_print(const struct table *, const struct table_style *);
void table_format(const struct table *, const struct table_style *,
struct ds *);
+void table_format_reset(void);
void table_usage(void);
#endif /* table.h */
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/tc.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/tc.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/tc.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/tc.c 2020-03-11 16:15:44.000000000 +0000
@@ -346,10 +346,12 @@
if (attrs[TCA_FLOWER_KEY_VLAN_ID]) {
flower->key.vlan_id =
nl_attr_get_u16(attrs[TCA_FLOWER_KEY_VLAN_ID]);
+ flower->mask.vlan_id = 0xffff;
}
if (attrs[TCA_FLOWER_KEY_VLAN_PRIO]) {
flower->key.vlan_prio =
nl_attr_get_u8(attrs[TCA_FLOWER_KEY_VLAN_PRIO]);
+ flower->mask.vlan_prio = 0xff;
}
}
@@ -932,7 +934,7 @@
nl_parse_flower_actions(struct nlattr **attrs, struct tc_flower *flower)
{
const struct nlattr *actions = attrs[TCA_FLOWER_ACT];
- static struct nl_policy actions_orders_policy[TCA_ACT_MAX_PRIO + 1] = {};
+ static struct nl_policy actions_orders_policy[TCA_ACT_MAX_NUM + 1] = {};
struct nlattr *actions_orders[ARRAY_SIZE(actions_orders_policy)];
const int max_size = ARRAY_SIZE(actions_orders_policy);
@@ -951,8 +953,8 @@
if (actions_orders[i]) {
int err;
- if (flower->action_count >= TCA_ACT_MAX_PRIO) {
- VLOG_DBG_RL(&error_rl, "Can only support %d actions", flower->action_count);
+ if (flower->action_count >= TCA_ACT_MAX_NUM) {
+ VLOG_DBG_RL(&error_rl, "Can only support %d actions", TCA_ACT_MAX_NUM);
return EOPNOTSUPP;
}
err = nl_parse_single_action(actions_orders[i], flower);
@@ -1637,9 +1639,11 @@
nl_msg_put_be16(request, TCA_FLOWER_KEY_ETH_TYPE, flower->key.eth_type);
if (is_vlan) {
- if (flower->key.vlan_id || flower->key.vlan_prio) {
+ if (flower->key.vlan_id) {
nl_msg_put_u16(request, TCA_FLOWER_KEY_VLAN_ID,
flower->key.vlan_id);
+ }
+ if (flower->key.vlan_prio) {
nl_msg_put_u8(request, TCA_FLOWER_KEY_VLAN_PRIO,
flower->key.vlan_prio);
}
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/tc.h openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/tc.h
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/tc.h 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/tc.h 2020-03-11 16:15:44.000000000 +0000
@@ -148,6 +148,8 @@
TC_OFFLOADED_STATE_NOT_IN_HW,
};
+#define TCA_ACT_MAX_NUM 16
+
struct tc_flower {
uint32_t handle;
uint32_t prio;
@@ -156,7 +158,7 @@
struct tc_flower_key mask;
int action_count;
- struct tc_action actions[TCA_ACT_MAX_PRIO];
+ struct tc_action actions[TCA_ACT_MAX_NUM];
struct ovs_flow_stats stats;
uint64_t lastused;
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/wmi.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/wmi.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/lib/wmi.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/lib/wmi.c 2020-03-11 16:15:44.000000000 +0000
@@ -686,7 +686,7 @@
/* Check if the element already exists on the switch. */
wchar_t internal_port_query[WMI_QUERY_COUNT] = L"SELECT * FROM "
- L"Msvm_InternalEthernetPort WHERE ElementName = \"";
+ L"CIM_EthernetPort WHERE ElementName = \"";
wide_name = xmalloc((strlen(name) + 1) * sizeof(wchar_t));
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/NEWS openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/NEWS
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/NEWS 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/NEWS 2020-03-11 16:15:44.000000000 +0000
@@ -1,6 +1,23 @@
-v2.10.1 - xx xxx xxxx
+v2.10.5 - xx xxx xxxx
---------------------
+ - DPDK
+ * OVS validated with DPDK 17.11.6 which is recommended to be used.
+v2.10.4 - 06 Sep 2019
+---------------------
+ - Fix compilation issue with Ubuntu kernel 4.15.60.
+
+v2.10.3 - 03 Sep 2019
+---------------------
+ - Bug fixes
+
+v2.10.2 - 30 Mar 2019
+---------------------
+ - Bug fixes
+
+v2.10.1 - 19 Oct 2018
+---------------------
+ - Bug fixes
v2.10.0 - 18 Aug 2018
---------------------
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ofproto/bond.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ofproto/bond.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ofproto/bond.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ofproto/bond.c 2020-03-11 16:15:44.000000000 +0000
@@ -186,6 +186,7 @@
uint16_t vlan)
OVS_REQ_RDLOCK(rwlock);
static void update_recirc_rules__(struct bond *bond);
+static bool bond_is_falling_back_to_ab(const struct bond *);
/* Attempts to parse 's' as the name of a bond balancing mode. If successful,
* stores the mode in '*balance' and returns true. Otherwise returns false
@@ -648,6 +649,13 @@
if (bond->lacp_status != lacp_status) {
bond->lacp_status = lacp_status;
bond->bond_revalidate = true;
+
+ /* Change in LACP status can affect whether the bond is falling back to
+ * active-backup. Make sure to create or destroy buckets if
+ * necessary. */
+ if (bond_is_falling_back_to_ab(bond) || !bond->hash) {
+ bond_entry_reset(bond);
+ }
}
/* Enable slaves based on link status and LACP feedback. */
@@ -756,6 +764,15 @@
return packet;
}
+
+static bool
+bond_is_falling_back_to_ab(const struct bond *bond)
+{
+ return (bond->lacp_fallback_ab
+ && (bond->balance == BM_SLB || bond->balance == BM_TCP)
+ && bond->lacp_status == LACP_CONFIGURED);
+}
+
/* Checks whether a packet that arrived on 'slave_' within 'bond', with an
* Ethernet destination address of 'eth_dst', should be admitted.
*
@@ -927,7 +944,8 @@
static bool
bond_may_recirc(const struct bond *bond)
{
- return bond->balance == BM_TCP && bond->recirc_id;
+ return (bond->balance == BM_TCP && bond->recirc_id
+ && !bond_is_falling_back_to_ab(bond));
}
static void
@@ -986,7 +1004,8 @@
bond_is_balanced(const struct bond *bond) OVS_REQ_RDLOCK(rwlock)
{
return bond->rebalance_interval
- && (bond->balance == BM_SLB || bond->balance == BM_TCP);
+ && (bond->balance == BM_SLB || bond->balance == BM_TCP)
+ && !(bond->lacp_fallback_ab && bond->lacp_status == LACP_CONFIGURED);
}
/* Notifies 'bond' that 'n_bytes' bytes were sent in 'flow' within 'vlan'. */
@@ -1645,7 +1664,7 @@
static void
bond_entry_reset(struct bond *bond)
{
- if (bond->balance != BM_AB) {
+ if (bond->balance != BM_AB && !bond_is_falling_back_to_ab(bond)) {
size_t hash_len = BOND_BUCKETS * sizeof *bond->hash;
if (!bond->hash) {
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ofproto/connmgr.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ofproto/connmgr.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ofproto/connmgr.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ofproto/connmgr.c 2020-03-11 16:15:44.000000000 +0000
@@ -1538,6 +1538,10 @@
ovs_assert(reason < 32);
ovs_assert((unsigned int) type < OAM_N_TYPES);
+ if (!rconn_is_connected(ofconn->rconn)) {
+ return false;
+ }
+
/* Keep the following code in sync with the documentation in the
* "Asynchronous Messages" section in 'topics/design' */
@@ -1965,7 +1969,7 @@
struct ofpbuf ofpacts;
struct match match;
- ofpbuf_init(&ofpacts, OFPACT_OUTPUT_SIZE);
+ ofpbuf_init(&ofpacts, sizeof(struct ofpact_output));
ofpact_put_OUTPUT(&ofpacts)->port = OFPP_NORMAL;
match_init_catchall(&match);
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ofproto/fail-open.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ofproto/fail-open.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ofproto/fail-open.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ofproto/fail-open.c 2020-03-11 16:15:44.000000000 +0000
@@ -163,7 +163,7 @@
/* Set up a flow that matches every packet and directs them to
* OFPP_NORMAL. */
- ofpbuf_init(&ofpacts, OFPACT_OUTPUT_SIZE);
+ ofpbuf_init(&ofpacts, sizeof(struct ofpact_output));
ofpact_put_OUTPUT(&ofpacts)->port = OFPP_NORMAL;
match_init_catchall(&match);
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ofproto/ofproto.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ofproto/ofproto.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ofproto/ofproto.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ofproto/ofproto.c 2020-03-11 16:15:44.000000000 +0000
@@ -2492,6 +2492,9 @@
{
struct ofport *port = ofproto_get_port(ofproto, ofp_port);
if (port) {
+ if (port->ofproto->ofproto_class->set_lldp) {
+ port->ofproto->ofproto_class->set_lldp(port, NULL);
+ }
if (port->ofproto->ofproto_class->set_stp_port) {
port->ofproto->ofproto_class->set_stp_port(port, NULL);
}
@@ -3548,9 +3551,20 @@
}
static void
+ofproto_packet_out_prepare(struct ofproto *ofproto,
+ struct ofproto_packet_out *opo)
+ OVS_REQUIRES(ofproto_mutex)
+{
+ ofproto->ofproto_class->packet_execute_prepare(ofproto, opo);
+}
+
+/* Execution of packet_out action in datapath could end up in upcall with
+ * subsequent flow translations and possible rule modifications.
+ * So, the caller should not hold 'ofproto_mutex'. */
+static void
ofproto_packet_out_finish(struct ofproto *ofproto,
struct ofproto_packet_out *opo)
- OVS_REQUIRES(ofproto_mutex)
+ OVS_EXCLUDED(ofproto_mutex)
{
ofproto->ofproto_class->packet_execute(ofproto, opo);
}
@@ -3593,10 +3607,13 @@
opo.version = p->tables_version;
error = ofproto_packet_out_start(p, &opo);
if (!error) {
- ofproto_packet_out_finish(p, &opo);
+ ofproto_packet_out_prepare(p, &opo);
}
ovs_mutex_unlock(&ofproto_mutex);
+ if (!error) {
+ ofproto_packet_out_finish(p, &opo);
+ }
ofproto_packet_out_uninit(&opo);
return error;
}
@@ -7192,6 +7209,8 @@
*CONST_CAST(long long int *, &(new_group->created)) = old_group->created;
*CONST_CAST(long long int *, &(new_group->modified)) = time_msec();
+ *CONST_CAST(uint32_t *, &(new_group->n_buckets)) =
+ ovs_list_size(&(new_group->buckets));
group_collection_add(&ogm->old_groups, old_group);
/* Mark the old group for deletion. */
@@ -7391,6 +7410,8 @@
rf.xid = req->request->xid;
rf.reason = OFPRFR_GROUP_MOD;
rf.group_mod = &ogm->gm;
+ rf.new_buckets = new_group ? &new_group->buckets : NULL;
+ rf.group_existed = group_collection_n(&ogm->old_groups) > 0;
connmgr_send_requestforward(ofproto->connmgr, req->ofconn, &rf);
}
}
@@ -7875,7 +7896,7 @@
} else if (be->type == OFPTYPE_GROUP_MOD) {
ofproto_group_mod_finish(ofproto, &be->ogm, &req);
} else if (be->type == OFPTYPE_PACKET_OUT) {
- ofproto_packet_out_finish(ofproto, &be->opo);
+ ofproto_packet_out_prepare(ofproto, &be->opo);
}
}
}
@@ -7885,6 +7906,13 @@
ovs_mutex_unlock(&ofproto_mutex);
}
+ /* Executing remaining datapath actions. */
+ LIST_FOR_EACH (be, node, &bundle->msg_list) {
+ if (be->type == OFPTYPE_PACKET_OUT) {
+ ofproto_packet_out_finish(ofproto, &be->opo);
+ }
+ }
+
/* The bundle is discarded regardless the outcome. */
ofp_bundle_remove__(ofconn, bundle);
return error;
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ofproto/ofproto-dpif.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ofproto/ofproto-dpif.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ofproto/ofproto-dpif.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ofproto/ofproto-dpif.c 2020-03-11 16:15:44.000000000 +0000
@@ -2239,24 +2239,24 @@
const struct smap *cfg)
{
struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
+ struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport->up.ofproto);
int error = 0;
if (cfg) {
if (!ofport->lldp) {
- struct ofproto_dpif *ofproto;
-
- ofproto = ofproto_dpif_cast(ofport->up.ofproto);
ofproto->backer->need_revalidate = REV_RECONFIGURE;
ofport->lldp = lldp_create(ofport->up.netdev, ofport_->mtu, cfg);
}
if (!lldp_configure(ofport->lldp, cfg)) {
+ lldp_unref(ofport->lldp);
+ ofport->lldp = NULL;
error = EINVAL;
}
- }
- if (error) {
+ } else if (ofport->lldp) {
lldp_unref(ofport->lldp);
ofport->lldp = NULL;
+ ofproto->backer->need_revalidate = REV_RECONFIGURE;
}
ofproto_dpif_monitor_port_update(ofport,
@@ -3684,10 +3684,11 @@
}
dp_port_name = netdev_vport_get_dpif_port(netdev, namebuf, sizeof namebuf);
+ if (!dpif_port_exists(ofproto->backer->dpif, dp_port_name)) {
+ odp_port_t port_no = ODPP_NONE;
+ int error;
- odp_port_t port_no = ODPP_NONE;
- int error = dpif_port_add(ofproto->backer->dpif, netdev, &port_no);
- if (error != EEXIST && error != EBUSY) {
+ error = dpif_port_add(ofproto->backer->dpif, netdev, &port_no);
if (error) {
return error;
}
@@ -4676,12 +4677,13 @@
}
static void
-packet_execute(struct ofproto *ofproto_, struct ofproto_packet_out *opo)
+packet_execute_prepare(struct ofproto *ofproto_,
+ struct ofproto_packet_out *opo)
OVS_REQUIRES(ofproto_mutex)
{
struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
struct dpif_flow_stats stats;
- struct dpif_execute execute;
+ struct dpif_execute *execute;
struct ofproto_dpif_packet_out *aux = opo->aux;
ovs_assert(aux);
@@ -4690,22 +4692,40 @@
dpif_flow_stats_extract(opo->flow, opo->packet, time_msec(), &stats);
ofproto_dpif_xcache_execute(ofproto, &aux->xcache, &stats);
- execute.actions = aux->odp_actions.data;
- execute.actions_len = aux->odp_actions.size;
+ execute = xzalloc(sizeof *execute);
+ execute->actions = xmemdup(aux->odp_actions.data, aux->odp_actions.size);
+ execute->actions_len = aux->odp_actions.size;
pkt_metadata_from_flow(&opo->packet->md, opo->flow);
- execute.packet = opo->packet;
- execute.flow = opo->flow;
- execute.needs_help = aux->needs_help;
- execute.probe = false;
- execute.mtu = 0;
+ execute->packet = opo->packet;
+ execute->flow = opo->flow;
+ execute->needs_help = aux->needs_help;
+ execute->probe = false;
+ execute->mtu = 0;
/* Fix up in_port. */
ofproto_dpif_set_packet_odp_port(ofproto, opo->flow->in_port.ofp_port,
opo->packet);
- dpif_execute(ofproto->backer->dpif, &execute);
ofproto_dpif_packet_out_delete(aux);
+ opo->aux = execute;
+}
+
+static void
+packet_execute(struct ofproto *ofproto_, struct ofproto_packet_out *opo)
+ OVS_EXCLUDED(ofproto_mutex)
+{
+ struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
+ struct dpif_execute *execute = opo->aux;
+
+ if (!execute) {
+ return;
+ }
+
+ dpif_execute(ofproto->backer->dpif, execute);
+
+ free(CONST_CAST(struct nlattr *, execute->actions));
+ free(execute);
opo->aux = NULL;
}
@@ -5051,18 +5071,29 @@
const struct ofputil_packet_in_private *pin)
{
struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
+ struct dpif_flow_stats stats;
+ struct xlate_cache xcache;
+ struct flow flow;
+ xlate_cache_init(&xcache);
/* Translate pin into datapath actions. */
uint64_t odp_actions_stub[1024 / 8];
struct ofpbuf odp_actions = OFPBUF_STUB_INITIALIZER(odp_actions_stub);
enum slow_path_reason slow;
- enum ofperr error = xlate_resume(ofproto, pin, &odp_actions, &slow);
+ enum ofperr error = xlate_resume(ofproto, pin, &odp_actions, &slow,
+ &flow, &xcache);
/* Steal 'pin->packet' and put it into a dp_packet. */
struct dp_packet packet;
dp_packet_init(&packet, pin->base.packet_len);
dp_packet_put(&packet, pin->base.packet, pin->base.packet_len);
+ /* Run the side effects from the xcache. */
+ dpif_flow_stats_extract(&flow, &packet, time_msec(), &stats);
+ ovs_mutex_lock(&ofproto_mutex);
+ ofproto_dpif_xcache_execute(ofproto, &xcache, &stats);
+ ovs_mutex_unlock(&ofproto_mutex);
+
pkt_metadata_from_flow(&packet.md, &pin->base.flow_metadata.flow);
/* Fix up in_port. */
@@ -5951,11 +5982,11 @@
/* Provider ID unknown. Use backer to allocate a new DP meter */
if (meter_id->uint32 == UINT32_MAX) {
if (!ofproto->backer->meter_ids) {
- return EFBIG; /* Datapath does not support meter. */
+ return OFPERR_OFPMMFC_OUT_OF_METERS; /* Meters not supported. */
}
if(!id_pool_alloc_id(ofproto->backer->meter_ids, &meter_id->uint32)) {
- return ENOMEM; /* Can't allocate a DP meter. */
+ return OFPERR_OFPMMFC_OUT_OF_METERS; /* Can't allocate meter. */
}
}
@@ -6069,6 +6100,7 @@
rule_get_stats,
packet_xlate,
packet_xlate_revert,
+ packet_execute_prepare,
packet_execute,
set_frag_handling,
nxt_resume,
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ofproto/ofproto-dpif-sflow.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ofproto/ofproto-dpif-sflow.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ofproto/ofproto-dpif-sflow.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ofproto/ofproto-dpif-sflow.c 2020-03-11 16:15:44.000000000 +0000
@@ -468,15 +468,16 @@
const char *target;
SSET_FOR_EACH (target, targets) {
struct sockaddr_storage ss;
- if (inet_parse_active(target, SFL_DEFAULT_COLLECTOR_PORT, &ss)) {
+ if (inet_parse_active(target, SFL_DEFAULT_COLLECTOR_PORT, &ss, true)) {
/* sFlow only supports target in default routing table with
* packet mark zero.
*/
- ip = ss_get_address(&ss);
+ struct in6_addr target_ip = ss_get_address(&ss);
struct in6_addr gw, src = in6addr_any;
char name[IFNAMSIZ];
- if (ovs_router_lookup(0, &ip, name, &src, &gw)) {
+ if (ovs_router_lookup(0, &target_ip, name, &src, &gw)) {
+ ip = src;
goto success;
}
}
@@ -1025,7 +1026,7 @@
sflow_actions->tunnel.ip_tos = key->ipv4_tos;
}
if (key->ipv4_ttl) {
- sflow_actions->tunnel.ip_tos = key->ipv4_ttl;
+ sflow_actions->tunnel.ip_ttl = key->ipv4_ttl;
}
}
break;
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ofproto/ofproto-dpif-trace.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ofproto/ofproto-dpif-trace.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ofproto/ofproto-dpif-trace.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ofproto/ofproto-dpif-trace.c 2020-03-11 16:15:44.000000000 +0000
@@ -675,7 +675,7 @@
ds_put_format(output, "\nrecirc(%#"PRIx32")",
recirc_node->recirc_id);
- if (recirc_node->type == OFT_RECIRC_CONNTRACK) {
+ if (next_ct_states && recirc_node->type == OFT_RECIRC_CONNTRACK) {
uint32_t ct_state;
if (ovs_list_is_empty(next_ct_states)) {
ct_state = CS_TRACKED | CS_NEW;
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ofproto/ofproto-dpif-upcall.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ofproto/ofproto-dpif-upcall.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ofproto/ofproto-dpif-upcall.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ofproto/ofproto-dpif-upcall.c 2020-03-11 16:15:44.000000000 +0000
@@ -1021,7 +1021,6 @@
* initialized with at least 128 bytes of space. */
static void
compose_slow_path(struct udpif *udpif, struct xlate_out *xout,
- const struct flow *flow,
odp_port_t odp_in_port, ofp_port_t ofp_in_port,
struct ofpbuf *buf, uint32_t meter_id,
struct uuid *ofproto_uuid)
@@ -1030,6 +1029,7 @@
odp_port_t port;
uint32_t pid;
+ memset(&cookie, 0, sizeof cookie);
cookie.type = USER_ACTION_COOKIE_SLOW_PATH;
cookie.ofp_in_port = ofp_in_port;
cookie.ofproto_uuid = *ofproto_uuid;
@@ -1038,7 +1038,7 @@
port = xout->slow & (SLOW_CFM | SLOW_BFD | SLOW_LACP | SLOW_STP)
? ODPP_NONE
: odp_in_port;
- pid = dpif_port_get_pid(udpif->dpif, port, flow_hash_5tuple(flow, 0));
+ pid = dpif_port_get_pid(udpif->dpif, port);
size_t offset;
size_t ac_offset;
@@ -1196,7 +1196,7 @@
odp_actions->data, odp_actions->size);
} else {
/* upcall->put_actions already initialized by upcall_receive(). */
- compose_slow_path(udpif, &upcall->xout, upcall->flow,
+ compose_slow_path(udpif, &upcall->xout,
upcall->flow->in_port.odp_port, upcall->ofp_in_port,
&upcall->put_actions,
upcall->ofproto->up.slowpath_meter_id,
@@ -1757,7 +1757,7 @@
}
reval_seq = seq_read(udpif->reval_seq) - 1; /* Ensure revalidation. */
- ofpbuf_use_const(&actions, &flow->actions, flow->actions_len);
+ ofpbuf_use_const(&actions, flow->actions, flow->actions_len);
*ukey = ukey_create__(flow->key, flow->key_len,
flow->mask, flow->mask_len, flow->ufid_present,
&flow->ufid, flow->pmd_id, &actions,
@@ -2155,7 +2155,7 @@
goto exit;
}
- compose_slow_path(udpif, xoutp, &ctx.flow, ctx.flow.in_port.odp_port,
+ compose_slow_path(udpif, xoutp, ctx.flow.in_port.odp_port,
ofp_in_port, odp_actions,
ofproto->up.slowpath_meter_id, &ofproto->uuid);
}
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ofproto/ofproto-dpif-xlate.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ofproto/ofproto-dpif-xlate.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ofproto/ofproto-dpif-xlate.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ofproto/ofproto-dpif-xlate.c 2020-03-11 16:15:44.000000000 +0000
@@ -534,6 +534,8 @@
static void clone_xlate_actions(const struct ofpact *, size_t ofpacts_len,
struct xlate_ctx *, bool, bool);
static void xlate_normal(struct xlate_ctx *);
+static void xlate_normal_flood(struct xlate_ctx *ct,
+ struct xbundle *in_xbundle, struct xvlan *);
static void xlate_table_action(struct xlate_ctx *, ofp_port_t in_port,
uint8_t table_id, bool may_packet_in,
bool honor_table_miss, bool with_ct_orig,
@@ -2028,21 +2030,10 @@
return;
}
- if (ctx->xin->resubmit_stats) {
- mirror_update_stats(xbridge->mbridge, mirrors,
- ctx->xin->resubmit_stats->n_packets,
- ctx->xin->resubmit_stats->n_bytes);
- }
- if (ctx->xin->xcache) {
- struct xc_entry *entry;
-
- entry = xlate_cache_add_entry(ctx->xin->xcache, XC_MIRROR);
- entry->mirror.mbridge = mbridge_ref(xbridge->mbridge);
- entry->mirror.mirrors = mirrors;
- }
-
- /* 'mirrors' is a bit-mask of candidates for mirroring. Iterate as long as
- * some candidates remain. */
+ /* 'mirrors' is a bit-mask of candidates for mirroring. Iterate through
+ * the candidates, adding the ones that really should be mirrored to
+ * 'used_mirrors', as long as some candidates remain. */
+ mirror_mask_t used_mirrors = 0;
while (mirrors) {
const unsigned long *vlans;
mirror_mask_t dup_mirrors;
@@ -2066,6 +2057,9 @@
continue;
}
+ /* We sent a packet to this mirror. */
+ used_mirrors |= rightmost_1bit(mirrors);
+
/* Record the mirror, and the mirrors that output to the same
* destination, so that we don't mirror to them again. This must be
* done now to ensure that output_normal(), below, doesn't recursively
@@ -2099,6 +2093,21 @@
mirrors &= ~ctx->mirrors;
ctx->mirror_snaplen = 0;
}
+
+ if (used_mirrors) {
+ if (ctx->xin->resubmit_stats) {
+ mirror_update_stats(xbridge->mbridge, used_mirrors,
+ ctx->xin->resubmit_stats->n_packets,
+ ctx->xin->resubmit_stats->n_bytes);
+ }
+ if (ctx->xin->xcache) {
+ struct xc_entry *entry;
+
+ entry = xlate_cache_add_entry(ctx->xin->xcache, XC_MIRROR);
+ entry->mirror.mbridge = mbridge_ref(xbridge->mbridge);
+ entry->mirror.mirrors = used_mirrors;
+ }
+ }
}
static void
@@ -2662,6 +2671,53 @@
}
ovs_rwlock_unlock(&ms->rwlock);
}
+
+/* A list of multicast output ports.
+ *
+ * We accumulate output ports and then do all the outputs afterward. It would
+ * be more natural to do the outputs one at a time as we discover the need for
+ * each one, but this can cause a deadlock because we need to take the
+ * mcast_snooping's rwlock for reading to iterate through the port lists and
+ * doing an output, if it goes to a patch port, can eventually come back to the
+ * same mcast_snooping and attempt to take the write lock (see
+ * https://github.com/openvswitch/ovs-issues/issues/153). */
+struct mcast_output {
+ /* Discrete ports. */
+ struct xbundle **xbundles;
+ size_t n, allocated;
+
+ /* If set, flood to all ports. */
+ bool flood;
+};
+#define MCAST_OUTPUT_INIT { NULL, 0, 0, false }
+
+/* Add 'mcast_bundle' to 'out'. */
+static void
+mcast_output_add(struct mcast_output *out, struct xbundle *mcast_xbundle)
+{
+ if (out->n >= out->allocated) {
+ out->xbundles = x2nrealloc(out->xbundles, &out->allocated,
+ sizeof *out->xbundles);
+ }
+ out->xbundles[out->n++] = mcast_xbundle;
+}
+
+/* Outputs the packet in 'ctx' to all of the output ports in 'out', given input
+ * bundle 'in_xbundle' and the current 'xvlan'. */
+static void
+mcast_output_finish(struct xlate_ctx *ctx, struct mcast_output *out,
+ struct xbundle *in_xbundle, struct xvlan *xvlan)
+{
+ if (out->flood) {
+ xlate_normal_flood(ctx, in_xbundle, xvlan);
+ } else {
+ for (size_t i = 0; i < out->n; i++) {
+ output_normal(ctx, out->xbundles[i], xvlan);
+ }
+ }
+
+ free(out->xbundles);
+}
/* send the packet to ports having the multicast group learned */
static void
@@ -2669,7 +2725,7 @@
struct mcast_snooping *ms OVS_UNUSED,
struct mcast_group *grp,
struct xbundle *in_xbundle,
- const struct xvlan *xvlan)
+ struct mcast_output *out)
OVS_REQ_RDLOCK(ms->rwlock)
{
struct mcast_group_bundle *b;
@@ -2679,7 +2735,7 @@
mcast_xbundle = xbundle_lookup(ctx->xcfg, b->port);
if (mcast_xbundle && mcast_xbundle != in_xbundle) {
xlate_report(ctx, OFT_DETAIL, "forwarding to mcast group port");
- output_normal(ctx, mcast_xbundle, xvlan);
+ mcast_output_add(out, mcast_xbundle);
} else if (!mcast_xbundle) {
xlate_report(ctx, OFT_WARN,
"mcast group port is unknown, dropping");
@@ -2695,7 +2751,8 @@
xlate_normal_mcast_send_mrouters(struct xlate_ctx *ctx,
struct mcast_snooping *ms,
struct xbundle *in_xbundle,
- const struct xvlan *xvlan)
+ const struct xvlan *xvlan,
+ struct mcast_output *out)
OVS_REQ_RDLOCK(ms->rwlock)
{
struct mcast_mrouter_bundle *mrouter;
@@ -2706,7 +2763,7 @@
if (mcast_xbundle && mcast_xbundle != in_xbundle
&& mrouter->vlan == xvlan->v[0].vid) {
xlate_report(ctx, OFT_DETAIL, "forwarding to mcast router port");
- output_normal(ctx, mcast_xbundle, xvlan);
+ mcast_output_add(out, mcast_xbundle);
} else if (!mcast_xbundle) {
xlate_report(ctx, OFT_WARN,
"mcast router port is unknown, dropping");
@@ -2725,7 +2782,7 @@
xlate_normal_mcast_send_fports(struct xlate_ctx *ctx,
struct mcast_snooping *ms,
struct xbundle *in_xbundle,
- const struct xvlan *xvlan)
+ struct mcast_output *out)
OVS_REQ_RDLOCK(ms->rwlock)
{
struct mcast_port_bundle *fport;
@@ -2735,7 +2792,7 @@
mcast_xbundle = xbundle_lookup(ctx->xcfg, fport->port);
if (mcast_xbundle && mcast_xbundle != in_xbundle) {
xlate_report(ctx, OFT_DETAIL, "forwarding to mcast flood port");
- output_normal(ctx, mcast_xbundle, xvlan);
+ mcast_output_add(out, mcast_xbundle);
} else if (!mcast_xbundle) {
xlate_report(ctx, OFT_WARN,
"mcast flood port is unknown, dropping");
@@ -2751,7 +2808,7 @@
xlate_normal_mcast_send_rports(struct xlate_ctx *ctx,
struct mcast_snooping *ms,
struct xbundle *in_xbundle,
- const struct xvlan *xvlan)
+ struct mcast_output *out)
OVS_REQ_RDLOCK(ms->rwlock)
{
struct mcast_port_bundle *rport;
@@ -2764,7 +2821,7 @@
&& mcast_xbundle->ofbundle != in_xbundle->ofbundle) {
xlate_report(ctx, OFT_DETAIL,
"forwarding report to mcast flagged port");
- output_normal(ctx, mcast_xbundle, xvlan);
+ mcast_output_add(out, mcast_xbundle);
} else if (!mcast_xbundle) {
xlate_report(ctx, OFT_WARN,
"mcast port is unknown, dropping the report");
@@ -2916,8 +2973,11 @@
}
if (mcast_snooping_is_membership(flow->tp_src)) {
+ struct mcast_output out = MCAST_OUTPUT_INIT;
+
ovs_rwlock_rdlock(&ms->rwlock);
- xlate_normal_mcast_send_mrouters(ctx, ms, in_xbundle, &xvlan);
+ xlate_normal_mcast_send_mrouters(ctx, ms, in_xbundle, &xvlan,
+ &out);
/* RFC4541: section 2.1.1, item 1: A snooping switch should
* forward IGMP Membership Reports only to those ports where
* multicast routers are attached. Alternatively stated: a
@@ -2926,8 +2986,10 @@
* An administrative control may be provided to override this
* restriction, allowing the report messages to be flooded to
* other ports. */
- xlate_normal_mcast_send_rports(ctx, ms, in_xbundle, &xvlan);
+ xlate_normal_mcast_send_rports(ctx, ms, in_xbundle, &out);
ovs_rwlock_unlock(&ms->rwlock);
+
+ mcast_output_finish(ctx, &out, in_xbundle, &xvlan);
} else {
xlate_report(ctx, OFT_DETAIL, "multicast traffic, flooding");
xlate_normal_flood(ctx, in_xbundle, &xvlan);
@@ -2940,10 +3002,15 @@
in_xbundle, ctx->xin->packet);
}
if (is_mld_report(flow, wc)) {
+ struct mcast_output out = MCAST_OUTPUT_INIT;
+
ovs_rwlock_rdlock(&ms->rwlock);
- xlate_normal_mcast_send_mrouters(ctx, ms, in_xbundle, &xvlan);
- xlate_normal_mcast_send_rports(ctx, ms, in_xbundle, &xvlan);
+ xlate_normal_mcast_send_mrouters(ctx, ms, in_xbundle, &xvlan,
+ &out);
+ xlate_normal_mcast_send_rports(ctx, ms, in_xbundle, &out);
ovs_rwlock_unlock(&ms->rwlock);
+
+ mcast_output_finish(ctx, &out, in_xbundle, &xvlan);
} else {
xlate_report(ctx, OFT_DETAIL, "MLD query, flooding");
xlate_normal_flood(ctx, in_xbundle, &xvlan);
@@ -2961,6 +3028,8 @@
}
/* forwarding to group base ports */
+ struct mcast_output out = MCAST_OUTPUT_INIT;
+
ovs_rwlock_rdlock(&ms->rwlock);
if (flow->dl_type == htons(ETH_TYPE_IP)) {
grp = mcast_snooping_lookup4(ms, flow->nw_dst, vlan);
@@ -2968,20 +3037,24 @@
grp = mcast_snooping_lookup(ms, &flow->ipv6_dst, vlan);
}
if (grp) {
- xlate_normal_mcast_send_group(ctx, ms, grp, in_xbundle, &xvlan);
- xlate_normal_mcast_send_fports(ctx, ms, in_xbundle, &xvlan);
- xlate_normal_mcast_send_mrouters(ctx, ms, in_xbundle, &xvlan);
+ xlate_normal_mcast_send_group(ctx, ms, grp, in_xbundle, &out);
+ xlate_normal_mcast_send_fports(ctx, ms, in_xbundle, &out);
+ xlate_normal_mcast_send_mrouters(ctx, ms, in_xbundle, &xvlan,
+ &out);
} else {
if (mcast_snooping_flood_unreg(ms)) {
xlate_report(ctx, OFT_DETAIL,
"unregistered multicast, flooding");
- xlate_normal_flood(ctx, in_xbundle, &xvlan);
+ out.flood = true;
} else {
- xlate_normal_mcast_send_mrouters(ctx, ms, in_xbundle, &xvlan);
- xlate_normal_mcast_send_fports(ctx, ms, in_xbundle, &xvlan);
+ xlate_normal_mcast_send_mrouters(ctx, ms, in_xbundle, &xvlan,
+ &out);
+ xlate_normal_mcast_send_fports(ctx, ms, in_xbundle, &out);
}
}
ovs_rwlock_unlock(&ms->rwlock);
+
+ mcast_output_finish(ctx, &out, in_xbundle, &xvlan);
} else {
ovs_rwlock_rdlock(&ctx->xbridge->ml->rwlock);
mac = mac_learning_lookup(ctx->xbridge->ml, flow->dl_dst, vlan);
@@ -3040,7 +3113,7 @@
/* When meter action is not required, avoid generate sample action
* for 100% sampling rate. */
bool is_sample = probability < UINT32_MAX || meter_id != UINT32_MAX;
- size_t sample_offset, actions_offset;
+ size_t sample_offset = 0, actions_offset = 0;
if (is_sample) {
sample_offset = nl_msg_start_nested(ctx->odp_actions,
OVS_ACTION_ATTR_SAMPLE);
@@ -3056,8 +3129,7 @@
odp_port_t odp_port = ofp_port_to_odp_port(
ctx->xbridge, ctx->xin->flow.in_port.ofp_port);
- uint32_t pid = dpif_port_get_pid(ctx->xbridge->dpif, odp_port,
- flow_hash_5tuple(&ctx->xin->flow, 0));
+ uint32_t pid = dpif_port_get_pid(ctx->xbridge->dpif, odp_port);
size_t cookie_offset = odp_put_userspace_action(pid, cookie,
sizeof *cookie,
tunnel_out_port,
@@ -3087,11 +3159,13 @@
return 0;
}
- struct user_action_cookie cookie = {
- .type = USER_ACTION_COOKIE_SFLOW,
- .ofp_in_port = ctx->xin->flow.in_port.ofp_port,
- .ofproto_uuid = ctx->xbridge->ofproto->uuid
- };
+ struct user_action_cookie cookie;
+
+ memset(&cookie, 0, sizeof cookie);
+ cookie.type = USER_ACTION_COOKIE_SFLOW;
+ cookie.ofp_in_port = ctx->xin->flow.in_port.ofp_port;
+ cookie.ofproto_uuid = ctx->xbridge->ofproto->uuid;
+
return compose_sample_action(ctx, dpif_sflow_get_probability(sflow),
&cookie, ODPP_NONE, true);
}
@@ -3131,12 +3205,14 @@
}
}
- struct user_action_cookie cookie = {
- .type = USER_ACTION_COOKIE_IPFIX,
- .ofp_in_port = ctx->xin->flow.in_port.ofp_port,
- .ofproto_uuid = ctx->xbridge->ofproto->uuid,
- .ipfix.output_odp_port = output_odp_port
- };
+ struct user_action_cookie cookie;
+
+ memset(&cookie, 0, sizeof cookie);
+ cookie.type = USER_ACTION_COOKIE_IPFIX;
+ cookie.ofp_in_port = ctx->xin->flow.in_port.ofp_port;
+ cookie.ofproto_uuid = ctx->xbridge->ofproto->uuid;
+ cookie.ipfix.output_odp_port = output_odp_port;
+
compose_sample_action(ctx,
dpif_ipfix_get_bridge_exporter_probability(ipfix),
&cookie, tunnel_out_port, false);
@@ -3279,6 +3355,7 @@
struct dp_packet *packet)
{
struct xbridge *xbridge = out_dev->xbridge;
+ ovs_version_t version = ofproto_dpif_get_tables_version(xbridge->ofproto);
struct ofpact_output output;
struct flow flow;
@@ -3288,8 +3365,7 @@
output.port = OFPP_TABLE;
output.max_len = 0;
- return ofproto_dpif_execute_actions__(xbridge->ofproto,
- ctx->xin->tables_version, &flow,
+ return ofproto_dpif_execute_actions__(xbridge->ofproto, version, &flow,
NULL, &output.ofpact, sizeof output,
ctx->depth, ctx->resubmits, packet);
}
@@ -3553,13 +3629,6 @@
nl_msg_end_non_empty_nested(ctx->odp_actions, clone_ofs);
} else {
nl_msg_cancel_nested(ctx->odp_actions, clone_ofs);
- /* XXX : There is no real use-case for a tunnel push without
- * any post actions. However keeping it now
- * as is to make the 'make check' happy. Should remove when all the
- * make check tunnel test case does something meaningful on a
- * tunnel encap packets.
- */
- odp_put_tnl_push_action(ctx->odp_actions, &tnl_push_data);
}
/* Restore context status. */
@@ -4199,6 +4268,7 @@
!is_ip_any(&ctx->xin->flow)) {
xlate_report_error(ctx,
"resubmit(ct) with non-tracked or non-IP packet!");
+ ctx->table_id = old_table_id;
return;
}
tuple_swap(&ctx->xin->flow, ctx->wc);
@@ -4460,7 +4530,7 @@
bool is_last_action)
{
if (group->up.type == OFPGT11_ALL || group->up.type == OFPGT11_INDIRECT) {
- struct ovs_list *last_bucket = ovs_list_back(&group->up.buckets);
+ struct ovs_list *last_bucket = group->up.buckets.prev;
struct ofputil_bucket *bucket;
LIST_FOR_EACH (bucket, list_node, &group->up.buckets) {
bool is_last_bucket = &bucket->list_node == last_bucket;
@@ -4609,8 +4679,7 @@
odp_port_t odp_port = ofp_port_to_odp_port(ctx->xbridge,
ctx->xin->flow.in_port.ofp_port);
- uint32_t pid = dpif_port_get_pid(ctx->xbridge->dpif, odp_port,
- flow_hash_5tuple(&ctx->xin->flow, 0));
+ uint32_t pid = dpif_port_get_pid(ctx->xbridge->dpif, odp_port);
odp_put_userspace_action(pid, &cookie, sizeof cookie, ODPP_NONE,
false, ctx->odp_actions);
}
@@ -5393,19 +5462,19 @@
}
}
- struct user_action_cookie cookie = {
- .type = USER_ACTION_COOKIE_FLOW_SAMPLE,
- .ofp_in_port = ctx->xin->flow.in_port.ofp_port,
- .ofproto_uuid = ctx->xbridge->ofproto->uuid,
- .flow_sample = {
- .probability = os->probability,
- .collector_set_id = os->collector_set_id,
- .obs_domain_id = os->obs_domain_id,
- .obs_point_id = os->obs_point_id,
- .output_odp_port = output_odp_port,
- .direction = os->direction,
- }
- };
+ struct user_action_cookie cookie;
+
+ memset(&cookie, 0, sizeof cookie);
+ cookie.type = USER_ACTION_COOKIE_FLOW_SAMPLE;
+ cookie.ofp_in_port = ctx->xin->flow.in_port.ofp_port;
+ cookie.ofproto_uuid = ctx->xbridge->ofproto->uuid;
+ cookie.flow_sample.probability = os->probability;
+ cookie.flow_sample.collector_set_id = os->collector_set_id;
+ cookie.flow_sample.obs_domain_id = os->obs_domain_id;
+ cookie.flow_sample.obs_point_id = os->obs_point_id;
+ cookie.flow_sample.output_odp_port = output_odp_port;
+ cookie.flow_sample.direction = os->direction;
+
compose_sample_action(ctx, probability, &cookie, tunnel_out_port, false);
}
@@ -6946,9 +7015,7 @@
/* Some fields we consider to always be examined. */
WC_MASK_FIELD(ctx->wc, packet_type);
WC_MASK_FIELD(ctx->wc, in_port);
- if (is_ethernet(&ctx->xin->flow, NULL)) {
- WC_MASK_FIELD(ctx->wc, dl_type);
- }
+ WC_MASK_FIELD(ctx->wc, dl_type);
if (is_ip_any(&ctx->xin->flow)) {
WC_MASK_FIELD_MASK(ctx->wc, nw_frag, FLOW_NW_FRAG_MASK);
}
@@ -6975,12 +7042,14 @@
* use non-header fields as part of the cache. */
flow_wildcards_clear_non_packet_fields(ctx->wc);
- /* Wildcard ethernet fields if the original packet type was not
- * Ethernet. */
+ /* Wildcard Ethernet address fields if the original packet type was not
+ * Ethernet.
+ *
+ * (The Ethertype field is used even when the original packet type is not
+ * Ethernet.) */
if (ctx->xin->upcall_flow->packet_type != htonl(PT_ETH)) {
ctx->wc->masks.dl_dst = eth_addr_zero;
ctx->wc->masks.dl_src = eth_addr_zero;
- ctx->wc->masks.dl_type = 0;
}
/* ICMPv4 and ICMPv6 have 8-bit "type" and "code" fields. struct flow
@@ -7436,19 +7505,22 @@
xlate_resume(struct ofproto_dpif *ofproto,
const struct ofputil_packet_in_private *pin,
struct ofpbuf *odp_actions,
- enum slow_path_reason *slow)
+ enum slow_path_reason *slow,
+ struct flow *flow,
+ struct xlate_cache *xcache)
{
struct dp_packet packet;
dp_packet_use_const(&packet, pin->base.packet,
pin->base.packet_len);
- struct flow flow;
- flow_extract(&packet, &flow);
+ pkt_metadata_from_flow(&packet.md, &pin->base.flow_metadata.flow);
+ flow_extract(&packet, flow);
struct xlate_in xin;
xlate_in_init(&xin, ofproto, ofproto_dpif_get_tables_version(ofproto),
- &flow, 0, NULL, ntohs(flow.tcp_flags),
+ flow, 0, NULL, ntohs(flow->tcp_flags),
&packet, NULL, odp_actions);
+ xin.xcache = xcache;
struct ofpact_note noop;
ofpact_init_NOTE(&noop);
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ofproto/ofproto-dpif-xlate.h openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ofproto/ofproto-dpif-xlate.h
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ofproto/ofproto-dpif-xlate.h 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ofproto/ofproto-dpif-xlate.h 2020-03-11 16:15:44.000000000 +0000
@@ -230,8 +230,8 @@
enum ofperr xlate_resume(struct ofproto_dpif *,
const struct ofputil_packet_in_private *,
- struct ofpbuf *odp_actions, enum slow_path_reason *);
-
+ struct ofpbuf *odp_actions, enum slow_path_reason *,
+ struct flow *, struct xlate_cache *);
int xlate_send_packet(const struct ofport_dpif *, bool oam, struct dp_packet *);
void xlate_mac_learning_update(const struct ofproto_dpif *ofproto,
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ofproto/ofproto-provider.h openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ofproto/ofproto-provider.h
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ofproto/ofproto-provider.h 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ofproto/ofproto-provider.h 2020-03-11 16:15:44.000000000 +0000
@@ -1336,9 +1336,15 @@
* packet_xlate_revert() calls have to be made in reverse order. */
void (*packet_xlate_revert)(struct ofproto *, struct ofproto_packet_out *);
- /* Executes the datapath actions, translation side-effects, and stats as
- * produced by ->packet_xlate(). The caller retains ownership of 'opo'.
- */
+ /* Translates side-effects, and stats as produced by ->packet_xlate().
+ * Prepares to execute datapath actions. The caller retains ownership
+ * of 'opo'. */
+ void (*packet_execute_prepare)(struct ofproto *,
+ struct ofproto_packet_out *opo);
+
+ /* Executes the datapath actions. The caller retains ownership of 'opo'.
+ * Should be called after successful packet_execute_prepare().
+ * No-op if called after packet_xlate_revert(). */
void (*packet_execute)(struct ofproto *, struct ofproto_packet_out *opo);
/* Changes the OpenFlow IP fragment handling policy to 'frag_handling',
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovn/controller/ofctrl.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovn/controller/ofctrl.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovn/controller/ofctrl.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovn/controller/ofctrl.c 2020-03-11 16:15:44.000000000 +0000
@@ -630,9 +630,11 @@
*
* The caller should initialize its own hmap to hold the flows. */
void
-ofctrl_add_flow(struct hmap *desired_flows,
- uint8_t table_id, uint16_t priority, uint64_t cookie,
- const struct match *match, const struct ofpbuf *actions)
+ofctrl_check_and_add_flow(struct hmap *desired_flows,
+ uint8_t table_id, uint16_t priority, uint64_t cookie,
+ const struct match *match,
+ const struct ofpbuf *actions,
+ bool log_duplicate_flow)
{
struct ovn_flow *f = xmalloc(sizeof *f);
f->table_id = table_id;
@@ -644,13 +646,14 @@
f->cookie = cookie;
if (ovn_flow_lookup(desired_flows, f)) {
- static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5);
- if (!VLOG_DROP_DBG(&rl)) {
- char *s = ovn_flow_to_string(f);
- VLOG_DBG("dropping duplicate flow: %s", s);
- free(s);
+ if (log_duplicate_flow) {
+ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5);
+ if (!VLOG_DROP_DBG(&rl)) {
+ char *s = ovn_flow_to_string(f);
+ VLOG_DBG("dropping duplicate flow: %s", s);
+ free(s);
+ }
}
-
ovn_flow_destroy(f);
return;
}
@@ -658,6 +661,14 @@
hmap_insert(desired_flows, &f->hmap_node, f->hmap_node.hash);
}
+void
+ofctrl_add_flow(struct hmap *desired_flows,
+ uint8_t table_id, uint16_t priority, uint64_t cookie,
+ const struct match *match, const struct ofpbuf *actions)
+{
+ ofctrl_check_and_add_flow(desired_flows, table_id, priority, cookie,
+ match, actions, true);
+}
/* ovn_flow. */
@@ -777,7 +788,7 @@
static struct ofpbuf *
encode_group_mod(const struct ofputil_group_mod *gm)
{
- return ofputil_encode_group_mod(OFP13_VERSION, gm);
+ return ofputil_encode_group_mod(OFP13_VERSION, gm, NULL, -1);
}
static void
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovn/controller/ofctrl.h openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovn/controller/ofctrl.h
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovn/controller/ofctrl.h 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovn/controller/ofctrl.h 2020-03-11 16:15:44.000000000 +0000
@@ -55,4 +55,9 @@
uint16_t priority, uint64_t cookie,
const struct match *, const struct ofpbuf *ofpacts);
+void ofctrl_check_and_add_flow(struct hmap *desired_flows, uint8_t table_id,
+ uint16_t priority, uint64_t cookie,
+ const struct match *,
+ const struct ofpbuf *ofpacts,
+ bool log_duplicate_flow);
#endif /* ovn/ofctrl.h */
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovn/controller/ovn-controller.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovn/controller/ovn-controller.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovn/controller/ovn-controller.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovn/controller/ovn-controller.c 2020-03-11 16:15:44.000000000 +0000
@@ -801,7 +801,7 @@
if (pending_pkt.conn) {
char *error = ofctrl_inject_pkt(br_int, pending_pkt.flow_s,
- &port_groups, &addr_sets);
+ &addr_sets, &port_groups);
if (error) {
unixctl_command_reply_error(pending_pkt.conn, error);
free(error);
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovn/controller/physical.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovn/controller/physical.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovn/controller/physical.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovn/controller/physical.c 2020-03-11 16:15:44.000000000 +0000
@@ -189,7 +189,8 @@
static void
put_local_common_flows(uint32_t dp_key, uint32_t port_key,
- bool nested_container, const struct zone_ids *zone_ids,
+ uint32_t parent_port_key,
+ const struct zone_ids *zone_ids,
struct ofpbuf *ofpacts_p, struct hmap *flow_table)
{
struct match match;
@@ -244,11 +245,19 @@
/* Table 64, Priority 100.
* =======================
*
- * If the packet is supposed to hair-pin because the "loopback"
- * flag is set (or if the destination is a nested container),
+ * If the packet is supposed to hair-pin because the
+ * - "loopback" flag is set
+ * - or if the destination is a nested container
+ * - or if "nested_container" flag is set and the destination is the
+ * parent port,
* temporarily set the in_port to zero, resubmit to
* table 65 for logical-to-physical translation, then restore
- * the port number. */
+ * the port number.
+ *
+ * If 'parent_port_key' is set, then the 'port_key' represents a nested
+ * container. */
+
+ bool nested_container = parent_port_key ? true: false;
match_init_catchall(&match);
ofpbuf_clear(ofpacts_p);
match_set_metadata(&match, htonll(dp_key));
@@ -264,6 +273,38 @@
put_stack(MFF_IN_PORT, ofpact_put_STACK_POP(ofpacts_p));
ofctrl_add_flow(flow_table, OFTABLE_SAVE_INPORT, 100, 0,
&match, ofpacts_p);
+
+ if (nested_container) {
+ /* It's a nested container and when the packet from the nested
+ * container is to be sent to the parent port, "nested_container"
+ * flag will be set. We need to temporarily set the in_port to zero
+ * as mentioned in the comment above.
+ *
+ * If a parent port has multiple child ports, then this if condition
+ * will be hit multiple times, but we want to add only one flow.
+ * ofctrl_add_flow() logs a warning message for duplicate flows.
+ * So use the function 'ofctrl_check_and_add_flow' which doesn't
+ * log a warning.
+ *
+ * Other option is to add this flow for all the ports which are not
+ * nested containers. In which case we will add this flow for all the
+ * ports even if they don't have any child ports which is
+ * unnecessary.
+ */
+ match_init_catchall(&match);
+ ofpbuf_clear(ofpacts_p);
+ match_set_metadata(&match, htonll(dp_key));
+ match_set_reg(&match, MFF_LOG_OUTPORT - MFF_REG0, parent_port_key);
+ match_set_reg_masked(&match, MFF_LOG_FLAGS - MFF_REG0,
+ MLF_NESTED_CONTAINER, MLF_NESTED_CONTAINER);
+
+ put_stack(MFF_IN_PORT, ofpact_put_STACK_PUSH(ofpacts_p));
+ put_load(0, MFF_IN_PORT, 0, 16, ofpacts_p);
+ put_resubmit(OFTABLE_LOG_TO_PHY, ofpacts_p);
+ put_stack(MFF_IN_PORT, ofpact_put_STACK_POP(ofpacts_p));
+ ofctrl_check_and_add_flow(flow_table, OFTABLE_SAVE_INPORT, 100, 0,
+ &match, ofpacts_p, false);
+ }
}
static void
@@ -328,7 +369,7 @@
}
struct zone_ids binding_zones = get_zone_ids(binding, ct_zones);
- put_local_common_flows(dp_key, port_key, false, &binding_zones,
+ put_local_common_flows(dp_key, port_key, 0, &binding_zones,
ofpacts_p, flow_table);
match_init_catchall(&match);
@@ -452,6 +493,7 @@
int tag = 0;
bool nested_container = false;
+ const struct sbrec_port_binding *parent_port = NULL;
ofp_port_t ofport;
bool is_remote = false;
if (binding->parent_port && *binding->parent_port) {
@@ -463,6 +505,8 @@
if (ofport) {
tag = *binding->tag;
nested_container = true;
+ parent_port = lport_lookup_by_name(
+ sbrec_port_binding_by_name, binding->parent_port);
}
} else {
ofport = u16_to_ofp(simap_get(&localvif_to_ofport,
@@ -523,7 +567,10 @@
*/
struct zone_ids zone_ids = get_zone_ids(binding, ct_zones);
- put_local_common_flows(dp_key, port_key, nested_container, &zone_ids,
+ uint32_t parent_port_key = parent_port ? parent_port->tunnel_key : 0;
+ /* Pass the parent port tunnel key if the port is a nested
+ * container. */
+ put_local_common_flows(dp_key, port_key, parent_port_key, &zone_ids,
ofpacts_p, flow_table);
/* Table 0, Priority 150 and 100.
@@ -553,8 +600,10 @@
if (nested_container) {
/* When a packet comes from a container sitting behind a
* parent_port, we should let it loopback to other containers
- * or the parent_port itself. */
- put_load(MLF_ALLOW_LOOPBACK, MFF_LOG_FLAGS, 0, 1, ofpacts_p);
+ * or the parent_port itself. Indicate this by setting the
+ * MLF_NESTED_CONTAINER_BIT in MFF_LOG_FLAGS.*/
+ put_load(1, MFF_LOG_FLAGS, MLF_NESTED_CONTAINER_BIT, 1,
+ ofpacts_p);
}
ofpact_put_STRIP_VLAN(ofpacts_p);
}
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovn/controller/pinctrl.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovn/controller/pinctrl.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovn/controller/pinctrl.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovn/controller/pinctrl.c 2020-03-11 16:15:44.000000000 +0000
@@ -432,7 +432,7 @@
if (dp_packet_l4_size(pkt_in) < (UDP_HEADER_LEN +
sizeof (struct dhcp_header) + sizeof(uint32_t) + 3)) {
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
- VLOG_WARN_RL(&rl, "Invalid or incomplete DHCP packet recieved");
+ VLOG_WARN_RL(&rl, "Invalid or incomplete DHCP packet received");
goto exit;
}
@@ -609,6 +609,11 @@
return false;
}
+ if (!iaid) {
+ /* If iaid is None, it means its an DHCPv6 information request.
+ * Don't put IA_NA option in the response. */
+ break;
+ }
/* IA Address option is used to specify IPv6 addresses associated
* with an IA_NA or IA_TA. The IA Address option must be
* encapsulated in the Options field of an IA_NA or IA_TA option.
@@ -717,7 +722,8 @@
}
uint8_t out_dhcpv6_msg_type;
- switch(*in_dhcpv6_data) {
+ uint8_t in_dhcpv6_msg_type = *in_dhcpv6_data;
+ switch (in_dhcpv6_msg_type) {
case DHCPV6_MSG_TYPE_SOLICIT:
out_dhcpv6_msg_type = DHCPV6_MSG_TYPE_ADVT;
break;
@@ -725,6 +731,7 @@
case DHCPV6_MSG_TYPE_REQUEST:
case DHCPV6_MSG_TYPE_CONFIRM:
case DHCPV6_MSG_TYPE_DECLINE:
+ case DHCPV6_MSG_TYPE_INFO_REQ:
out_dhcpv6_msg_type = DHCPV6_MSG_TYPE_REPLY;
break;
@@ -737,7 +744,10 @@
in_dhcpv6_data += 4;
/* We need to extract IAID from the IA-NA option of the client's DHCPv6
* solicit/request/confirm packet and copy the same IAID in the Server's
- * response. */
+ * response.
+ * DHCPv6 information packet (for stateless request will not have IA-NA
+ * option. So we don't need to copy that in the Server's response.
+ * */
ovs_be32 iaid = 0;
struct dhcpv6_opt_header const *in_opt_client_id = NULL;
size_t udp_len = ntohs(in_udp->udp_len);
@@ -771,7 +781,7 @@
goto exit;
}
- if (!iaid) {
+ if (!iaid && in_dhcpv6_msg_type != DHCPV6_MSG_TYPE_INFO_REQ) {
VLOG_WARN_RL(&rl, "DHCPv6 option - IA NA not present in the "
" DHCPv6 packet");
goto exit;
@@ -898,6 +908,12 @@
goto exit;
}
+ /* Check that the packet stores at least the minimal headers. */
+ if (dp_packet_l4_size(pkt_in) < (UDP_HEADER_LEN + DNS_HEADER_LEN)) {
+ VLOG_WARN_RL(&rl, "truncated dns packet");
+ goto exit;
+ }
+
/* Extract the DNS header */
struct dns_header const *in_dns_header = dp_packet_get_udp_payload(pkt_in);
if (!in_dns_header) {
@@ -922,7 +938,7 @@
uint8_t *end = (uint8_t *)in_udp + MIN(udp_len, l4_len);
uint8_t *in_dns_data = (uint8_t *)(in_dns_header + 1);
uint8_t *in_queryname = in_dns_data;
- uint8_t idx = 0;
+ uint16_t idx = 0;
struct ds query_name;
ds_init(&query_name);
/* Extract the query_name. If the query name is - 'www.ovn.org' it would be
@@ -1378,7 +1394,7 @@
config->min_interval = smap_get_int(&pb->options, "ipv6_ra_min_interval",
nd_ra_min_interval_default(config->max_interval));
config->mtu = smap_get_int(&pb->options, "ipv6_ra_mtu", ND_MTU_DEFAULT);
- config->la_flags = ND_PREFIX_ON_LINK;
+ config->la_flags = IPV6_ND_RA_OPT_PREFIX_ON_LINK;
const char *address_mode = smap_get(&pb->options, "ipv6_ra_address_mode");
if (!address_mode) {
@@ -1387,10 +1403,11 @@
}
if (!strcmp(address_mode, "dhcpv6_stateless")) {
config->mo_flags = IPV6_ND_RA_FLAG_OTHER_ADDR_CONFIG;
+ config->la_flags |= IPV6_ND_RA_OPT_PREFIX_AUTONOMOUS;
} else if (!strcmp(address_mode, "dhcpv6_stateful")) {
config->mo_flags = IPV6_ND_RA_FLAG_MANAGED_ADDR_CONFIG;
} else if (!strcmp(address_mode, "slaac")) {
- config->la_flags |= ND_PREFIX_AUTONOMOUS_ADDRESS;
+ config->la_flags |= IPV6_ND_RA_OPT_PREFIX_AUTONOMOUS;
} else {
VLOG_WARN("Invalid address mode %s", address_mode);
goto fail;
@@ -1563,6 +1580,11 @@
ra->config->max_interval);
shash_add(&ipv6_ras, pb->logical_port, ra);
} else {
+ if (config->min_interval != ra->config->min_interval ||
+ config->max_interval != ra->config->max_interval)
+ ra->next_announce = ipv6_ra_calc_next_announce(
+ config->min_interval,
+ config->max_interval);
ipv6_ra_config_delete(ra->config);
ra->config = config;
}
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovn/lib/actions.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovn/lib/actions.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovn/lib/actions.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovn/lib/actions.c 2020-03-11 16:15:44.000000000 +0000
@@ -185,12 +185,15 @@
: ep->egress_ptable);
}
+#define MAX_NESTED_ACTION_DEPTH 32
+
/* Context maintained during ovnacts_parse(). */
struct action_context {
const struct ovnact_parse_params *pp; /* Parameters. */
struct lexer *lexer; /* Lexer for pulling more tokens. */
struct ofpbuf *ovnacts; /* Actions. */
struct expr *prereqs; /* Prerequisites to apply to match. */
+ int depth; /* Current nested action depth. */
};
static void parse_actions(struct action_context *, enum lex_type sentinel);
@@ -1092,6 +1095,11 @@
return;
}
+ if (ctx->depth + 1 == MAX_NESTED_ACTION_DEPTH) {
+ lexer_error(ctx->lexer, "maximum depth of nested actions reached");
+ return;
+ }
+
uint64_t stub[1024 / 8];
struct ofpbuf nested = OFPBUF_STUB_INITIALIZER(stub);
@@ -1100,6 +1108,7 @@
.lexer = ctx->lexer,
.ovnacts = &nested,
.prereqs = NULL,
+ .depth = ctx->depth + 1,
};
parse_actions(&inner_ctx, LEX_T_RCURLY);
@@ -1945,12 +1954,6 @@
return;
}
- if (addr_mode_stateful && prefix_set) {
- lexer_error(ctx->lexer, "prefix option can't be"
- " set when address mode is dhcpv6_stateful.");
- return;
- }
-
if (!addr_mode_stateful && !prefix_set) {
lexer_error(ctx->lexer, "prefix option needs "
"to be set when address mode is slaac/dhcpv6_stateless.");
@@ -1969,18 +1972,21 @@
static void
encode_put_nd_ra_option(const struct ovnact_gen_option *o,
- struct ofpbuf *ofpacts, struct ovs_ra_msg *ra)
+ struct ofpbuf *ofpacts, ptrdiff_t ra_offset)
{
const union expr_constant *c = o->value.values;
switch (o->option->code) {
case ND_RA_FLAG_ADDR_MODE:
+ {
+ struct ovs_ra_msg *ra = ofpbuf_at(ofpacts, ra_offset, sizeof *ra);
if (!strcmp(c->string, "dhcpv6_stateful")) {
ra->mo_flags = IPV6_ND_RA_FLAG_MANAGED_ADDR_CONFIG;
} else if (!strcmp(c->string, "dhcpv6_stateless")) {
ra->mo_flags = IPV6_ND_RA_FLAG_OTHER_ADDR_CONFIG;
}
break;
+ }
case ND_OPT_SOURCE_LINKADDR:
{
@@ -2008,10 +2014,14 @@
struct ovs_nd_prefix_opt *prefix_opt =
ofpbuf_put_uninit(ofpacts, sizeof *prefix_opt);
uint8_t prefix_len = ipv6_count_cidr_bits(&c->mask.ipv6);
+ struct ovs_ra_msg *ra = ofpbuf_at(ofpacts, ra_offset, sizeof *ra);
prefix_opt->type = ND_OPT_PREFIX_INFORMATION;
prefix_opt->len = 4;
prefix_opt->prefix_len = prefix_len;
- prefix_opt->la_flags = IPV6_ND_RA_OPT_PREFIX_FLAGS;
+ prefix_opt->la_flags = IPV6_ND_RA_OPT_PREFIX_ON_LINK;
+ if (!(ra->mo_flags & IPV6_ND_RA_FLAG_MANAGED_ADDR_CONFIG)) {
+ prefix_opt->la_flags |= IPV6_ND_RA_OPT_PREFIX_AUTONOMOUS;
+ }
put_16aligned_be32(&prefix_opt->valid_lifetime,
htonl(IPV6_ND_RA_OPT_PREFIX_VALID_LIFETIME));
put_16aligned_be32(&prefix_opt->preferred_lifetime,
@@ -2042,6 +2052,7 @@
* pinctrl module receives the ICMPv6 Router Solicitation packet
* it can copy the userdata field AS IS and resume the packet.
*/
+ size_t ra_offset = ofpacts->size;
struct ovs_ra_msg *ra = ofpbuf_put_zeros(ofpacts, sizeof *ra);
ra->icmph.icmp6_type = ND_ROUTER_ADVERT;
ra->cur_hop_limit = IPV6_ND_RA_CUR_HOP_LIMIT;
@@ -2050,7 +2061,7 @@
for (const struct ovnact_gen_option *o = po->options;
o < &po->options[po->n_options]; o++) {
- encode_put_nd_ra_option(o, ofpacts, ra);
+ encode_put_nd_ra_option(o, ofpacts, ra_offset);
}
encode_finish_controller_op(oc_offset, ofpacts);
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovn/lib/expr.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovn/lib/expr.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovn/lib/expr.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovn/lib/expr.c 2020-03-11 16:15:44.000000000 +0000
@@ -459,6 +459,8 @@
/* Parsing. */
+#define MAX_PAREN_DEPTH 100
+
/* Context maintained during expr_parse(). */
struct expr_context {
struct lexer *lexer; /* Lexer for pulling more tokens. */
@@ -466,6 +468,7 @@
const struct shash *addr_sets; /* Address set table. */
const struct shash *port_groups; /* Port group table. */
bool not; /* True inside odd number of NOT operators. */
+ unsigned int paren_depth; /* Depth of nested parentheses. */
};
struct expr *expr_parse__(struct expr_context *);
@@ -578,6 +581,11 @@
f->symbol->name);
goto exit;
}
+ if (!cs->n_values) {
+ lexer_error(ctx->lexer, "Only == and != operators may be used "
+ "to compare a field against an empty value set.");
+ goto exit;
+ }
if (cs->values[0].masked) {
lexer_error(ctx->lexer, "Only == and != operators may be used "
"with masked constants. Consider using subfields "
@@ -1077,7 +1085,15 @@
{
*atomic = false;
if (lexer_match(ctx->lexer, LEX_T_LPAREN)) {
+ if (ctx->paren_depth >= MAX_PAREN_DEPTH) {
+ lexer_error(ctx->lexer, "Parentheses nested too deeply.");
+ return NULL;
+ }
+
+ ctx->paren_depth++;
struct expr *e = expr_parse__(ctx);
+ ctx->paren_depth--;
+
if (!lexer_force_match(ctx->lexer, LEX_T_RPAREN)) {
expr_destroy(e);
return NULL;
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovn/lib/extend-table.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovn/lib/extend-table.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovn/lib/extend-table.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovn/lib/extend-table.c 2020-03-11 16:15:44.000000000 +0000
@@ -33,26 +33,25 @@
hmap_init(&table->existing);
}
+static void
+ovn_extend_table_info_destroy(struct hmap *target)
+{
+ struct ovn_extend_table_info *e, *next;
+ HMAP_FOR_EACH_SAFE (e, next, hmap_node, target) {
+ hmap_remove(target, &e->hmap_node);
+ free(e->name);
+ free(e);
+ }
+ hmap_destroy(target);
+}
+
void
ovn_extend_table_destroy(struct ovn_extend_table *table)
{
bitmap_free(table->table_ids);
- struct ovn_extend_table_info *desired, *d_next;
- HMAP_FOR_EACH_SAFE (desired, d_next, hmap_node, &table->existing) {
- hmap_remove(&table->existing, &desired->hmap_node);
- free(desired->name);
- free(desired);
- }
- hmap_destroy(&table->desired);
-
- struct ovn_extend_table_info *existing, *e_next;
- HMAP_FOR_EACH_SAFE (existing, e_next, hmap_node, &table->existing) {
- hmap_remove(&table->existing, &existing->hmap_node);
- free(existing->name);
- free(existing);
- }
- hmap_destroy(&table->existing);
+ ovn_extend_table_info_destroy(&table->desired);
+ ovn_extend_table_info_destroy(&table->existing);
}
/* Finds and returns a group_info in 'existing' whose key is identical
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovn/lib/lex.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovn/lib/lex.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovn/lib/lex.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovn/lib/lex.c 2020-03-11 16:15:44.000000000 +0000
@@ -332,13 +332,15 @@
if (hexit < 0) {
lex_error(token, "Invalid syntax in hexadecimal constant.");
return;
+ } else if (hexit) {
+ /* Check within loop to ignore any number of leading zeros. */
+ if (i / 2 >= sizeof token->value.u8) {
+ lex_error(token, "Hexadecimal constant requires more than "
+ "%"PRIuSIZE" bits.", 8 * sizeof token->value.u8);
+ return;
+ }
+ out[-(i / 2)] |= i % 2 ? hexit << 4 : hexit;
}
- if (hexit && i / 2 >= sizeof token->value.u8) {
- lex_error(token, "Hexadecimal constant requires more than "
- "%"PRIuSIZE" bits.", 8 * sizeof token->value.u8);
- return;
- }
- out[-(i / 2)] |= i % 2 ? hexit << 4 : hexit;
}
token->format = LEX_F_HEXADECIMAL;
}
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovn/lib/logical-fields.h openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovn/lib/logical-fields.h
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovn/lib/logical-fields.h 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovn/lib/logical-fields.h 2020-03-11 16:15:44.000000000 +0000
@@ -50,6 +50,7 @@
MLF_FORCE_SNAT_FOR_DNAT_BIT = 2,
MLF_FORCE_SNAT_FOR_LB_BIT = 3,
MLF_LOCAL_ONLY_BIT = 4,
+ MLF_NESTED_CONTAINER_BIT = 5,
};
/* MFF_LOG_FLAGS_REG flag assignments */
@@ -75,6 +76,9 @@
* hypervisors should instead only be output to local targets
*/
MLF_LOCAL_ONLY = (1 << MLF_LOCAL_ONLY_BIT),
+
+ /* Indicate that a packet was received from a nested container. */
+ MLF_NESTED_CONTAINER = (1 << MLF_NESTED_CONTAINER_BIT),
};
#endif /* ovn/lib/logical-fields.h */
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovn/lib/ovn-l7.h openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovn/lib/ovn-l7.h
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovn/lib/ovn-l7.h 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovn/lib/ovn-l7.h 2020-03-11 16:15:44.000000000 +0000
@@ -70,6 +70,8 @@
#define DHCP_OPT_T1 DHCP_OPTION("T1", 58, "uint32")
#define DHCP_OPT_T2 DHCP_OPTION("T2", 59, "uint32")
+#define DHCP_OPT_WPAD DHCP_OPTION("wpad", 252, "str")
+
static inline uint32_t
gen_opt_hash(char *opt_name)
{
@@ -149,6 +151,7 @@
#define DHCPV6_MSG_TYPE_CONFIRM 4
#define DHCPV6_MSG_TYPE_REPLY 7
#define DHCPV6_MSG_TYPE_DECLINE 9
+#define DHCPV6_MSG_TYPE_INFO_REQ 11
/* DHCPv6 Option codes */
@@ -242,7 +245,8 @@
#define IPV6_ND_RA_REACHABLE_TIME 0
#define IPV6_ND_RA_RETRANSMIT_TIMER 0
-#define IPV6_ND_RA_OPT_PREFIX_FLAGS 0xc0
+#define IPV6_ND_RA_OPT_PREFIX_ON_LINK 0x80
+#define IPV6_ND_RA_OPT_PREFIX_AUTONOMOUS 0x40
#define IPV6_ND_RA_OPT_PREFIX_VALID_LIFETIME 0xffffffff
#define IPV6_ND_RA_OPT_PREFIX_PREFERRED_LIFETIME 0xffffffff
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovn/northd/ovn-northd.8.xml openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovn/northd/ovn-northd.8.xml
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovn/northd/ovn-northd.8.xml 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovn/northd/ovn-northd.8.xml 2020-03-11 16:15:44.000000000 +0000
@@ -2055,6 +2055,30 @@
+ Unknown MAC address. For each IPv6 static route associated with the
+ router with the nexthop IP: G, a priority-200 flow
+ for IPv6 packets with match
+ eth.dst == 00:00:00:00:00:00 &&
+ xxreg0 == G
+ with the following actions is added:
+
+
+
+nd_ns {
+ eth.dst = E;
+ ip6.dst = I
+ nd.target = G;
+ output;
+};
+
+
+
+ Where E is the multicast mac derived from the Gateway IP,
+ I is the solicited-node multicast address corresponding
+ to the target address G.
+
+
+
Unknown MAC address. A priority-100 flow for IPv6 packets with match
eth.dst == 00:00:00:00:00:00 has the following actions:
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovn/northd/ovn-northd.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovn/northd/ovn-northd.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovn/northd/ovn-northd.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovn/northd/ovn-northd.c 2020-03-11 16:15:44.000000000 +0000
@@ -385,6 +385,7 @@
if (uuid_equals(&chassis->header_.uuid, &node->chassis_uuid)
&& node->queue_id == queue_id) {
hmap_remove(set, &node->key_node);
+ free(node);
break;
}
}
@@ -1400,7 +1401,7 @@
}
}
- if (!nbsp->n_addresses && nbsp->dynamic_addresses) {
+ if (!num_dynamic_addresses && nbsp->dynamic_addresses) {
nbrec_logical_switch_port_set_dynamic_addresses(nbsp, NULL);
}
}
@@ -1613,7 +1614,6 @@
}
op->od = od;
- ipam_add_port_addresses(od, op);
tag_alloc_add_existing_tags(tag_alloc_table, nbsp);
}
} else {
@@ -1657,7 +1657,6 @@
op->lrp_networks = lrp_networks;
op->od = od;
- ipam_add_port_addresses(op->od, op);
const char *redirect_chassis = smap_get(&op->nbrp->options,
"redirect-chassis");
@@ -1759,6 +1758,8 @@
}
}
}
+
+ ipam_add_port_addresses(op->od, op);
}
}
@@ -3203,7 +3204,7 @@
uint16_t *port, int *addr_family)
{
struct sockaddr_storage ss;
- if (!inet_parse_active(key, 0, &ss)) {
+ if (!inet_parse_active(key, 0, &ss, false)) {
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
VLOG_WARN_RL(&rl, "bad ip address or port for load balancer key %s",
key);
@@ -6206,13 +6207,10 @@
continue;
}
- /* Add the prefix option if the address mode is slaac or
- * dhcpv6_stateless. */
- if (strcmp(address_mode, "dhcpv6_stateful")) {
- ds_put_format(&actions, ", prefix = %s/%u",
- op->lrp_networks.ipv6_addrs[i].network_s,
- op->lrp_networks.ipv6_addrs[i].plen);
- }
+ ds_put_format(&actions, ", prefix = %s/%u",
+ op->lrp_networks.ipv6_addrs[i].network_s,
+ op->lrp_networks.ipv6_addrs[i].plen);
+
add_rs_response_flow = true;
}
@@ -6542,6 +6540,42 @@
continue;
}
+ for (int i = 0; i < od->nbr->n_static_routes; i++) {
+ const struct nbrec_logical_router_static_route *route;
+
+ route = od->nbr->static_routes[i];
+ struct in6_addr gw_ip6;
+ unsigned int plen;
+ char *error = ipv6_parse_cidr(route->nexthop, &gw_ip6, &plen);
+ if (error || plen != 128) {
+ free(error);
+ continue;
+ }
+
+ ds_clear(&match);
+ ds_put_format(&match, "eth.dst == 00:00:00:00:00:00 && "
+ "ip6 && xxreg0 == %s", route->nexthop);
+ struct in6_addr sn_addr;
+ struct eth_addr eth_dst;
+ in6_addr_solicited_node(&sn_addr, &gw_ip6);
+ ipv6_multicast_to_ethernet(ð_dst, &sn_addr);
+
+ char sn_addr_s[INET6_ADDRSTRLEN + 1];
+ ipv6_string_mapped(sn_addr_s, &sn_addr);
+
+ ds_clear(&actions);
+ ds_put_format(&actions,
+ "nd_ns { "
+ "eth.dst = "ETH_ADDR_FMT"; "
+ "ip6.dst = %s; "
+ "nd.target = %s; "
+ "output; "
+ "};", ETH_ADDR_ARGS(eth_dst), sn_addr_s,
+ route->nexthop);
+ ovn_lflow_add(lflows, od, S_ROUTER_IN_ARP_REQUEST, 200,
+ ds_cstr(&match), ds_cstr(&actions));
+ }
+
ovn_lflow_add(lflows, od, S_ROUTER_IN_ARP_REQUEST, 100,
"eth.dst == 00:00:00:00:00:00",
"arp { "
@@ -6913,7 +6947,7 @@
for (size_t i = 0; i < nb_meter->n_bands; i++) {
if (nb_bands[i].rate != sb_bands[i].rate
|| nb_bands[i].burst_size != sb_bands[i].burst_size
- || strcmp(nb_bands[i].action, nb_bands[i].action)) {
+ || strcmp(nb_bands[i].action, sb_bands[i].action)) {
need_update = true;
goto done;
}
@@ -7214,7 +7248,8 @@
DHCP_OPT_MTU,
DHCP_OPT_LEASE_TIME,
DHCP_OPT_T1,
- DHCP_OPT_T2
+ DHCP_OPT_T2,
+ DHCP_OPT_WPAD,
};
static struct gen_opts_map supported_dhcpv6_opts[] = {
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovn/ovn-nb.xml openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovn/ovn-nb.xml
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovn/ovn-nb.xml 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovn/ovn-nb.xml 2020-03-11 16:15:44.000000000 +0000
@@ -1991,6 +1991,7 @@
Microsoft Windows DHCPv4 clients.
+
@@ -2055,6 +2056,20 @@
for this option is 59.
+
+
+
+ These options accept a string value.
+
+
+
+
+ The DHCPv4 option code for this option is 252. This option is used
+ as part of web proxy auto discovery to provide a URL for a web
+ proxy.
+
+
+
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovn/utilities/ovn-ctl openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovn/utilities/ovn-ctl
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovn/utilities/ovn-ctl 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovn/utilities/ovn-ctl 2020-03-11 16:15:44.000000000 +0000
@@ -95,7 +95,7 @@
start_ovsdb__() {
local DB=$1 db=$2 schema_name=$3 table_name=$4
- local pid
+ local db_pid_file
local cluster_local_addr
local cluster_local_port
local cluster_local_proto
@@ -116,7 +116,10 @@
local addr
local active_conf_file
local use_remote_in_db
- eval pid=\$DB_${DB}_PID
+ local ovn_db_ssl_key
+ local ovn_db_ssl_cert
+ local ovn_db_ssl_cacert
+ eval db_pid_file=\$DB_${DB}_PID
eval cluster_local_addr=\$DB_${DB}_CLUSTER_LOCAL_ADDR
eval cluster_local_port=\$DB_${DB}_CLUSTER_LOCAL_PORT
eval cluster_local_proto=\$DB_${DB}_CLUSTER_LOCAL_PROTO
@@ -137,9 +140,12 @@
eval addr=\$DB_${DB}_ADDR
eval active_conf_file=\$ovn${db}_active_conf_file
eval use_remote_in_db=\$DB_${DB}_USE_REMOTE_IN_DB
+ eval ovn_db_ssl_key=\$OVN_${DB}_DB_SSL_KEY
+ eval ovn_db_ssl_cert=\$OVN_${DB}_DB_SSL_CERT
+ eval ovn_db_ssl_cacert=\$OVN_${DB}_DB_SSL_CA_CERT
# Check and eventually start ovsdb-server for DB
- if pidfile_is_running $pid; then
+ if pidfile_is_running $db_pid_file; then
return
fi
@@ -169,7 +175,7 @@
set ovsdb-server
set "$@" $log --log-file=$logfile
- set "$@" --remote=punix:$sock --pidfile=$pid
+ set "$@" --remote=punix:$sock --pidfile=$db_pid_file
set "$@" --unixctl=ovn${db}_db.ctl
if test X"$detach" != Xno; then
@@ -181,9 +187,23 @@
if test X"$use_remote_in_db" != Xno; then
set "$@" --remote=db:$schema_name,$table_name,connections
fi
- set "$@" --private-key=db:$schema_name,SSL,private_key
- set "$@" --certificate=db:$schema_name,SSL,certificate
- set "$@" --ca-cert=db:$schema_name,SSL,ca_cert
+
+ if test X"$ovn_db_ssl_key" != X; then
+ set "$@" --private-key=$ovn_db_ssl_key
+ else
+ set "$@" --private-key=db:$schema_name,SSL,private_key
+ fi
+ if test X"$ovn_db_ssl_cert" != X; then
+ set "$@" --certificate=$ovn_db_ssl_cert
+ else
+ set "$@" --certificate=db:$schema_name,SSL,certificate
+ fi
+ if test X"$ovn_db_ssl_cacert" != X; then
+ set "$@" --ca-cert=$ovn_db_ssl_cacert
+ else
+ set "$@" --ca-cert=db:$schema_name,SSL,ca_cert
+ fi
+
set "$@" --ssl-protocols=db:$schema_name,SSL,ssl_protocols
set "$@" --ssl-ciphers=db:$schema_name,SSL,ssl_ciphers
@@ -200,7 +220,7 @@
# Initialize the database if it's running standalone,
# active-passive, or is the first server in a cluster.
if test -z "$cluster_remote_addr"; then
- ovn-nbctl init
+ ovn-${db}ctl init
fi
if test $mode = cluster; then
@@ -469,6 +489,15 @@
OVN_NORTHD_SB_DB="unix:$DB_SB_SOCK"
DB_NB_USE_REMOTE_IN_DB="yes"
DB_SB_USE_REMOTE_IN_DB="yes"
+
+ OVN_NB_DB_SSL_KEY=""
+ OVN_NB_DB_SSL_CERT=""
+ OVN_NB_DB_SSL_CA_CERT=""
+
+ OVN_SB_DB_SSL_KEY=""
+ OVN_SB_DB_SSL_CERT=""
+ OVN_SB_DB_SSL_CA_CERT=""
+
}
set_option () {
@@ -524,6 +553,12 @@
--ovn-controller-ssl-cert=CERT OVN Southbound SSL certificate file
--ovn-controller-ssl-ca-cert=CERT OVN Southbound SSL CA certificate file
--ovn-controller-ssl-bootstrap-ca-cert=CERT Bootstrapped OVN Southbound SSL CA certificate file
+ --ovn-nb-db-ssl-key=KEY OVN Northbound DB SSL private key file
+ --ovn-nb-db-ssl-cert=CERT OVN Northbound DB SSL certificate file
+ --ovn-nb-db-ssl-ca-cert=CERT OVN Northbound DB SSL CA certificate file
+ --ovn-sb-db-ssl-key=KEY OVN Southbound DB SSL private key file
+ --ovn-sb-db-ssl-cert=CERT OVN Southbound DB SSL certificate file
+ --ovn-sb-db-ssl-ca-cert=CERT OVN Southbound DB SSL CA certificate file
--ovn-manage-ovsdb=yes|no Whether or not the OVN databases should be
automatically started and stopped along
with ovn-northd. The default is "yes". If
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovn/utilities/ovn-ctl.8.xml openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovn/utilities/ovn-ctl.8.xml
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovn/utilities/ovn-ctl.8.xml 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovn/utilities/ovn-ctl.8.xml 2020-03-11 16:15:44.000000000 +0000
@@ -196,4 +196,18 @@
start_northd
+
+ Passing ssl keys when starting OVN dbs will supercede the default ssl values in db
+ Starting standalone ovn db server passing SSL certificates
+
+
+ # ovn-ctl --ovn-nb-db-ssl-key=/etc/openvswitch/ovnnb-privkey.pem
+ --ovn-nb-db-ssl-cert=/etc/openvswitch/ovnnb-cert.pem
+ --ovn-nb-db-ssl-ca-cert=/etc/openvswitch/cacert.pem
+ --ovn-sb-db-ssl-key=/etc/openvswitch/ovnsb-privkey.pem
+ --ovn-sb-db-ssl-cert=/etc/openvswitch/ovnsb-cert.pem
+ --ovn-sb-db-ssl-ca-cert=/etc/openvswitch/cacert.pem
+ start_northd
+
+
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovn/utilities/ovndb-servers.ocf openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovn/utilities/ovndb-servers.ocf
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovn/utilities/ovndb-servers.ocf 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovn/utilities/ovndb-servers.ocf 2020-03-11 16:15:44.000000000 +0000
@@ -10,6 +10,12 @@
: ${MANAGE_NORTHD_DEFAULT="no"}
: ${INACTIVE_PROBE_DEFAULT="5000"}
: ${LISTEN_ON_MASTER_IP_ONLY_DEFAULT="yes"}
+: ${NB_SSL_KEY_DEFAULT="/etc/openvswitch/ovnnb-privkey.pem"}
+: ${NB_SSL_CERT_DEFAULT="/etc/openvswitch/ovnnb-cert.pem"}
+: ${NB_SSL_CACERT_DEFAULT="/etc/openvswitch/cacert.pem"}
+: ${SB_SSL_KEY_DEFAULT="/etc/openvswitch/ovnsb-privkey.pem"}
+: ${SB_SSL_CERT_DEFAULT="/etc/openvswitch/ovnsb-cert.pem"}
+: ${SB_SSL_CACERT_DEFAULT="/etc/openvswitch/cacert.pem"}
CRM_MASTER="${HA_SBIN_DIR}/crm_master -l reboot"
CRM_ATTR_REPL_INFO="${HA_SBIN_DIR}/crm_attribute --type crm_config --name OVN_REPL_INFO -s ovn_ovsdb_master_server"
@@ -21,6 +27,13 @@
SB_MASTER_PROTO=${OCF_RESKEY_sb_master_protocol:-${SB_MASTER_PROTO_DEFAULT}}
MANAGE_NORTHD=${OCF_RESKEY_manage_northd:-${MANAGE_NORTHD_DEFAULT}}
INACTIVE_PROBE=${OCF_RESKEY_inactive_probe_interval:-${INACTIVE_PROBE_DEFAULT}}
+NB_PRIVKEY=${OCF_RESKEY_ovn_nb_db_privkey:-${NB_SSL_KEY_DEFAULT}}
+NB_CERT=${OCF_RESKEY_ovn_nb_db_cert:-${NB_SSL_CERT_DEFAULT}}
+NB_CACERT=${OCF_RESKEY_ovn_nb_db_cacert:-${NB_SSL_CACERT_DEFAULT}}
+SB_PRIVKEY=${OCF_RESKEY_ovn_sb_db_privkey:-${SB_SSL_KEY_DEFAULT}}
+SB_CERT=${OCF_RESKEY_ovn_sb_db_cert:-${SB_SSL_CERT_DEFAULT}}
+SB_CACERT=${OCF_RESKEY_ovn_sb_db_cacert:-${SB_SSL_CACERT_DEFAULT}}
+
# In order for pacemaker to work with LB, we can set LISTEN_ON_MASTER_IP_ONLY
# to false and pass LB vip IP while creating pcs resource.
@@ -132,6 +145,54 @@
+
+
+ OVN NB DB private key absolute path for ssl setup.
+
+ OVN NB DB private key file
+
+
+
+
+
+ OVN NB DB certificate absolute path for ssl setup.
+
+ OVN NB DB cert file
+
+
+
+
+
+ OVN NB DB CA certificate absolute path for ssl setup.
+
+ OVN NB DB cacert file
+
+
+
+
+
+ OVN SB DB private key absolute path for ssl setup.
+
+ OVN SB DB private key file
+
+
+
+
+
+ OVN SB DB certificate absolute path for ssl setup.
+
+ OVN SB DB cert file
+
+
+
+
+
+ OVN SB DB CA certificate absolute path for ssl setup.
+
+ OVN SB DB cacert file
+
+
+
@@ -326,6 +387,16 @@
set $@ --db-sb-addr=${MASTER_IP} --db-sb-port=${SB_MASTER_PORT}
fi
+ if [ "x${NB_MASTER_PROTO}" = xssl ]; then
+ set $@ --ovn-nb-db-ssl-key=${NB_PRIVKEY}
+ set $@ --ovn-nb-db-ssl-cert=${NB_CERT}
+ set $@ --ovn-nb-db-ssl-ca-cert=${NB_CACERT}
+ fi
+ if [ "x${SB_MASTER_PROTO}" = xssl ]; then
+ set $@ --ovn-sb-db-ssl-key=${SB_PRIVKEY}
+ set $@ --ovn-sb-db-ssl-cert=${SB_CERT}
+ set $@ --ovn-sb-db-ssl-ca-cert=${SB_CACERT}
+ fi
if [ "x${present_master}" = x ]; then
# No master detected, or the previous master is not among the
# set starting.
@@ -343,7 +414,6 @@
set $@ --db-nb-sync-from-addr=${INVALID_IP_ADDRESS} --db-sb-sync-from-addr=${INVALID_IP_ADDRESS}
elif [ ${present_master} != ${host_name} ]; then
- # TODO: for using LB vip, need to test for ssl.
if [ "x${LISTEN_ON_MASTER_IP_ONLY}" = xyes ]; then
if [ "x${NB_MASTER_PROTO}" = xtcp ]; then
set $@ --db-nb-create-insecure-remote=yes
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovn/utilities/ovn-nbctl.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovn/utilities/ovn-nbctl.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovn/utilities/ovn-nbctl.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovn/utilities/ovn-nbctl.c 2020-03-11 16:15:44.000000000 +0000
@@ -117,7 +117,7 @@
size_t n_commands,
struct ovsdb_idl *idl,
const struct timer *);
-static void server_loop(struct ovsdb_idl *idl);
+static void server_loop(struct ovsdb_idl *idl, int argc, char *argv[]);
int
main(int argc, char *argv[])
@@ -173,26 +173,24 @@
shash_init(&local_options);
apply_options_direct(parsed_options, n_parsed_options, &local_options);
free(parsed_options);
- argc -= optind;
- argv += optind;
/* Initialize IDL. */
idl = the_idl = ovsdb_idl_create(db, &nbrec_idl_class, true, false);
ovsdb_idl_set_leader_only(idl, leader_only);
if (get_detach()) {
- if (argc != 0) {
+ if (argc != optind) {
ctl_fatal("non-option arguments not supported with --detach "
"(use --help for help)");
}
- server_loop(idl);
+ server_loop(idl, argc, argv);
} else {
struct ctl_command *commands;
size_t n_commands;
char *error;
- error = ctl_parse_commands(argc, argv, &local_options, &commands,
- &n_commands);
+ error = ctl_parse_commands(argc - optind, argv + optind,
+ &local_options, &commands, &n_commands);
if (error) {
ctl_fatal("%s", error);
}
@@ -2555,7 +2553,7 @@
}
struct sockaddr_storage ss_vip;
- if (!inet_parse_active(lb_vip, 0, &ss_vip)) {
+ if (!inet_parse_active(lb_vip, 0, &ss_vip, false)) {
ctl_error(ctx, "%s: should be an IP address (or an IP address "
"and a port number with : as a separator).", lb_vip);
return;
@@ -2585,7 +2583,7 @@
struct sockaddr_storage ss_dst;
if (lb_vip_port) {
- if (!inet_parse_active(token, -1, &ss_dst)) {
+ if (!inet_parse_active(token, -1, &ss_dst, false)) {
ctl_error(ctx, "%s: should be an IP address and a port "
"number with : as a separator.", token);
goto out;
@@ -2704,7 +2702,7 @@
const struct smap_node *node = nodes[i];
struct sockaddr_storage ss;
- if (!inet_parse_active(node->key, 0, &ss)) {
+ if (!inet_parse_active(node->key, 0, &ss, false)) {
continue;
}
@@ -5233,6 +5231,7 @@
}
struct ds output = DS_EMPTY_INITIALIZER;
+ table_format_reset();
for (struct ctl_command *c = commands; c < &commands[n_commands]; c++) {
if (c->table) {
table_format(c->table, &table_style, &output);
@@ -5271,11 +5270,12 @@
}
static void
-server_loop(struct ovsdb_idl *idl)
+server_loop(struct ovsdb_idl *idl, int argc, char *argv[])
{
struct unixctl_server *server = NULL;
bool exiting = false;
+ service_start(&argc, &argv);
daemonize_start(false);
int error = unixctl_server_create(unixctl_path, &server);
if (error) {
@@ -5365,7 +5365,6 @@
break;
VLOG_OPTION_HANDLERS
- TABLE_OPTION_HANDLERS(&table_style)
case OPT_LOCAL:
default:
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovsdb/condition.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovsdb/condition.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovsdb/condition.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovsdb/condition.c 2020-03-11 16:15:44.000000000 +0000
@@ -125,7 +125,12 @@
free(s);
return error;
}
+
+ /* Force the argument to be a scalar. */
+ type.n_min = 1;
+
break;
+
case OVSDB_F_EQ:
case OVSDB_F_NE:
break;
@@ -338,24 +343,17 @@
c->function == OVSDB_F_FALSE) {
return c->function == OVSDB_F_TRUE;
}
- if (ovsdb_type_is_optional_scalar(type) && field->n == 0) {
- switch (c->function) {
- case OVSDB_F_LT:
- case OVSDB_F_LE:
- case OVSDB_F_EQ:
- case OVSDB_F_GE:
- case OVSDB_F_GT:
- case OVSDB_F_INCLUDES:
- return false;
- case OVSDB_F_NE:
- case OVSDB_F_EXCLUDES:
- return true;
- case OVSDB_F_TRUE:
- case OVSDB_F_FALSE:
- OVS_NOT_REACHED();
- }
- } else if (ovsdb_type_is_scalar(type)
- || ovsdb_type_is_optional_scalar(type)) {
+ if (ovsdb_type_is_optional_scalar(type)
+ && field->n == 0
+ && (c->function == OVSDB_F_LT ||
+ c->function == OVSDB_F_LE ||
+ c->function == OVSDB_F_GT ||
+ c->function == OVSDB_F_GE)) {
+ return false;
+ } else if ((ovsdb_type_is_scalar(type)
+ || ovsdb_type_is_optional_scalar(type))
+ && field->n == 1
+ && arg->n == 1) {
int cmp = ovsdb_atom_compare_3way(&field->keys[0], &arg->keys[0],
type->key.type);
switch (c->function) {
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovsdb/file.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovsdb/file.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovsdb/file.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovsdb/file.c 2020-03-11 16:15:44.000000000 +0000
@@ -235,10 +235,14 @@
continue;
}
+ ovsdb_datum_destroy(&dst_row->fields[dst_column->index],
+ &dst_column->type);
+
struct ovsdb_error *error = ovsdb_datum_convert(
&dst_row->fields[dst_column->index], &dst_column->type,
&src_row->fields[src_column->index], &src_column->type);
if (error) {
+ ovsdb_datum_init_empty(&dst_row->fields[dst_column->index]);
ovsdb_row_destroy(dst_row);
return error;
}
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovsdb/monitor.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovsdb/monitor.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovsdb/monitor.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovsdb/monitor.c 2020-03-11 16:15:44.000000000 +0000
@@ -120,6 +120,12 @@
struct hmap rows;
int n_refs;
uint64_t transaction;
+
+ /* Save the mt->n_columns that is used when creating the changes.
+ * It can be different from the current mt->n_columns because
+ * mt->n_columns can be increased when there are condition changes
+ * from any of the clients sharing the dbmon. */
+ size_t n_columns;
};
/* A particular table being monitored. */
@@ -156,7 +162,8 @@
const struct ovsdb_monitor_session_condition * condition,
enum ovsdb_monitor_row_type row_type,
const void *,
- bool initial, unsigned long int *changed);
+ bool initial, unsigned long int *changed,
+ size_t n_columns);
static void ovsdb_monitor_destroy(struct ovsdb_monitor *dbmon);
static struct ovsdb_monitor_changes * ovsdb_monitor_table_add_changes(
@@ -255,14 +262,15 @@
return NULL;
}
-/* Allocates an array of 'mt->n_columns' ovsdb_datums and initializes them as
+/* Allocates an array of 'n_columns' ovsdb_datums and initializes them as
* copies of the data in 'row' drawn from the columns represented by
* mt->columns[]. Returns the array.
*
* If 'row' is NULL, returns NULL. */
static struct ovsdb_datum *
clone_monitor_row_data(const struct ovsdb_monitor_table *mt,
- const struct ovsdb_row *row)
+ const struct ovsdb_row *row,
+ size_t n_columns)
{
struct ovsdb_datum *data;
size_t i;
@@ -271,8 +279,8 @@
return NULL;
}
- data = xmalloc(mt->n_columns * sizeof *data);
- for (i = 0; i < mt->n_columns; i++) {
+ data = xmalloc(n_columns * sizeof *data);
+ for (i = 0; i < n_columns; i++) {
const struct ovsdb_column *c = mt->columns[i].column;
const struct ovsdb_datum *src = &row->fields[c->index];
struct ovsdb_datum *dst = &data[i];
@@ -283,16 +291,17 @@
return data;
}
-/* Replaces the mt->n_columns ovsdb_datums in row[] by copies of the data from
+/* Replaces the n_columns ovsdb_datums in row[] by copies of the data from
* in 'row' drawn from the columns represented by mt->columns[]. */
static void
update_monitor_row_data(const struct ovsdb_monitor_table *mt,
const struct ovsdb_row *row,
- struct ovsdb_datum *data)
+ struct ovsdb_datum *data,
+ size_t n_columns)
{
size_t i;
- for (i = 0; i < mt->n_columns; i++) {
+ for (i = 0; i < n_columns; i++) {
const struct ovsdb_column *c = mt->columns[i].column;
const struct ovsdb_datum *src = &row->fields[c->index];
struct ovsdb_datum *dst = &data[i];
@@ -305,16 +314,17 @@
}
}
-/* Frees all of the mt->n_columns ovsdb_datums in data[], using the types taken
+/* Frees all of the n_columns ovsdb_datums in data[], using the types taken
* from mt->columns[], plus 'data' itself. */
static void
free_monitor_row_data(const struct ovsdb_monitor_table *mt,
- struct ovsdb_datum *data)
+ struct ovsdb_datum *data,
+ size_t n_columns)
{
if (data) {
size_t i;
- for (i = 0; i < mt->n_columns; i++) {
+ for (i = 0; i < n_columns; i++) {
const struct ovsdb_column *c = mt->columns[i].column;
ovsdb_datum_destroy(&data[i], &c->type);
@@ -326,11 +336,12 @@
/* Frees 'row', which must have been created from 'mt'. */
static void
ovsdb_monitor_row_destroy(const struct ovsdb_monitor_table *mt,
- struct ovsdb_monitor_row *row)
+ struct ovsdb_monitor_row *row,
+ size_t n_columns)
{
if (row) {
- free_monitor_row_data(mt, row->old);
- free_monitor_row_data(mt, row->new);
+ free_monitor_row_data(mt, row->old, n_columns);
+ free_monitor_row_data(mt, row->new, n_columns);
free(row);
}
}
@@ -492,6 +503,7 @@
changes->transaction = next_txn;
changes->mt = mt;
changes->n_refs = 1;
+ changes->n_columns = mt->n_columns;
hmap_init(&changes->rows);
hmap_insert(&mt->changes, &changes->hmap_node, hash_uint64(next_txn));
@@ -552,7 +564,7 @@
HMAP_FOR_EACH_SAFE (row, next, hmap_node, &changes->rows) {
hmap_remove(&changes->rows, &row->hmap_node);
- ovsdb_monitor_row_destroy(changes->mt, row);
+ ovsdb_monitor_row_destroy(changes->mt, row, changes->n_columns);
}
hmap_destroy(&changes->rows);
free(changes);
@@ -788,7 +800,8 @@
const struct ovsdb_datum *old,
const struct ovsdb_datum *new,
enum ovsdb_monitor_selection type,
- unsigned long int *changed)
+ unsigned long int *changed,
+ size_t n_columns)
{
if (!(mt->select & type)) {
return true;
@@ -798,8 +811,8 @@
size_t i, n_changes;
n_changes = 0;
- memset(changed, 0, bitmap_n_bytes(mt->n_columns));
- for (i = 0; i < mt->n_columns; i++) {
+ memset(changed, 0, bitmap_n_bytes(n_columns));
+ for (i = 0; i < n_columns; i++) {
const struct ovsdb_column *c = mt->columns[i].column;
size_t index = row_type == OVSDB_ROW ? c->index : i;
if (!ovsdb_datum_equals(&old[index], &new[index], &c->type)) {
@@ -825,14 +838,15 @@
* going to be used as part of an "update" notification.
*
* 'changed' must be a scratch buffer for internal use that is at least
- * bitmap_n_bytes(mt->n_columns) bytes long. */
+ * bitmap_n_bytes(n_columns) bytes long. */
static struct json *
ovsdb_monitor_compose_row_update(
const struct ovsdb_monitor_table *mt,
const struct ovsdb_monitor_session_condition *condition OVS_UNUSED,
enum ovsdb_monitor_row_type row_type OVS_UNUSED,
const void *_row,
- bool initial, unsigned long int *changed)
+ bool initial, unsigned long int *changed,
+ size_t n_columns OVS_UNUSED)
{
const struct ovsdb_monitor_row *row = _row;
enum ovsdb_monitor_selection type;
@@ -843,7 +857,8 @@
ovs_assert(row_type == OVSDB_MONITOR_ROW);
type = ovsdb_monitor_row_update_type(initial, row->old, row->new);
if (ovsdb_monitor_row_skip_update(mt, row_type, row->old,
- row->new, type, changed)) {
+ row->new, type, changed,
+ mt->n_columns)) {
return NULL;
}
@@ -891,14 +906,15 @@
* false if it is going to be used as part of an "update2" notification.
*
* 'changed' must be a scratch buffer for internal use that is at least
- * bitmap_n_bytes(mt->n_columns) bytes long. */
+ * bitmap_n_bytes(n_columns) bytes long. */
static struct json *
ovsdb_monitor_compose_row_update2(
const struct ovsdb_monitor_table *mt,
const struct ovsdb_monitor_session_condition *condition,
enum ovsdb_monitor_row_type row_type,
const void *_row,
- bool initial, unsigned long int *changed)
+ bool initial, unsigned long int *changed,
+ size_t n_columns)
{
enum ovsdb_monitor_selection type;
struct json *row_update2, *diff_json;
@@ -914,7 +930,8 @@
type = ovsdb_monitor_row_update_type_condition(mt, condition, initial,
row_type, old, new);
- if (ovsdb_monitor_row_skip_update(mt, row_type, old, new, type, changed)) {
+ if (ovsdb_monitor_row_skip_update(mt, row_type, old, new, type, changed,
+ n_columns)) {
return NULL;
}
@@ -1032,7 +1049,7 @@
HMAP_FOR_EACH_SAFE (row, next, hmap_node, &changes->rows) {
struct json *row_json;
row_json = (*row_update)(mt, condition, OVSDB_MONITOR_ROW, row,
- initial, changed);
+ initial, changed, changes->n_columns);
if (row_json) {
ovsdb_monitor_add_json_row(&json, mt->table->schema->name,
&table_json, row_json,
@@ -1076,7 +1093,8 @@
row_json = ovsdb_monitor_compose_row_update2(mt, condition,
OVSDB_ROW, row,
- false, changed);
+ false, changed,
+ mt->n_columns);
if (row_json) {
ovsdb_monitor_add_json_row(&json, mt->table->schema->name,
&table_json, row_json,
@@ -1235,8 +1253,8 @@
change = xzalloc(sizeof *change);
hmap_insert(&changes->rows, &change->hmap_node, uuid_hash(uuid));
change->uuid = *uuid;
- change->old = clone_monitor_row_data(mt, old);
- change->new = clone_monitor_row_data(mt, new);
+ change->old = clone_monitor_row_data(mt, old, changes->n_columns);
+ change->new = clone_monitor_row_data(mt, new, changes->n_columns);
} else {
if (new) {
if (!change->new) {
@@ -1275,12 +1293,14 @@
* replication, the row carries the same UUID as the row
* just deleted.
*/
- change->new = clone_monitor_row_data(mt, new);
+ change->new = clone_monitor_row_data(mt, new,
+ changes->n_columns);
} else {
- update_monitor_row_data(mt, new, change->new);
+ update_monitor_row_data(mt, new, change->new,
+ changes->n_columns);
}
} else {
- free_monitor_row_data(mt, change->new);
+ free_monitor_row_data(mt, change->new, changes->n_columns);
change->new = NULL;
if (!change->old) {
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovsdb/mutation.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovsdb/mutation.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovsdb/mutation.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovsdb/mutation.c 2020-03-11 16:15:44.000000000 +0000
@@ -147,6 +147,8 @@
if (error && ovsdb_type_is_map(&m->type)
&& m->mutator == OVSDB_M_DELETE) {
ovsdb_error_destroy(error);
+ ovsdb_base_type_destroy(&m->type.value);
+ m->type.value.enum_ = NULL;
m->type.value.type = OVSDB_TYPE_VOID;
error = ovsdb_datum_from_json(&m->arg, &m->type, array->elems[2],
symtab);
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovsdb/ovsdb-client.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovsdb/ovsdb-client.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovsdb/ovsdb-client.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovsdb/ovsdb-client.c 2020-03-11 16:15:44.000000000 +0000
@@ -1269,7 +1269,7 @@
jsonrpc_send(rpc, request);
VLOG_DBG("cond change %s %s", argv[1], argv[2]);
- unixctl_command_reply(conn, "condiiton changed");
+ unixctl_command_reply(conn, "condition changed");
}
static void
@@ -1763,9 +1763,9 @@
for (i = 1; i < argc; i++) {
node = shash_find(&tschema->columns, argv[i]);
if (!node) {
- ovs_fatal(0, "Table \"%s\" has no column %s.", argv[0], argv[1]);
+ ovs_fatal(0, "Table \"%s\" has no column %s.", argv[0], argv[i]);
}
- shash_add(&custom_columns, argv[1], node->data);
+ shash_add(&custom_columns, argv[i], node->data);
}
} else {
tables = shash_sort(&schema->tables);
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovsdb/ovsdb-idlc.in openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovsdb/ovsdb-idlc.in
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovsdb/ovsdb-idlc.in 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovsdb/ovsdb-idlc.in 2020-03-11 16:15:44.000000000 +0000
@@ -1192,7 +1192,7 @@
%(s)s_index_init_row(struct ovsdb_idl_index *index)
{
ovs_assert(index->table->class_ == &%(p)stable_%(tl)s);
- return (struct %(s)s *) ovsdb_idl_index_init_row(index);
+ return ALIGNED_CAST(struct %(s)s *, ovsdb_idl_index_init_row(index));
}
struct %(s)s *
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovsdb/raft.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovsdb/raft.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovsdb/raft.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovsdb/raft.c 2020-03-11 16:15:44.000000000 +0000
@@ -296,6 +296,7 @@
struct raft *, const struct uuid *target_sid,
const struct uuid *requester_sid, struct unixctl_conn *requester_conn,
bool success, const char *comment);
+static void raft_finished_leaving_cluster(struct raft *);
static void raft_server_init_leader(struct raft *, struct raft_server *);
@@ -303,9 +304,16 @@
static bool raft_is_rpc_synced(const struct raft *, const union raft_rpc *);
static void raft_handle_rpc(struct raft *, const union raft_rpc *);
-static bool raft_send(struct raft *, const union raft_rpc *);
-static bool raft_send__(struct raft *, const union raft_rpc *,
- struct raft_conn *);
+
+static bool raft_send_at(struct raft *, const union raft_rpc *,
+ int line_number);
+#define raft_send(raft, rpc) raft_send_at(raft, rpc, __LINE__)
+
+static bool raft_send_to_conn_at(struct raft *, const union raft_rpc *,
+ struct raft_conn *, int line_number);
+#define raft_send_to_conn(raft, rpc, conn) \
+ raft_send_to_conn_at(raft, rpc, conn, __LINE__)
+
static void raft_send_append_request(struct raft *,
struct raft_server *, unsigned int n,
const char *comment);
@@ -1055,7 +1063,7 @@
.term = raft->term,
}
};
- raft_send__(raft, &rpc, conn);
+ raft_send_to_conn(raft, &rpc, conn);
raft_record_note(raft, "transfer leadership",
"transferring leadership to %s because %s",
@@ -1295,14 +1303,18 @@
}
static void
-log_rpc(const union raft_rpc *rpc,
- const char *direction, const struct raft_conn *conn)
+log_rpc(const union raft_rpc *rpc, const char *direction,
+ const struct raft_conn *conn, int line_number)
{
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(600, 600);
if (!raft_rpc_is_heartbeat(rpc) && !VLOG_DROP_DBG(&rl)) {
struct ds s = DS_EMPTY_INITIALIZER;
+ if (line_number) {
+ ds_put_format(&s, "raft.c:%d ", line_number);
+ }
+ ds_put_format(&s, "%s%s ", direction, conn->nickname);
raft_rpc_format(rpc, &s);
- VLOG_DBG("%s%s %s", direction, conn->nickname, ds_cstr(&s));
+ VLOG_DBG("%s", ds_cstr(&s));
ds_destroy(&s);
}
}
@@ -1320,7 +1332,7 @@
.address = raft->local_address,
},
};
- raft_send__(raft, &rq, conn);
+ raft_send_to_conn(raft, &rq, conn);
}
static void
@@ -1345,7 +1357,7 @@
.sid = raft->sid,
},
};
- raft_send__(raft, &rq, conn);
+ raft_send_to_conn(raft, &rq, conn);
} else {
union raft_rpc rq = (union raft_rpc) {
.hello_request = {
@@ -1356,7 +1368,7 @@
.address = raft->local_address,
},
};
- raft_send__(raft, &rq, conn);
+ raft_send_to_conn(raft, &rq, conn);
}
}
@@ -1366,7 +1378,7 @@
break;
}
- log_rpc(&rpc, "<--", conn);
+ log_rpc(&rpc, "<--", conn, 0);
raft_handle_rpc(raft, &rpc);
raft_rpc_uninit(&rpc);
}
@@ -1434,7 +1446,7 @@
struct raft_conn *dst = raft_find_conn_by_sid(raft, &rpc->common.sid);
if (dst) {
- raft_send__(raft, rpc, dst);
+ raft_send_to_conn(raft, rpc, dst);
}
}
@@ -2186,16 +2198,28 @@
}
static void
-raft_send_remove_server_reply_rpc(struct raft *raft, const struct uuid *sid,
+raft_send_remove_server_reply_rpc(struct raft *raft,
+ const struct uuid *dst_sid,
+ const struct uuid *target_sid,
bool success, const char *comment)
{
+ if (uuid_equals(&raft->sid, dst_sid)) {
+ if (success && uuid_equals(&raft->sid, target_sid)) {
+ raft_finished_leaving_cluster(raft);
+ }
+ return;
+ }
+
const union raft_rpc rpy = {
.remove_server_reply = {
.common = {
.type = RAFT_RPC_REMOVE_SERVER_REPLY,
- .sid = *sid,
+ .sid = *dst_sid,
.comment = CONST_CAST(char *, comment),
},
+ .target_sid = (uuid_equals(dst_sid, target_sid)
+ ? UUID_ZERO
+ : *target_sid),
.success = success,
}
};
@@ -2224,6 +2248,9 @@
} else {
char buf[SID_LEN + 1];
ds_put_cstr(&s, raft_get_nickname(raft, target_sid, buf, sizeof buf));
+ if (uuid_equals(target_sid, &raft->sid)) {
+ ds_put_cstr(&s, " (ourselves)");
+ }
}
ds_put_format(&s, " from cluster "CID_FMT" %s",
CID_ARGS(&raft->cid),
@@ -2240,11 +2267,12 @@
* allows it to be sure that it's really removed and update its log and
* disconnect permanently. */
if (!uuid_is_zero(requester_sid)) {
- raft_send_remove_server_reply_rpc(raft, requester_sid,
+ raft_send_remove_server_reply_rpc(raft, requester_sid, target_sid,
success, comment);
}
if (!uuid_equals(requester_sid, target_sid)) {
- raft_send_remove_server_reply_rpc(raft, target_sid, success, comment);
+ raft_send_remove_server_reply_rpc(raft, target_sid, target_sid,
+ success, comment);
}
if (requester_conn) {
if (success) {
@@ -2556,9 +2584,6 @@
while (raft->commit_index < new_commit_index) {
uint64_t index = ++raft->commit_index;
const struct raft_entry *e = raft_get_entry(raft, index);
- if (e->servers) {
- raft_run_reconfigure(raft);
- }
if (e->data) {
struct raft_command *cmd
= raft_find_command_by_index(raft, index);
@@ -2566,6 +2591,12 @@
raft_command_complete(raft, cmd, RAFT_CMD_SUCCESS);
}
}
+ if (e->servers) {
+ /* raft_run_reconfigure() can write a new Raft entry, which can
+ * reallocate raft->entries, which would invalidate 'e', so
+ * this case must be last, after the one for 'e->data'. */
+ raft_run_reconfigure(raft);
+ }
}
} else {
raft->commit_index = new_commit_index;
@@ -3031,8 +3062,10 @@
static void
raft_update_our_match_index(struct raft *raft, uint64_t min_index)
{
- raft_update_match_index(raft, raft_find_server(raft, &raft->sid),
- min_index);
+ struct raft_server *server = raft_find_server(raft, &raft->sid);
+ if (server) {
+ raft_update_match_index(raft, server, min_index);
+ }
}
static void
@@ -3543,17 +3576,25 @@
}
static void
-raft_handle_remove_server_reply(struct raft *raft,
- const struct raft_remove_server_reply *rpc)
+raft_finished_leaving_cluster(struct raft *raft)
{
- if (rpc->success) {
- VLOG_INFO(SID_FMT": finished leaving cluster "CID_FMT,
- SID_ARGS(&raft->sid), CID_ARGS(&raft->cid));
+ VLOG_INFO(SID_FMT": finished leaving cluster "CID_FMT,
+ SID_ARGS(&raft->sid), CID_ARGS(&raft->cid));
- raft_record_note(raft, "left", "this server left the cluster");
+ raft_record_note(raft, "left", "this server left the cluster");
- raft->leaving = false;
- raft->left = true;
+ raft->leaving = false;
+ raft->left = true;
+}
+
+static void
+raft_handle_remove_server_reply(struct raft *raft,
+ const struct raft_remove_server_reply *rpc)
+{
+ if (rpc->success
+ && (uuid_is_zero(&rpc->target_sid)
+ || uuid_equals(&rpc->target_sid, &raft->sid))) {
+ raft_finished_leaving_cluster(raft);
}
}
@@ -4001,10 +4042,10 @@
static bool
-raft_send__(struct raft *raft, const union raft_rpc *rpc,
- struct raft_conn *conn)
+raft_send_to_conn_at(struct raft *raft, const union raft_rpc *rpc,
+ struct raft_conn *conn, int line_number)
{
- log_rpc(rpc, "-->", conn);
+ log_rpc(rpc, "-->", conn, line_number);
return !jsonrpc_session_send(
conn->js, raft_rpc_to_jsonrpc(&raft->cid, &raft->sid, rpc));
}
@@ -4022,12 +4063,13 @@
}
static bool
-raft_send(struct raft *raft, const union raft_rpc *rpc)
+raft_send_at(struct raft *raft, const union raft_rpc *rpc, int line_number)
{
const struct uuid *dst = &rpc->common.sid;
if (uuid_equals(dst, &raft->sid)) {
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
- VLOG_WARN_RL(&rl, "attempting to send RPC to self");
+ VLOG_WARN_RL(&rl, "attempted to send RPC to self from raft.c:%d",
+ line_number);
return false;
}
@@ -4035,9 +4077,10 @@
if (!conn) {
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
char buf[SID_LEN + 1];
- VLOG_DBG_RL(&rl, "%s: no connection to %s, cannot send RPC",
- raft->local_nickname,
- raft_get_nickname(raft, dst, buf, sizeof buf));
+ VLOG_DBG_RL(&rl, "%s: no connection to %s, cannot send RPC "
+ "from raft.c:%d", raft->local_nickname,
+ raft_get_nickname(raft, dst, buf, sizeof buf),
+ line_number);
return false;
}
@@ -4046,7 +4089,7 @@
return true;
}
- return raft_send__(raft, rpc, conn);
+ return raft_send_to_conn_at(raft, rpc, conn, line_number);
}
static struct raft *
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovsdb/raft-private.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovsdb/raft-private.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovsdb/raft-private.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovsdb/raft-private.c 2020-03-11 16:15:44.000000000 +0000
@@ -33,7 +33,7 @@
return NULL;
} else if (!strncmp(address, "ssl:", 4) || !strncmp(address, "tcp:", 4)) {
struct sockaddr_storage ss;
- if (!inet_parse_active(address + 4, -1, &ss)) {
+ if (!inet_parse_active(address + 4, -1, &ss, true)) {
return ovsdb_error(NULL, "%s: syntax error in address", address);
}
return NULL;
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovsdb/raft-rpc.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovsdb/raft-rpc.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovsdb/raft-rpc.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovsdb/raft-rpc.c 2020-03-11 16:15:44.000000000 +0000
@@ -460,6 +460,10 @@
raft_remove_server_reply_to_jsonrpc(const struct raft_remove_server_reply *rpy,
struct json *args)
{
+ if (!uuid_is_zero(&rpy->target_sid)) {
+ json_object_put_format(args, "target_server",
+ UUID_FMT, UUID_ARGS(&rpy->target_sid));
+ }
json_object_put(args, "success", json_boolean_create(rpy->success));
}
@@ -468,6 +472,7 @@
struct raft_remove_server_reply *rpy)
{
rpy->success = raft_parse_required_boolean(p, "success");
+ raft_parse_optional_uuid(p, "target_server", &rpy->target_sid);
}
static void
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovsdb/raft-rpc.h openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovsdb/raft-rpc.h
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovsdb/raft-rpc.h 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovsdb/raft-rpc.h 2020-03-11 16:15:44.000000000 +0000
@@ -205,6 +205,13 @@
struct raft_remove_server_reply {
struct raft_rpc_common common;
bool success;
+
+ /* SID of the removed server, but all-zeros if it is the same as the
+ * destination of the RPC. (Older ovsdb-server did not have 'target_sid'
+ * and assumed that the destination was always the target, so by omitting
+ * 'target_sid' when this is the case we can preserve a small amount of
+ * inter-version compatibility.) */
+ struct uuid target_sid;
};
struct raft_install_snapshot_request {
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovsdb/replication.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovsdb/replication.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/ovsdb/replication.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/ovsdb/replication.c 2020-03-11 16:15:44.000000000 +0000
@@ -299,19 +299,7 @@
/* After receiving schemas, reset the local databases that
* will be monitored and send out monitor requests for them. */
if (hmap_is_empty(&request_ids)) {
- struct shash_node *node, *next;
-
- SHASH_FOR_EACH_SAFE (node, next, replication_dbs) {
- db = node->data;
- error = reset_database(db);
- if (error) {
- const char *db_name = db->schema->name;
- shash_find_and_delete(replication_dbs, db_name);
- ovsdb_error_assert(error);
- VLOG_WARN("Failed to reset database, "
- "%s not replicated.", db_name);
- }
- }
+ struct shash_node *node;
if (shash_is_empty(replication_dbs)) {
VLOG_WARN("Nothing to replicate.");
@@ -335,7 +323,16 @@
case RPL_S_MONITOR_REQUESTED: {
/* Reply to monitor requests. */
struct ovsdb_error *error;
- error = process_notification(msg->result, db);
+ VLOG_INFO("Monitor request received. Resetting the database");
+ /* Resetting the database here has few risks. If the
+ * process_notification() fails, the database is completely
+ * lost locally. In case that node becomes active, then
+ * there is a chance of complete data loss in the active/standy
+ * cluster. */
+ error = reset_database(db);
+ if (!error) {
+ error = process_notification(msg->result, db);
+ }
if (error) {
ovsdb_error_assert(error);
state = RPL_S_ERR;
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/python/ovs/db/idl.py openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/python/ovs/db/idl.py
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/python/ovs/db/idl.py 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/python/ovs/db/idl.py 2020-03-11 16:15:44.000000000 +0000
@@ -855,7 +855,7 @@
if removes is not None:
for key in removes:
if key not in (inserts or {}):
- del dmap[key]
+ dmap.pop(key, None)
datum = data.Datum.from_python(column.type, dmap,
_row_to_uuid)
else:
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/python/ovs/_json.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/python/ovs/_json.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/python/ovs/_json.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/python/ovs/_json.c 2020-03-11 16:15:44.000000000 +0000
@@ -170,6 +170,7 @@
json = json_parser_finish(self->_parser);
self->_parser = NULL;
obj = json_to_python(json);
+ json_destroy(json);
return obj;
}
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/python/ovs/json.py openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/python/ovs/json.py
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/python/ovs/json.py 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/python/ovs/json.py 2020-03-11 16:15:44.000000000 +0000
@@ -21,10 +21,13 @@
import six
+PARSER_C = 'C'
+PARSER_PY = 'PYTHON'
try:
import ovs._json
+ PARSER = PARSER_C
except ImportError:
- pass
+ PARSER = PARSER_PY
__pychecker__ = 'no-stringiter'
@@ -91,10 +94,9 @@
MAX_HEIGHT = 1000
def __new__(cls, *args, **kwargs):
- try:
+ if PARSER == PARSER_C:
return ovs._json.Parser(*args, **kwargs)
- except NameError:
- return super(Parser, cls).__new__(cls)
+ return super(Parser, cls).__new__(cls)
def __init__(self, check_trailer=False):
self.check_trailer = check_trailer
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/python/ovs/jsonrpc.py openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/python/ovs/jsonrpc.py
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/python/ovs/jsonrpc.py 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/python/ovs/jsonrpc.py 2020-03-11 16:15:44.000000000 +0000
@@ -272,7 +272,8 @@
# data, so we convert it here as soon as possible.
if data and not error:
try:
- data = decoder.decode(data)
+ if six.PY3 or ovs.json.PARSER == ovs.json.PARSER_PY:
+ data = decoder.decode(data)
except UnicodeError:
error = errno.EILSEQ
if error:
@@ -298,7 +299,11 @@
else:
if self.parser is None:
self.parser = ovs.json.Parser()
- self.input = self.input[self.parser.feed(self.input):]
+ if six.PY3 and ovs.json.PARSER == ovs.json.PARSER_C:
+ self.input = self.input.encode('utf-8')[
+ self.parser.feed(self.input):].decode()
+ else:
+ self.input = self.input[self.parser.feed(self.input):]
if self.parser.is_done():
msg = self.__process_msg()
if msg:
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/python/ovs/socket_util.py openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/python/ovs/socket_util.py
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/python/ovs/socket_util.py 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/python/ovs/socket_util.py 2020-03-11 16:15:44.000000000 +0000
@@ -178,7 +178,7 @@
pfds = p.poll(0)
if len(pfds) == 1:
revents = pfds[0][1]
- if revents & ovs.poller.POLLERR:
+ if revents & ovs.poller.POLLERR or revents & ovs.poller.POLLHUP:
try:
# The following should raise an exception.
sock.send("\0".encode(), socket.MSG_DONTWAIT)
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/python/ovs/stream.py openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/python/ovs/stream.py
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/python/ovs/stream.py 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/python/ovs/stream.py 2020-03-11 16:15:44.000000000 +0000
@@ -741,7 +741,11 @@
error, sock = ovs.socket_util.inet_open_active(socket.SOCK_STREAM,
suffix, 0, dscp)
if not error:
- sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
+ try:
+ sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
+ except socket.error as e:
+ sock.close()
+ return ovs.socket_util.get_exception_errno(e), None
return error, sock
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/python/ovs/vlog.py openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/python/ovs/vlog.py
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/python/ovs/vlog.py 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/python/ovs/vlog.py 2020-03-11 16:15:44.000000000 +0000
@@ -139,7 +139,7 @@
min_width = int(matches.group(2))
if len(replace) < min_width:
replace = replace.center(min_width)
- return re.sub(match, replace, tmp)
+ return re.sub(match, replace.replace('\\', r'\\'), tmp)
def _format_time(self, tmp):
date_regex = re.compile('(%(0?[1-9]?[dD])(\{(.*)\})?)')
@@ -237,7 +237,7 @@
Vlog.__file_handler = logging.FileHandler(Vlog.__log_file)
logger.addHandler(Vlog.__file_handler)
except (IOError, socket.error):
- logger.setLevel(logging.CRITICAL)
+ logger.disabled = True
ovs.unixctl.command_register("vlog/reopen", "", 0, 0,
Vlog._unixctl_vlog_reopen, None)
@@ -305,20 +305,19 @@
return
logger = logging.getLogger('syslog')
- # If there is no infrastructure to support python syslog, disable
- # the logger to avoid repeated errors.
- if not os.path.exists("/dev/log"):
- logger.disabled = True
- return
+
+ if facility is None:
+ facility = syslog_facility
+
+ new_handler = logging.handlers.SysLogHandler(address="/dev/log",
+ facility=facility)
if syslog_handler:
logger.removeHandler(syslog_handler)
- if facility:
- syslog_facility = facility
+ syslog_handler = new_handler
+ syslog_facility = facility
- syslog_handler = logging.handlers.SysLogHandler(address="/dev/log",
- facility=syslog_facility)
logger.addHandler(syslog_handler)
return
@@ -342,7 +341,11 @@
return "Please supply a valid pattern and destination"
elif words[0] == "FACILITY":
if words[1] in FACILITIES:
- Vlog.add_syslog_handler(words[1])
+ try:
+ Vlog.add_syslog_handler(words[1])
+ except (IOError, socket.error):
+ logger = logging.getLogger('syslog')
+ logger.disabled = True
return
else:
return "Facility %s is invalid" % words[1]
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/README.rst openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/README.rst
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/README.rst 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/README.rst 2020-03-11 16:15:44.000000000 +0000
@@ -1,5 +1,6 @@
-.. NOTE(stephenfin): If making changes to this file, ensure that the line
- numbers found in 'Documentation/intro/what-is-ovs' are kept up-to-date.
+.. NOTE(stephenfin): If making changes to this file, ensure that the
+ start-after/end-before lines found in 'Documentation/intro/what-is-ovs'
+ are kept up-to-date.
============
Open vSwitch
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/rhel/etc_init.d_openvswitch openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/rhel/etc_init.d_openvswitch
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/rhel/etc_init.d_openvswitch 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/rhel/etc_init.d_openvswitch 2020-03-11 16:15:44.000000000 +0000
@@ -28,6 +28,7 @@
### END INIT INFO
SYSTEMCTL_SKIP_REDIRECT=yes
+SYSTEMD_NO_WRAP=yes
. /usr/share/openvswitch/scripts/ovs-lib || exit 1
test -e /etc/sysconfig/openvswitch && . /etc/sysconfig/openvswitch
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/rhel/openvswitch-fedora.spec.in openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/rhel/openvswitch-fedora.spec.in
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/rhel/openvswitch-fedora.spec.in 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/rhel/openvswitch-fedora.spec.in 2020-03-11 16:15:44.000000000 +0000
@@ -223,6 +223,7 @@
--with-dpdk=$(dirname %{_datadir}/dpdk/*/.config) \
%endif
--enable-ssl \
+ --enable-shared \
--with-pkidir=%{_sharedstatedir}/openvswitch/pki \
%if 0%{?fedora} > 22 || %{with build_python3}
PYTHON3=%{__python3} \
@@ -396,7 +397,7 @@
-c "Open vSwitch Daemons" openvswitch
%if %{with dpdk}
- getent group hugetlbfs >/dev/null || groupadd hugetlbfs
+ getent group hugetlbfs >/dev/null || groupadd -r hugetlbfs
usermod -a -G hugetlbfs openvswitch
%endif
exit 0
@@ -422,7 +423,7 @@
%else
# Package install, not upgrade
if [ $1 -eq 1 ]; then
- /bin/systemctl daemon-reload >dev/null || :
+ /bin/systemctl daemon-reload >/dev/null || :
fi
%endif
@@ -523,6 +524,7 @@
%{python2_sitelib}/ovstest
%files devel
+%{_libdir}/lib*.so
%{_libdir}/*.a
%{_libdir}/*.la
%{_libdir}/pkgconfig/*.pc
@@ -571,6 +573,7 @@
%{_bindir}/ovs-testcontroller
%{_bindir}/ovs-pki
%{_bindir}/vtep-ctl
+%{_libdir}/lib*.so.*
%{_sbindir}/ovs-bugtool
%{_sbindir}/ovs-vswitchd
%{_sbindir}/ovsdb-server
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/rhel/openvswitch-kmod-fedora.spec.in openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/rhel/openvswitch-kmod-fedora.spec.in
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/rhel/openvswitch-kmod-fedora.spec.in 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/rhel/openvswitch-kmod-fedora.spec.in 2020-03-11 16:15:44.000000000 +0000
@@ -80,6 +80,15 @@
fi
fi
+%posttrans
+# The upgrade path from the older kmod-openvswitch SysV package to
+# the newer openvswitch-kmod systemd package will end up removing
+# the symlinks to the weak-updates/openvswitch drivers because of
+# it's %postun section. We add this section to handle that case.
+if [ -x "%{_datadir}/openvswitch/scripts/ovs-kmod-manage.sh" ]; then
+ %{_datadir}/openvswitch/scripts/ovs-kmod-manage.sh
+fi
+
%files
%defattr(0644,root,root)
/lib/modules/%{kernel}/extra/*.ko
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/rhel/usr_lib_systemd_system_ovn-controller.service openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/rhel/usr_lib_systemd_system_ovn-controller.service
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/rhel/usr_lib_systemd_system_ovn-controller.service 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/rhel/usr_lib_systemd_system_ovn-controller.service 2020-03-11 16:15:44.000000000 +0000
@@ -21,6 +21,7 @@
[Service]
Type=forking
+PIDFile=/var/run/openvswitch/ovn-controller.pid
Restart=on-failure
EnvironmentFile=-/etc/sysconfig/ovn-controller
ExecStart=/usr/share/openvswitch/scripts/ovn-ctl --no-monitor \
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/rhel/usr_lib_systemd_system_ovsdb-server.service openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/rhel/usr_lib_systemd_system_ovsdb-server.service
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/rhel/usr_lib_systemd_system_ovsdb-server.service 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/rhel/usr_lib_systemd_system_ovsdb-server.service 2020-03-11 16:15:44.000000000 +0000
@@ -7,6 +7,7 @@
[Service]
Type=forking
+PIDFile=/var/run/openvswitch/ovsdb-server.pid
Restart=on-failure
EnvironmentFile=/etc/openvswitch/default.conf
EnvironmentFile=-/etc/sysconfig/openvswitch
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/rhel/usr_lib_systemd_system_ovs-vswitchd.service.in openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/rhel/usr_lib_systemd_system_ovs-vswitchd.service.in
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/rhel/usr_lib_systemd_system_ovs-vswitchd.service.in 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/rhel/usr_lib_systemd_system_ovs-vswitchd.service.in 2020-03-11 16:15:44.000000000 +0000
@@ -9,6 +9,7 @@
[Service]
Type=forking
+PIDFile=/var/run/openvswitch/ovs-vswitchd.pid
Restart=on-failure
Environment=HOME=/var/run/openvswitch
EnvironmentFile=/etc/openvswitch/default.conf
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/selinux/openvswitch-custom.te.in openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/selinux/openvswitch-custom.te.in
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/selinux/openvswitch-custom.te.in 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/selinux/openvswitch-custom.te.in 2020-03-11 16:15:44.000000000 +0000
@@ -16,6 +16,7 @@
type init_t;
type init_var_run_t;
type insmod_exec_t;
+ type kernel_t;
type hostname_exec_t;
type modules_conf_t;
type modules_object_t;
@@ -32,7 +33,6 @@
@begin_dpdk@
type hugetlbfs_t;
- type kernel_t;
type svirt_t;
type svirt_image_t;
type svirt_tmpfs_t;
@@ -50,7 +50,7 @@
class netlink_audit_socket { create nlmsg_relay audit_write read write };
class netlink_socket { setopt getopt create connect getattr write read };
class sock_file { write };
- class system module_load;
+ class system { module_load module_request };
class process { sigchld signull transition noatsecure siginh rlimitinh };
class unix_stream_socket { write getattr read connectto connect setopt getopt sendto accept bind recvfrom acceptfrom ioctl };
@@ -107,6 +107,7 @@
allow openvswitch_load_module_t init_t:unix_stream_socket { getattr ioctl read write };
allow openvswitch_load_module_t init_var_run_t:dir { getattr read open search };
allow openvswitch_load_module_t insmod_exec_t:file { execute execute_no_trans getattr map open read };
+allow openvswitch_load_module_t kernel_t:system module_request;
allow openvswitch_load_module_t modules_conf_t:dir { getattr open read search };
allow openvswitch_load_module_t modules_conf_t:file { getattr open read };
allow openvswitch_load_module_t modules_object_t:file { map getattr open read };
@@ -117,7 +118,7 @@
allow openvswitch_load_module_t proc_t:file { getattr open read };
allow openvswitch_load_module_t self:system module_load;
allow openvswitch_load_module_t self:process { siginh noatsecure rlimitinh siginh };
-allow openvswitch_load_module_t shell_exec_t:file { map execute read open getattr };
+allow openvswitch_load_module_t shell_exec_t:file { map execute execute_no_trans read open getattr };
allow openvswitch_load_module_t sssd_public_t:dir { getattr open read search };
allow openvswitch_load_module_t sssd_public_t:file { getattr map open read };
allow openvswitch_load_module_t sssd_t:unix_stream_socket connectto;
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/atlocal.in openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/atlocal.in
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/atlocal.in 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/atlocal.in 2020-03-11 16:15:44.000000000 +0000
@@ -190,6 +190,9 @@
# Set HAVE_TCPDUMP
find_command tcpdump
+# Set HAVE_LFTP
+find_command lftp
+
CURL_OPT="-g -v --max-time 1 --retry 2 --retry-delay 1 --connect-timeout 1"
# Determine whether "diff" supports "normal" diffs. (busybox diff does not.)
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/automake.mk openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/automake.mk
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/automake.mk 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/automake.mk 2020-03-11 16:15:44.000000000 +0000
@@ -404,6 +404,10 @@
tests_ovstest_LDADD = lib/libopenvswitch.la ovn/lib/libovn.la
+noinst_PROGRAMS += tests/test-stream
+tests_test_stream_SOURCES = tests/test-stream.c
+tests_test_stream_LDADD = lib/libopenvswitch.la
+
noinst_PROGRAMS += tests/test-strtok_r
tests_test_strtok_r_SOURCES = tests/test-strtok_r.c
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/bridge.at openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/bridge.at
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/bridge.at 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/bridge.at 2020-03-11 16:15:44.000000000 +0000
@@ -79,3 +79,27 @@
OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])
OVS_APP_EXIT_AND_WAIT([ovsdb-server])
AT_CLEANUP
+
+AT_SETUP([bridge - add port after stopping controller])
+OVS_VSWITCHD_START
+
+dnl Start ovs-testcontroller
+AT_CHECK([ovs-testcontroller --detach punix:controller --pidfile], [0], [ignore])
+OVS_WAIT_UNTIL([test -e controller])
+
+AT_CHECK([ovs-vsctl set-controller br0 unix:controller])
+AT_CHECK([ovs-vsctl add-port br0 p1 -- set Interface p1 type=internal], [0], [ignore])
+AT_CHECK([ovs-appctl -t ovs-vswitchd version], [0], [ignore])
+
+# Now kill the ovs-testcontroller
+kill `cat ovs-testcontroller.pid`
+if test "$IS_WIN32" = "yes"; then
+ AT_CHECK([rm controller], [0], [ignore])
+fi
+OVS_WAIT_UNTIL([! test -e controller])
+AT_CHECK([ovs-vsctl --no-wait add-port br0 p2 -- set Interface p2 type=internal], [0], [ignore])
+AT_CHECK([ovs-appctl -t ovs-vswitchd version], [0], [ignore])
+
+OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])
+OVS_APP_EXIT_AND_WAIT([ovsdb-server])
+AT_CLEANUP
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/dpif-netdev.at openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/dpif-netdev.at
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/dpif-netdev.at 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/dpif-netdev.at 2020-03-11 16:15:44.000000000 +0000
@@ -110,8 +110,10 @@
m4_define([DPIF_NETDEV_MISS_FLOW_INSTALL],
[AT_SETUP([dpif-netdev - miss upcall key matches flow_install - $1])
OVS_VSWITCHD_START(
- [add-port br0 p1 -- set interface p1 type=$1 options:pstream=punix:$OVS_RUNDIR/p0.sock
- set bridge br0 datapath-type=dummy other-config:datapath-id=1234 fail-mode=secure], [], [],
+ [add-port br0 p1 \
+ -- set interface p1 type=$1 options:pstream=punix:$OVS_RUNDIR/p0.sock \
+ -- set bridge br0 datapath-type=dummy \
+ other-config:datapath-id=1234 fail-mode=secure], [], [],
[m4_if([$1], [dummy-pmd], [--dummy-numa="0,0,0,0,1,1,1,1"], [])])
AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])
@@ -150,8 +152,10 @@
m4_define([DPIF_NETDEV_MISS_FLOW_DUMP],
[AT_SETUP([dpif-netdev - miss upcall key matches flow_dump - $1])
OVS_VSWITCHD_START(
- [add-port br0 p1 -- set interface p1 type=$1 options:pstream=punix:$OVS_RUNDIR/p0.sock
- set bridge br0 datapath-type=dummy other-config:datapath-id=1234 fail-mode=secure], [], [],
+ [add-port br0 p1 \
+ -- set interface p1 type=$1 options:pstream=punix:$OVS_RUNDIR/p0.sock \
+ -- set bridge br0 datapath-type=dummy \
+ other-config:datapath-id=1234 fail-mode=secure], [], [],
[m4_if([$1], [dummy-pmd], [--dummy-numa="0,0,0,0,1,1,1,1"], [])])
AT_CHECK([ovs-appctl upcall/disable-ufid], [0], [Datapath dumping tersely using UFID disabled
], [])
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/.gitignore openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/.gitignore
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/.gitignore 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/.gitignore 2020-03-11 16:15:44.000000000 +0000
@@ -51,6 +51,7 @@
/test-sha1
/test-skiplist
/test-stp
+/test-stream
/test-strtok_r
/test-timeval
/test-type-props
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/nsh.at openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/nsh.at
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/nsh.at 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/nsh.at 2020-03-11 16:15:44.000000000 +0000
@@ -374,7 +374,7 @@
decap()
Final flow: recirc_id=0x1,eth,in_port=4,vlan_tci=0x0000,dl_src=00:00:00:00:00:00,dl_dst=00:00:00:00:00:00,dl_type=0x0000
-Megaflow: recirc_id=0x1,packet_type=(1,0x894f),in_port=4,nsh_mdtype=1,nsh_np=3,nsh_spi=0x1234,nsh_c1=0x11223344
+Megaflow: recirc_id=0x1,packet_type=(1,0x894f),in_port=4,dl_type=0x894f,nsh_mdtype=1,nsh_np=3,nsh_spi=0x1234,nsh_c1=0x11223344
Datapath actions: pop_nsh(),recirc(0x2)
])
@@ -413,7 +413,7 @@
ovs-appctl dpctl/dump-flows dummy@ovs-dummy | strip_used | grep -v ipv6 | sort
], [0], [flow-dump from non-dpdk interfaces:
recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(dst=1e:2c:e9:2a:66:9e),eth_type(0x0800),ipv4(frag=no), packets:1, bytes:98, used:0.0s, actions:push_nsh(flags=0,ttl=63,mdtype=1,np=3,spi=0x1234,si=255,c1=0x11223344,c2=0x0,c3=0x0,c4=0x0),push_nsh(flags=0,ttl=63,mdtype=1,np=4,spi=0x5678,si=255,c1=0x55667788,c2=0x0,c3=0x0,c4=0x0),push_eth(src=00:00:00:00:00:00,dst=11:22:33:44:55:66),pop_eth,pop_nsh(),recirc(0x3)
-recirc_id(0x3),in_port(1),packet_type(ns=1,id=0x894f),nsh(mdtype=1,np=3,spi=0x1234,c1=0x11223344), packets:1, bytes:122, used:0.0s, actions:pop_nsh(),recirc(0x4)
+recirc_id(0x3),in_port(1),packet_type(ns=1,id=0x894f),eth_type(0x894f),nsh(mdtype=1,np=3,spi=0x1234,c1=0x11223344), packets:1, bytes:122, used:0.0s, actions:pop_nsh(),recirc(0x4)
recirc_id(0x4),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:1, bytes:98, used:0.0s, actions:2
])
@@ -725,8 +725,8 @@
ovs-appctl dpctl/dump-flows dummy@ovs-dummy | strip_used | grep -v ipv6 | sort
], [0], [flow-dump from non-dpdk interfaces:
recirc_id(0),in_port(4),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(dst=192.168.10.30,frag=no), packets:1, bytes:98, used:0.0s, actions:pop_eth,push_nsh(flags=0,ttl=63,mdtype=1,np=1,spi=0x3000,si=255,c1=0x0,c2=0x0,c3=0x0,c4=0x0),clone(tnl_push(tnl_port(4789),header(size=50,type=4,eth(dst=aa:55:00:00:00:03,src=aa:55:00:00:00:01,dl_type=0x0800),ipv4(src=10.0.0.1,dst=10.0.0.3,proto=17,tos=0,ttl=64,frag=0x4000),udp(src=0,dst=4789,csum=0x0),vxlan(flags=0xc000004,vni=0x0)),out_port(1)),set(ipv4(src=30.0.0.1,dst=30.0.0.3)),tnl_pop(4789))
-tunnel(tun_id=0x0,src=30.0.0.1,dst=30.0.0.3,flags(-df-csum+key)),recirc_id(0),in_port(4789),packet_type(ns=1,id=0x894f),nsh(np=1,spi=0x3000,si=255), packets:1, bytes:108, used:0.0s, actions:pop_nsh(),recirc(0x1)
-tunnel(tun_id=0x0,src=30.0.0.1,dst=30.0.0.3,flags(-df-csum+key)),recirc_id(0x1),in_port(4789),packet_type(ns=1,id=0x800),ipv4(frag=no), packets:1, bytes:84, used:0.0s, actions:push_eth(src=00:00:00:00:00:00,dst=aa:55:aa:55:00:03),6
+tunnel(tun_id=0x0,src=30.0.0.1,dst=30.0.0.3,flags(-df-csum+key)),recirc_id(0),in_port(4789),packet_type(ns=1,id=0x894f),eth_type(0x894f),nsh(np=1,spi=0x3000,si=255), packets:1, bytes:108, used:0.0s, actions:pop_nsh(),recirc(0x1)
+tunnel(tun_id=0x0,src=30.0.0.1,dst=30.0.0.3,flags(-df-csum+key)),recirc_id(0x1),in_port(4789),packet_type(ns=1,id=0x800),eth_type(0x0800),ipv4(frag=no), packets:1, bytes:84, used:0.0s, actions:push_eth(src=00:00:00:00:00:00,dst=aa:55:aa:55:00:03),6
])
AT_CHECK([
@@ -779,9 +779,9 @@
ovs-appctl dpctl/dump-flows dummy@ovs-dummy | strip_used | grep -v ipv6 | sort
], [0], [flow-dump from non-dpdk interfaces:
recirc_id(0),in_port(4),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(dst=192.168.10.20/255.255.255.248,frag=no), packets:1, bytes:98, used:0.0s, actions:pop_eth,push_nsh(flags=0,ttl=63,mdtype=1,np=1,spi=0x3020,si=255,c1=0x0,c2=0x0,c3=0x0,c4=0x0),clone(tnl_push(tnl_port(4789),header(size=50,type=4,eth(dst=aa:55:00:00:00:02,src=aa:55:00:00:00:01,dl_type=0x0800),ipv4(src=10.0.0.1,dst=10.0.0.2,proto=17,tos=0,ttl=64,frag=0x4000),udp(src=0,dst=4789,csum=0x0),vxlan(flags=0xc000004,vni=0x0)),out_port(1)),set(ipv4(src=20.0.0.1,dst=20.0.0.2)),tnl_pop(4789))
-tunnel(tun_id=0x0,src=20.0.0.1,dst=20.0.0.2,flags(-df-csum+key)),recirc_id(0),in_port(4789),packet_type(ns=1,id=0x894f),nsh(spi=0x3020,si=255), packets:1, bytes:108, used:0.0s, actions:push_eth(src=00:00:00:00:00:00,dst=11:22:33:44:55:66),set(nsh(spi=0x3020,si=254)),pop_eth,clone(tnl_push(tnl_port(4789),header(size=50,type=4,eth(dst=aa:55:00:00:00:03,src=aa:55:00:00:00:02,dl_type=0x0800),ipv4(src=20.0.0.2,dst=20.0.0.3,proto=17,tos=0,ttl=64,frag=0x4000),udp(src=0,dst=4789,csum=0x0),vxlan(flags=0xc000004,vni=0x0)),out_port(2)),set(ipv4(src=30.0.0.2,dst=30.0.0.3)),tnl_pop(4789))
-tunnel(tun_id=0x0,src=30.0.0.2,dst=30.0.0.3,flags(-df-csum+key)),recirc_id(0),in_port(4789),packet_type(ns=1,id=0x894f),nsh(np=1,spi=0x3020,si=254), packets:1, bytes:108, used:0.0s, actions:pop_nsh(),recirc(0x2)
-tunnel(tun_id=0x0,src=30.0.0.2,dst=30.0.0.3,flags(-df-csum+key)),recirc_id(0x2),in_port(4789),packet_type(ns=1,id=0x800),ipv4(frag=no), packets:1, bytes:84, used:0.0s, actions:push_eth(src=00:00:00:00:00:00,dst=aa:55:aa:55:00:03),6
+tunnel(tun_id=0x0,src=20.0.0.1,dst=20.0.0.2,flags(-df-csum+key)),recirc_id(0),in_port(4789),packet_type(ns=1,id=0x894f),eth_type(0x894f),nsh(spi=0x3020,si=255), packets:1, bytes:108, used:0.0s, actions:push_eth(src=00:00:00:00:00:00,dst=11:22:33:44:55:66),set(nsh(spi=0x3020,si=254)),pop_eth,clone(tnl_push(tnl_port(4789),header(size=50,type=4,eth(dst=aa:55:00:00:00:03,src=aa:55:00:00:00:02,dl_type=0x0800),ipv4(src=20.0.0.2,dst=20.0.0.3,proto=17,tos=0,ttl=64,frag=0x4000),udp(src=0,dst=4789,csum=0x0),vxlan(flags=0xc000004,vni=0x0)),out_port(2)),set(ipv4(src=30.0.0.2,dst=30.0.0.3)),tnl_pop(4789))
+tunnel(tun_id=0x0,src=30.0.0.2,dst=30.0.0.3,flags(-df-csum+key)),recirc_id(0),in_port(4789),packet_type(ns=1,id=0x894f),eth_type(0x894f),nsh(np=1,spi=0x3020,si=254), packets:1, bytes:108, used:0.0s, actions:pop_nsh(),recirc(0x2)
+tunnel(tun_id=0x0,src=30.0.0.2,dst=30.0.0.3,flags(-df-csum+key)),recirc_id(0x2),in_port(4789),packet_type(ns=1,id=0x800),eth_type(0x0800),ipv4(frag=no), packets:1, bytes:84, used:0.0s, actions:push_eth(src=00:00:00:00:00:00,dst=aa:55:aa:55:00:03),6
])
AT_CHECK([
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/ofproto.at openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/ofproto.at
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/ofproto.at 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/ofproto.at 2020-03-11 16:15:44.000000000 +0000
@@ -678,6 +678,20 @@
AT_CHECK([ovs-ofctl -O OpenFlow11 -vwarn insert-buckets br0 group_id=1234,command_bucket_id=first,bucket=bucket_id:0,actions=output:0,bucket=bucket_id:1,actions=output:1], [1], [],
[ovs-ofctl: insert-bucket needs OpenFlow 1.5 or later ('-O OpenFlow15')
])
+
+# Verify insert-buckets command to insert bucket with weight value for select group.
+AT_CHECK([ovs-ofctl -O OpenFlow15 --strict del-groups br0 group_id=1234])
+AT_DATA([groups.txt], [dnl
+group_id=1234,type=select,selection_method=hash,bucket=bucket_id=1,weight:100,output:11
+])
+AT_CHECK([ovs-ofctl -O OpenFlow15 -vwarn add-groups br0 groups.txt])
+AT_CHECK([ovs-ofctl -O OpenFlow15 insert-buckets br0 group_id=1234,command_bucket_id=last,bucket=bucket_id=2,weight=100,actions=output:11])
+AT_CHECK([ovs-ofctl -O OpenFlow15 -vwarn dump-groups br0], [0], [stdout])
+AT_CHECK([strip_xids < stdout], [0], [dnl
+OFPST_GROUP_DESC reply (OF1.5):
+ group_id=1234,type=select,selection_method=hash,bucket=bucket_id:1,weight:100,actions=output:11,bucket=bucket_id:2,weight:100,actions=output:11
+])
+
OVS_VSWITCHD_STOP
AT_CLEANUP
@@ -1241,6 +1255,22 @@
OFPST_GROUP reply (OF1.5):
])
OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+dnl This is used to find that the bucket counter is not updated.
+AT_SETUP([ofproto - group stats after insert a new bucket (OpenFlow 1.5)])
+OVS_VSWITCHD_START
+AT_DATA([groups.txt], [dnl
+group_id=1234,type=select,selection_method=hash bucket=bucket_id=1,weight:100,actions=output:10
+])
+AT_CHECK([ovs-ofctl -O OpenFlow15 -vwarn add-groups br0 groups.txt])
+AT_CHECK([ovs-ofctl -O OpenFlow15 -vwarn insert-buckets br0 'group_id=1234, command_bucket_id=last, bucket=bucket_id=2,weight:100,actions=output:10'])
+AT_CHECK([ovs-ofctl -O OpenFlow15 -vwarn dump-group-stats br0 group_id=1234], [0], [stdout])
+AT_CHECK([strip_xids < stdout | sed 's/duration=[[0-9.]]*s/duration=?s/' | sort], [0], [dnl
+ group_id=1234,duration=?s,ref_count=0,packet_count=0,byte_count=0,bucket0:packet_count=0,byte_count=0,bucket1:packet_count=0,byte_count=0
+OFPST_GROUP reply (OF1.5):
+])
+OVS_VSWITCHD_STOP
AT_CLEANUP
dnl This found a use-after-free error in bridge destruction in the
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/ofproto-dpif.at openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/ofproto-dpif.at
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/ofproto-dpif.at 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/ofproto-dpif.at 2020-03-11 16:15:44.000000000 +0000
@@ -4337,11 +4337,11 @@
OVS_VSWITCHD_START
add_of_ports br0 1 2 3 4 5 6 90
AT_DATA([flows.txt], [dnl
-priority=75 tcp ip_frag=no tp_dst=80 actions=move:OXM_OF_TCP_DST[[]]->OXM_OF_TCP_SRC[[]],output:1
-priority=75 tcp ip_frag=first tp_dst=80 actions=move:OXM_OF_TCP_DST[[]]->OXM_OF_TCP_SRC[[]],output:2
-priority=50 tcp ip_frag=no actions=move:OXM_OF_TCP_DST[[]]->OXM_OF_TCP_SRC[[]],output:4
-priority=50 tcp ip_frag=first actions=move:OXM_OF_TCP_DST[[]]->OXM_OF_TCP_SRC[[]],output:5
-priority=50 tcp ip_frag=later actions=output:6
+priority=75 tcp nw_frag=no tp_dst=80 actions=move:OXM_OF_TCP_DST[[]]->OXM_OF_TCP_SRC[[]],output:1
+priority=75 tcp nw_frag=first tp_dst=80 actions=move:OXM_OF_TCP_DST[[]]->OXM_OF_TCP_SRC[[]],output:2
+priority=50 tcp nw_frag=no actions=move:OXM_OF_TCP_DST[[]]->OXM_OF_TCP_SRC[[]],output:4
+priority=50 tcp nw_frag=first actions=move:OXM_OF_TCP_DST[[]]->OXM_OF_TCP_SRC[[]],output:5
+priority=50 tcp nw_frag=later actions=output:6
])
AT_CHECK([ovs-ofctl replace-flows br0 flows.txt])
@@ -5393,6 +5393,74 @@
-- set interface patch11 type=patch options:peer=patch10 \
ofport_request=11])
+AT_SETUP([ofproto-dpif - continuation flow stats])
+AT_KEYWORDS([continuations pause resume])
+OVS_VSWITCHD_START
+
+add_of_ports --pcap br0 `seq 1 2`
+
+flow="in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
+
+AT_DATA([flows.txt], [dnl
+table=0 in_port=1 actions=set_field:1->reg1 controller(pause) resubmit(,2)
+table=2 reg1=0x1 actions=2
+])
+
+AT_CHECK([ovs-ofctl -O OpenFlow13 add-flows br0 flows.txt])
+
+AT_CAPTURE_FILE([ofctl_monitor0.log])
+ovs-ofctl monitor br0 resume --detach --no-chdir \
+--pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log
+
+# Run a packet through the switch.
+AT_CHECK([ovs-appctl netdev-dummy/receive p1 "$flow"], [0], [stdout])
+
+# Check flow stats
+AT_CHECK([ovs-ofctl dump-flows br0], [0], [stdout])
+AT_CHECK([strip_xids < stdout | sed -n 's/duration=[[0-9]]*\.[[0-9]]*s/duration=0.0s/p' | sed -n 's/idle_age=[[0-9]]*/idle_age=0/p' | grep 'table=2'], [0], [dnl
+ cookie=0x0, duration=0.0s, table=2, n_packets=1, n_bytes=106, idle_age=0, reg1=0x1 actions=output:2
+])
+
+# The packet should be received by port 2
+AT_CHECK([test 1 = `$PYTHON "$top_srcdir/utilities/ovs-pcap.in" p2-tx.pcap | wc -l`])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto-dpif - continuation with conntrack])
+AT_KEYWORDS([continuations pause resume])
+OVS_VSWITCHD_START
+
+add_of_ports --pcap br0 `seq 1 2`
+
+flow="in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
+
+AT_DATA([flows.txt], [dnl
+table=0, in_port=1 icmp action=ct(table=1)
+table=1, icmp action=controller(pause) resubmit(,2)
+table=2, in_port=1 icmp ct_state=+trk+new action=output:2
+])
+
+AT_CHECK([ovs-ofctl -O OpenFlow13 add-flows br0 flows.txt])
+
+AT_CAPTURE_FILE([ofctl_monitor0.log])
+ovs-ofctl monitor br0 resume --detach --no-chdir \
+--pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log
+
+# Run a packet through the switch.
+AT_CHECK([ovs-appctl netdev-dummy/receive p1 "$flow"], [0], [stdout])
+
+# Check flow stats
+AT_CHECK([ovs-ofctl dump-flows br0], [0], [stdout])
+AT_CHECK([strip_xids < stdout | sed -n 's/duration=[[0-9]]*\.[[0-9]]*s/duration=0.0s/p' | sed -n 's/idle_age=[[0-9]]*/idle_age=0/p' | grep 'table=2'], [0], [dnl
+ cookie=0x0, duration=0.0s, table=2, n_packets=1, n_bytes=106, idle_age=0, ct_state=+new+trk,icmp,in_port=1 actions=output:2
+])
+
+# The packet should be received by port 2
+AT_CHECK([test 1 = `$PYTHON "$top_srcdir/utilities/ovs-pcap.in" p2-tx.pcap | wc -l`])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
# Check that pause works after the packet is cloned.
AT_SETUP([ofproto-dpif - continuation after clone])
@@ -5424,7 +5492,7 @@
ovs-vsctl show
ovs-ofctl dump-flows br0
-# The packet should be recieved by port 2 and not port 3
+# The packet should be received by port 2 and not port 3
AT_CHECK([test 1 = `$PYTHON "$top_srcdir/utilities/ovs-pcap.in" p2-tx.pcap | wc -l`])
AT_CHECK([test 0 = `$PYTHON "$top_srcdir/utilities/ovs-pcap.in" p3-tx.pcap | wc -l`])
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/ovn.at openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/ovn.at
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/ovn.at 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/ovn.at 2020-03-11 16:15:44.000000000 +0000
@@ -287,6 +287,8 @@
inport == "eth0"
!(inport != "eth0") => inport == "eth0"
+(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((0))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) => 0
+
ip4.src == "eth0" => Integer field ip4.src is not compatible with string constant.
inport == 1 => String field inport is not compatible with integer constant.
ip4.src = 1.2.3.4 => Syntax error at `=' expecting relational operator.
@@ -353,6 +355,10 @@
ip4.src == {1.2.3.4, $set1, $unknownset} => Syntax error at `$unknownset' expecting address set name.
eth.src == {$set3, badmac, 00:00:00:00:00:01} => Syntax error at `badmac' expecting constant.
+
+((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((())))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) => Parentheses nested too deeply.
+
+ct_label > $set4 => Only == and != operators may be used to compare a field against an empty value set.
]])
sed 's/ =>.*//' test-cases.txt > input.txt
sed 's/.* => //' test-cases.txt > expout
@@ -1100,9 +1106,9 @@
# put_dhcp_opts
reg1[0] = put_dhcp_opts(offerip = 1.2.3.4, router = 10.0.0.1);
encodes as controller(userdata=00.00.00.02.00.00.00.00.00.01.de.10.00.00.00.40.01.02.03.04.03.04.0a.00.00.01,pause)
-reg2[5] = put_dhcp_opts(offerip=10.0.0.4,router=10.0.0.1,netmask=255.255.254.0,mtu=1400,domain="ovn.org");
- formats as reg2[5] = put_dhcp_opts(offerip = 10.0.0.4, router = 10.0.0.1, netmask = 255.255.254.0, mtu = 1400, domain = "ovn.org");
- encodes as controller(userdata=00.00.00.02.00.00.00.00.00.01.de.10.00.00.00.25.0a.00.00.04.03.04.0a.00.00.01.01.04.ff.ff.fe.00.1a.02.05.78.0f.07.6f.76.6e.2e.6f.72.67,pause)
+reg2[5] = put_dhcp_opts(offerip=10.0.0.4,router=10.0.0.1,netmask=255.255.254.0,mtu=1400,domain="ovn.org",wpad="https://example.org");
+ formats as reg2[5] = put_dhcp_opts(offerip = 10.0.0.4, router = 10.0.0.1, netmask = 255.255.254.0, mtu = 1400, domain = "ovn.org", wpad = "https://example.org");
+ encodes as controller(userdata=00.00.00.02.00.00.00.00.00.01.de.10.00.00.00.25.0a.00.00.04.03.04.0a.00.00.01.01.04.ff.ff.fe.00.1a.02.05.78.0f.07.6f.76.6e.2e.6f.72.67.fc.13.68.74.74.70.73.3a.2f.2f.65.78.61.6d.70.6c.65.2e.6f.72.67,pause)
reg0[15] = put_dhcp_opts(offerip=10.0.0.4,router=10.0.0.1,netmask=255.255.255.0,mtu=1400,ip_forward_enable=1,default_ttl=121,dns_server={8.8.8.8,7.7.7.7},classless_static_route={30.0.0.0/24,10.0.0.4,40.0.0.0/16,10.0.0.6,0.0.0.0/0,10.0.0.1},ethernet_encap=1,router_discovery=0);
formats as reg0[15] = put_dhcp_opts(offerip = 10.0.0.4, router = 10.0.0.1, netmask = 255.255.255.0, mtu = 1400, ip_forward_enable = 1, default_ttl = 121, dns_server = {8.8.8.8, 7.7.7.7}, classless_static_route = {30.0.0.0/24, 10.0.0.4, 40.0.0.0/16, 10.0.0.6, 0.0.0.0/0, 10.0.0.1}, ethernet_encap = 1, router_discovery = 0);
encodes as controller(userdata=00.00.00.02.00.00.00.00.00.01.de.10.00.00.00.6f.0a.00.00.04.03.04.0a.00.00.01.01.04.ff.ff.ff.00.1a.02.05.78.13.01.01.17.01.79.06.08.08.08.08.08.07.07.07.07.79.14.18.1e.00.00.0a.00.00.04.10.28.00.0a.00.00.06.00.0a.00.00.01.24.01.01.1f.01.00,pause)
@@ -1256,9 +1262,11 @@
reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = 1500, prefix = aef0::/64);
slla option not present
reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateful", mtu = 1450, prefix = aef0::/64, prefix = bef0::/64, slla = ae:01:02:03:04:10);
- prefix option can't be set when address mode is dhcpv6_stateful.
+ encodes as controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.80.ff.ff.00.00.00.00.00.00.00.00.05.01.00.00.00.00.05.aa.03.04.40.80.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.ae.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00.03.04.40.80.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.be.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.10,pause)
+ has prereqs ip6
reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateful", mtu = 1450, prefix = aef0::/64, prefix = bef0::/64, slla = ae:01:02:03:04:10);
- prefix option can't be set when address mode is dhcpv6_stateful.
+ encodes as controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.80.ff.ff.00.00.00.00.00.00.00.00.05.01.00.00.00.00.05.aa.03.04.40.80.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.ae.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00.03.04.40.80.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.be.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.10,pause)
+ has prereqs ip6
reg1[0] = put_nd_ra_opts(addr_mode = "slaac", slla = ae:01:02:03:04:10);
prefix option needs to be set when address mode is slaac/dhcpv6_stateless.
reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateless", slla = ae:01:02:03:04:10);
@@ -4613,15 +4621,23 @@
# from the "ovs-ofctl monitor br-int resume"
test_dhcpv6() {
local inport=$1 src_mac=$2 src_lla=$3 msg_code=$4 offer_ip=$5
- local request=ffffffffffff${src_mac}86dd00000000002a1101${src_lla}
+ if test $msg_code != 0b; then
+ req_len=2a
+ else
+ req_len=1a
+ fi
+ local request=ffffffffffff${src_mac}86dd0000000000${req_len}1101${src_lla}
# dst ip ff02::1:2
request=${request}ff020000000000000000000000010002
# udp header and dhcpv6 header
- request=${request}02220223002affff${msg_code}010203
+ request=${request}0222022300${req_len}ffff${msg_code}010203
# Client identifier
request=${request}0001000a00030001${src_mac}
- # IA-NA (Identity Association for Non Temporary Address)
- request=${request}0003000c0102030400000e1000001518
+ # Add IA-NA (Identity Association for Non Temporary Address) if msg_code
+ # is not 11 (information request packet)
+ if test $msg_code != 0b; then
+ request=${request}0003000c0102030400000e1000001518
+ fi
shift; shift; shift; shift; shift;
if test $offer_ip != 0; then
local server_mac=000000100001
@@ -4752,7 +4768,7 @@
AT_CHECK([cat 4.packets], [0], [expout])
# Send DHCPv6 packet on ls1-lp3. native DHCPv6 works as stateless mode for this port.
-# The DHCPv6 reply should doesn't contian offer_ip.
+# The DHCPv6 reply shouldn't contain offer_ip.
src_mac=f00000000022
src_lla=fe80000000000000f20000fffe000022
reset_pcap_file hv1-vif5 hv1/vif5
@@ -4766,6 +4782,23 @@
cat 5.expected | cut -c 1-120,125- > expout
AT_CHECK([cat 5.packets | cut -c 1-120,125- ], [0], [expout])
+# Send DHCPv6 information request (code 11) on ls1-lp3. The DHCPv6 reply
+# shouldn't contain offer_ip
+src_mac=f00000000022
+src_lla=fe80000000000000f20000fffe000022
+reset_pcap_file hv1-vif5 hv1/vif5
+rm -f 5.expected
+test_dhcpv6 5 $src_mac $src_lla 0b 1 5
+
+# NXT_RESUMEs should be 4.
+OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
+
+$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif5-tx.pcap |
+trim_zeros > 5.packets
+# Skipping the UDP checksum
+cat 5.expected | cut -c 1-120,125- > expout
+AT_CHECK([cat 5.packets | cut -c 1-120,125- ], [0], [expout])
+
as hv1
OVS_APP_EXIT_AND_WAIT([ovn-controller])
OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])
@@ -6500,15 +6533,25 @@
ovs-appctl netdev-dummy/receive lp1 'in_port(1),eth(src=f0:00:00:00:00:01,dst=f0:00:00:00:00:02),eth_type(0x0800),ipv4(src=192.168.1.2,dst=192.168.1.3,proto=6,tos=0,ttl=64,frag=no),tcp(src=7777,dst=82)'
done
+# The rate at which packets are sent is highly system-dependent, so we
+# can't count on precise drop counts. To work around that, we just
+# check that exactly 100 "http-acl3" actions were logged and that there
+# were more "http-acl1" actions than "http-acl2" ones.
+OVS_WAIT_UNTIL([ test 100 = $(grep -c 'http-acl3' hv/ovn-controller.log) ])
+
+# On particularly slow or overloaded systems, the transmission rate may
+# be lower than the configured meter rate. To prevent false test
+# failures, we check the duration count of the meter, and if it's
+# greater than nine seconds, just skip the test.
+d_secs=$(as hv ovs-ofctl -O OpenFlow13 meter-stats br-int | grep "meter:1" | sed 's/.* duration:\([[0-9]]\{1,\}\)\.[[0-9]]\+s .*/\1/')
+
+echo "Meter duration: $d_secs"
+AT_SKIP_IF([test $d_secs -gt 9])
+
# Print some information that may help debugging.
as hv ovs-appctl -t ovn-controller meter-table-list
as hv ovs-ofctl -O OpenFlow13 meter-stats br-int
-# The userspace meter implementation doesn't precisely enforce counts,
-# so we just check that exactly 100 "http-acl3" actions were logged and
-# that there were more "http-acl1" actions than "http-acl2" ones.
-OVS_WAIT_UNTIL([ test 100 = $(grep -c 'http-acl3' hv/ovn-controller.log) ])
-
n_acl1=$(grep -c 'http-acl1' hv/ovn-controller.log)
n_acl2=$(grep -c 'http-acl2' hv/ovn-controller.log)
n_acl3=$(grep -c 'http-acl3' hv/ovn-controller.log)
@@ -6516,7 +6559,6 @@
AT_CHECK([ test $n_acl3 -gt $n_acl1 ], [0], [])
AT_CHECK([ test $n_acl1 -gt $n_acl2 ], [0], [])
-
OVN_CLEANUP([hv])
AT_CLEANUP
@@ -7035,6 +7077,17 @@
echo $packet >> expected1
OVN_CHECK_PACKETS([hv1/vm1-tx.pcap], [expected1])
+# Send broadcast packet from foo1. foo1 should not receive the same packet.
+src_mac="f00000010205"
+dst_mac="ffffffffffff"
+src_ip=`ip_to_hex 192 168 1 2`
+dst_ip=`ip_to_hex 255 255 255 255`
+packet=${dst_mac}${src_mac}8100000108004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
+as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
+
+# expected packet at VM1
+OVN_CHECK_PACKETS([hv1/vm1-tx.pcap], [expected1])
+
OVN_CLEANUP([hv1],[hv2])
AT_CLEANUP
@@ -8707,7 +8760,7 @@
OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-ofctl dump-flows br-int | grep -c "ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0"`])
addr_mode=80
-default_prefix_option_config=""
+default_prefix_option_config=03044080ffffffffffffffff00000000
src_mac=fa163e000004
src_lla=fe80000000000000f8163efffe000004
mtu=000005dc
@@ -9544,6 +9597,10 @@
2001:db8:1:0:200:02ff:fe01:0204/64 \
-- set Logical_Router_port ip6_public options:redirect-chassis="hv1"
+#install static route
+ovn-nbctl -- --id=@lrt create Logical_Router_Static_Route \
+ip_prefix="\:\:/0" nexthop="2001\:db8\:1\:0\:200\:02ff\:fe01\:1305" \
+-- add Logical_Router lr0_ip6 static_routes @lrt
ovn-nbctl lsp-add public rp-ip6_public -- set Logical_Switch_Port \
rp-ip6_public type=router options:router-port=ip6_public \
@@ -9586,36 +9643,82 @@
sed 's/\(00\)\{1,\}$//'
}
+reset_pcap_file() {
+ local iface=$1
+ local pcap_file=$2
+ ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
+options:rxq_pcap=dummy-rx.pcap
+ rm -f ${pcap_file}*.pcap
+ ovs-vsctl -- set Interface $iface options:tx_pcap=${pcap_file}-tx.pcap \
+options:rxq_pcap=${pcap_file}-rx.pcap
+}
+
# Test the IPv6 Neighbor Solicitation (NS) - nd_ns action for unknown MAC
# addresses. ovn-controller should generate an IPv6 NS request for IPv6
# packets whose MAC is unknown (in the ARP_REQUEST router pipeline stage.
# test_ipv6 INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
# This function sends ipv6 packet
test_ipv6() {
- local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4
- dst_ip=20010db800010000020002fffe010205
+ local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
+ local dst_mcast_mac=$6 mcast_node_ip=$7 nd_target=$8
local packet=${dst_mac}${src_mac}86dd6000000000083aff${src_ip}${dst_ip}
packet=${packet}8000000000000000
- shift; shift; shift; shift
- dst_mac=3333ff010205
src_mac=000002010204
- mcast_node_ip=ff0200000000000000000001ff010205
- expected_packet=${dst_mac}${src_mac}86dd6000000000203aff${src_ip}
- expected_packet=${expected_packet}${mcast_node_ip}8700XXXX00000000${dst_ip}
- expected_packet=${expected_packet}0101${src_mac}
+ expected_packet=${dst_mcast_mac}${src_mac}86dd6000000000203aff${src_ip}
+ expected_packet=${expected_packet}${mcast_node_ip}8700XXXX00000000
+ expected_packet=${expected_packet}${nd_target}0101${src_mac}
as hv1 ovs-appctl netdev-dummy/receive hv1-vif${inport} $packet
+ rm -f ipv6_ns.expected
echo $expected_packet >> ipv6_ns.expected
}
src_mac=506400000002
dst_mac=00000000af01
src_ip=aef0000000000000526400fffe000002
+dst_ip=20010db800010000020002fffe010205
+dst_mcast_mac=3333ff010205
+mcast_node_ip=ff0200000000000000000001ff010205
+nd_target=20010db800010000020002fffe010205
# Send an IPv6 packet. Generated IPv6 Neighbor solicitation packet
# should be received by the ports attached to br-phys.
-test_ipv6 1 $src_mac $dst_mac $src_ip 2
+test_ipv6 1 $src_mac $dst_mac $src_ip $dst_ip $dst_mcast_mac \
+$mcast_node_ip $nd_target
+
+OVS_WAIT_WHILE([test 24 = $(wc -c hv1/br-phys_n1-tx.pcap | cut -d " " -f1)])
+OVS_WAIT_WHILE([test 24 = $(wc -c hv1/br-phys-tx.pcap | cut -d " " -f1)])
+
+$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/br-phys_n1-tx.pcap | \
+trim_zeros > 1.packets
+$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/br-phys-tx.pcap | \
+trim_zeros > 2.packets
+
+cat ipv6_ns.expected | cut -c -112 > expout
+AT_CHECK([cat 1.packets | cut -c -112], [0], [expout])
+AT_CHECK([cat 2.packets | cut -c -112], [0], [expout])
+
+# Skipping the ICMPv6 checksum
+cat ipv6_ns.expected | cut -c 117- > expout
+AT_CHECK([cat 1.packets | cut -c 117-], [0], [expout])
+AT_CHECK([cat 2.packets | cut -c 117-], [0], [expout])
+
+# Now send a packet with destination ip other than
+# 2001:db8:1:0:200:02ff:fe01:0204/64 prefix.
+reset_pcap_file br-phys_n1 hv1/br-phys_n1
+reset_pcap_file br-phys hv1/br-phys
+
+src_mac=506400000002
+dst_mac=00000000af01
+src_ip=aef0000000000000526400fffe000002
+dst_ip=20020ab8000100000200020000020306
+# multicast mac of the nexthop IP - 2001:db8:1:0:200:02ff:fe01:1305
+dst_mcast_mac=3333ff011305
+mcast_node_ip=ff0200000000000000000001ff011305
+nd_target=20010db800010000020002fffe011305
+test_ipv6 1 $src_mac $dst_mac $src_ip $dst_ip $dst_mcast_mac \
+$mcast_node_ip $nd_target
OVS_WAIT_WHILE([test 24 = $(wc -c hv1/br-phys_n1-tx.pcap | cut -d " " -f1)])
OVS_WAIT_WHILE([test 24 = $(wc -c hv1/br-phys-tx.pcap | cut -d " " -f1)])
@@ -9900,7 +10003,7 @@
# And the other address mode
ovn-nbctl --wait=hv set Logical_Router_Port ro-sw ipv6_ra_configs:address_mode=dhcpv6_stateless
-ra_test 000005dc 40 80 40 aef00000000000000000000000000000 30 fd0f0000000000000000000000000000
+ra_test 000005dc 40 c0 40 aef00000000000000000000000000000 30 fd0f0000000000000000000000000000
OVN_CLEANUP([hv1],[hv2])
AT_CLEANUP
@@ -11194,3 +11297,43 @@
OVN_CLEANUP([hv1],[hv2])
AT_CLEANUP
+
+AT_SETUP([ovn -- ipam to non-ipam])
+ovn_start
+
+ovn-nbctl ls-add sw0
+ovn-nbctl lsp-add sw0 p0 -- lsp-set-addresses p0 dynamic
+ovn-nbctl --wait=sb add Logical-Switch sw0 other_config subnet=192.168.1.0/24
+
+AT_CHECK([ovn-nbctl get Logical-Switch-Port p0 dynamic_addresses], [0],
+ ["0a:00:00:00:00:01 192.168.1.2"
+])
+
+ovn-nbctl lsp-set-addresses p0 router
+
+ovn-nbctl get Logical-Switch-Port p0 dynamic_addresses
+
+AT_CHECK([ovn-nbctl get Logical-Switch-Port p0 dynamic_addresses], [0], [[[]]
+])
+AT_CLEANUP
+
+AT_SETUP([ovn -- ipam router ports])
+ovn_start
+
+ovn-nbctl ls-add sw
+ovn-nbctl set logical_switch sw other-config:subnet=192.168.1.0/24
+
+for i in 2 3 4; do
+ ovn-nbctl lr-add ro$i
+ ovn-nbctl lsp-add sw swp$i
+ ovn-nbctl --wait=sb lsp-set-addresses swp$i "02:00:00:00:00:0$i dynamic"
+ cidr=$(ovn-nbctl get logical_switch_port swp$i dynamic_addresses |cut -f2 -d' '|cut -f1 -d\")
+ ovn-nbctl lrp-add ro$i rop$i 02:00:00:00:00:0$i $cidr/24 -- set logical_switch_port swp$i type=router options:router-port=rop$i addresses=router;
+ AT_CHECK_UNQUOTED([ovn-nbctl get logical_router_port rop$i networks], [0], [[["192.168.1.$i/24"]]
+])
+done
+
+ovn-nbctl list logical_switch_port
+ovn-nbctl list logical_router_port
+
+AT_CLEANUP
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/ovn-nbctl.at openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/ovn-nbctl.at
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/ovn-nbctl.at 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/ovn-nbctl.at 2020-03-11 16:15:44.000000000 +0000
@@ -1517,3 +1517,25 @@
AT_CHECK([ovn-nbctl get Port_Group pg0 name], [0], [dnl
"pg0"
])])
+
+
+OVN_NBCTL_TEST([ovn_nbctl_extra_newlines], [extra newlines], [
+dnl This test addresses a specific issue seen when running ovn-nbctl in
+dnl daemon mode. All we have to do is ensure that each time we list database
+dnl information, there is not an extra newline at the beginning of the output.
+AT_CHECK([ovn-nbctl ls-add sw1], [0], [ignore])
+AT_CHECK([ovn-nbctl --columns=name list logical_switch sw1], [0], [dnl
+name : "sw1"
+])
+AT_CHECK([ovn-nbctl --columns=name list logical_switch sw1], [0], [dnl
+name : "sw1"
+])])
+
+OVN_NBCTL_TEST([ovn_nbctl_table_formatting], [table formatting], [
+dnl This test addresses a specific issue seen when running ovn-nbctl in
+dnl daemon mode. We need to ensure that table formatting options are honored
+dnl when listing database information.
+AT_CHECK([ovn-nbctl ls-add sw1], [0], [ignore])
+AT_CHECK([ovn-nbctl --bare --columns=name list logical_switch sw1], [0], [dnl
+sw1
+])])
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/ovsdb-condition.at openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/ovsdb-condition.at
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/ovsdb-condition.at 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/ovsdb-condition.at 2020-03-11 16:15:44.000000000 +0000
@@ -92,7 +92,58 @@
'[["u", ">", ["uuid", "b10d28f7-af18-4a67-9e78-2a6394516c59"]]]' \
'[["u", ">=", ["uuid", "9179ca6d-6d65-400a-b455-3ad92783a099"]]]' \
'[["u", "<", ["uuid", "ad0fa355-8b84-4a36-a4b5-b2c1bfd91758"]]]' \
- '[["u", "<=", ["uuid", "62315898-64e0-40b9-b26f-ff74225303e6"]]]']],
+ '[["u", "<=", ["uuid", "62315898-64e0-40b9-b26f-ff74225303e6"]]]' \
+ '[["i", "==", ["set", []]]]' \
+ '[["i", "!=", ["set", []]]]' \
+ '[["i", ">", ["set", []]]]' \
+ '[["i", ">=", ["set", []]]]' \
+ '[["i", "<", ["set", []]]]' \
+ '[["i", "<=", ["set", []]]]' \
+ '[["i", "includes", ["set", []]]]' \
+ '[["i", "excludes", ["set", []]]]' \
+ '[["i", ">", ["set", []]]]' \
+ '[["i", "==", ["set", []]]]' \
+ '[["r", "==", ["set", []]]]' \
+ '[["r", "!=", ["set", []]]]' \
+ '[["r", ">", ["set", []]]]' \
+ '[["r", ">=", ["set", []]]]' \
+ '[["r", "<", ["set", []]]]' \
+ '[["r", "<=", ["set", []]]]' \
+ '[["r", "includes", ["set", []]]]' \
+ '[["r", "excludes", ["set", []]]]' \
+ '[["r", ">", ["set", []]]]' \
+ '[["r", "==", ["set", []]]]' \
+ '[["b", "==", ["set", []]]]' \
+ '[["b", "!=", ["set", []]]]' \
+ '[["b", ">", ["set", []]]]' \
+ '[["b", ">=", ["set", []]]]' \
+ '[["b", "<", ["set", []]]]' \
+ '[["b", "<=", ["set", []]]]' \
+ '[["b", "includes", ["set", []]]]' \
+ '[["b", "excludes", ["set", []]]]' \
+ '[["b", ">", ["set", []]]]' \
+ '[["b", "==", ["set", []]]]' \
+ '[["s", "==", ["set", []]]]' \
+ '[["s", "!=", ["set", []]]]' \
+ '[["s", ">", ["set", []]]]' \
+ '[["s", ">=", ["set", []]]]' \
+ '[["s", "<", ["set", []]]]' \
+ '[["s", "<=", ["set", []]]]' \
+ '[["s", "includes", ["set", []]]]' \
+ '[["s", "excludes", ["set", []]]]' \
+ '[["s", ">", ["set", []]]]' \
+ '[["s", "==", ["set", []]]]' \
+ '[["u", "==", ["set", []]]]' \
+ '[["u", "!=", ["set", []]]]' \
+ '[["u", ">", ["set", []]]]' \
+ '[["u", ">=", ["set", []]]]' \
+ '[["u", "<", ["set", []]]]' \
+ '[["u", "<=", ["set", []]]]' \
+ '[["u", "includes", ["set", []]]]' \
+ '[["u", "excludes", ["set", []]]]' \
+ '[["u", ">", ["set", []]]]' \
+ '[["u", "==", ["set", []]]]' \
+]],
[1], [],
[[test-ovsdb: syntax "["b",">",true]": syntax error: Type mismatch: ">" operator may not be applied to column b of type boolean.
test-ovsdb: syntax "["b",">=",false]": syntax error: Type mismatch: ">=" operator may not be applied to column b of type boolean.
@@ -106,6 +157,209 @@
test-ovsdb: syntax "["u",">=",["uuid","9179ca6d-6d65-400a-b455-3ad92783a099"]]": syntax error: Type mismatch: ">=" operator may not be applied to column u of type uuid.
test-ovsdb: syntax "["u","<",["uuid","ad0fa355-8b84-4a36-a4b5-b2c1bfd91758"]]": syntax error: Type mismatch: "<" operator may not be applied to column u of type uuid.
test-ovsdb: syntax "["u","<=",["uuid","62315898-64e0-40b9-b26f-ff74225303e6"]]": syntax error: Type mismatch: "<=" operator may not be applied to column u of type uuid.
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["b",">",["set",[]]]": syntax error: Type mismatch: ">" operator may not be applied to column b of type boolean.
+test-ovsdb: syntax "["b",">=",["set",[]]]": syntax error: Type mismatch: ">=" operator may not be applied to column b of type boolean.
+test-ovsdb: syntax "["b","<",["set",[]]]": syntax error: Type mismatch: "<" operator may not be applied to column b of type boolean.
+test-ovsdb: syntax "["b","<=",["set",[]]]": syntax error: Type mismatch: "<=" operator may not be applied to column b of type boolean.
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["b",">",["set",[]]]": syntax error: Type mismatch: ">" operator may not be applied to column b of type boolean.
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["s",">",["set",[]]]": syntax error: Type mismatch: ">" operator may not be applied to column s of type string.
+test-ovsdb: syntax "["s",">=",["set",[]]]": syntax error: Type mismatch: ">=" operator may not be applied to column s of type string.
+test-ovsdb: syntax "["s","<",["set",[]]]": syntax error: Type mismatch: "<" operator may not be applied to column s of type string.
+test-ovsdb: syntax "["s","<=",["set",[]]]": syntax error: Type mismatch: "<=" operator may not be applied to column s of type string.
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["s",">",["set",[]]]": syntax error: Type mismatch: ">" operator may not be applied to column s of type string.
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["u",">",["set",[]]]": syntax error: Type mismatch: ">" operator may not be applied to column u of type uuid.
+test-ovsdb: syntax "["u",">=",["set",[]]]": syntax error: Type mismatch: ">=" operator may not be applied to column u of type uuid.
+test-ovsdb: syntax "["u","<",["set",[]]]": syntax error: Type mismatch: "<" operator may not be applied to column u of type uuid.
+test-ovsdb: syntax "["u","<=",["set",[]]]": syntax error: Type mismatch: "<=" operator may not be applied to column u of type uuid.
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["u",">",["set",[]]]": syntax error: Type mismatch: ">" operator may not be applied to column u of type uuid.
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+]])
+AT_CLEANUP
+
+OVSDB_CHECK_POSITIVE([conditions on optional scalars],
+ [[parse-conditions \
+ '{"columns":
+ {"i": {"type": {"key": "integer", "min": 0, "max": 1}},
+ "r": {"type": {"key": "real", "min": 0, "max": 1}},
+ "b": {"type": {"key": "boolean", "min": 0, "max": 1}},
+ "s": {"type": {"key": "string", "min": 0, "max": 1}},
+ "u": {"type": {"key": "uuid", "min": 0, "max": 1}}}}' \
+ '[["i", "==", 0]]' \
+ '[["i", "!=", 1]]' \
+ '[["i", "<", 2]]' \
+ '[["i", "<=", 3]]' \
+ '[["i", ">", 4]]' \
+ '[["i", ">=", 5]]' \
+ '[["i", "includes", 6]]' \
+ '[["i", "excludes", 7]]' \
+ '[["r", "==", 0.5]]' \
+ '[["r", "!=", 1.5]]' \
+ '[["r", "<", 2.5]]' \
+ '[["r", "<=", 3.5]]' \
+ '[["r", ">", 4.5]]' \
+ '[["r", ">=", 5.5]]' \
+ '[["r", "includes", 6.5]]' \
+ '[["r", "excludes", 7.5]]' \
+ '[["b", "==", true]]' \
+ '[["b", "!=", false]]' \
+ '[["b", "includes", false]]' \
+ '[["b", "excludes", true]]' \
+ '[["s", "==", "a"]]' \
+ '[["s", "!=", "b"]]' \
+ '[["s", "includes", "c"]]' \
+ '[["s", "excludes", "d"]]' \
+ '[["u", "==", ["uuid", "b10d28f7-af18-4a67-9e78-2a6394516c59"]]]' \
+ '[["u", "!=", ["uuid", "9179ca6d-6d65-400a-b455-3ad92783a099"]]]' \
+ '[["u", "includes", ["uuid", "ad0fa355-8b84-4a36-a4b5-b2c1bfd91758"]]]' \
+ '[["u", "excludes", ["uuid", "62315898-64e0-40b9-b26f-ff74225303e6"]]]']],
+ [[[["i","==",0]]
+[["i","!=",1]]
+[["i","<",2]]
+[["i","<=",3]]
+[["i",">",4]]
+[["i",">=",5]]
+[["i","includes",6]]
+[["i","excludes",7]]
+[["r","==",0.5]]
+[["r","!=",1.5]]
+[["r","<",2.5]]
+[["r","<=",3.5]]
+[["r",">",4.5]]
+[["r",">=",5.5]]
+[["r","includes",6.5]]
+[["r","excludes",7.5]]
+[["b","==",true]]
+[["b","!=",false]]
+[["b","includes",false]]
+[["b","excludes",true]]
+[["s","==","a"]]
+[["s","!=","b"]]
+[["s","includes","c"]]
+[["s","excludes","d"]]
+[["u","==",["uuid","b10d28f7-af18-4a67-9e78-2a6394516c59"]]]
+[["u","!=",["uuid","9179ca6d-6d65-400a-b455-3ad92783a099"]]]
+[["u","includes",["uuid","ad0fa355-8b84-4a36-a4b5-b2c1bfd91758"]]]
+[["u","excludes",["uuid","62315898-64e0-40b9-b26f-ff74225303e6"]]]]],
+ [condition])
+
+AT_SETUP([disallowed conditions on optional scalars])
+AT_KEYWORDS([ovsdb negative condition])
+AT_CHECK([[test-ovsdb parse-conditions \
+ '{"columns":
+ {"i": {"type": {"key": "integer", "min": 0, "max": 1}},
+ "r": {"type": {"key": "real", "min": 0, "max": 1}},
+ "b": {"type": {"key": "boolean", "min": 0, "max": 1}},
+ "s": {"type": {"key": "string", "min": 0, "max": 1}},
+ "u": {"type": {"key": "uuid", "min": 0, "max": 1}}}}' \
+ '[["b", ">", true]]' \
+ '[["b", ">=", false]]' \
+ '[["b", "<", false]]' \
+ '[["b", "<=", false]]' \
+ '[["s", ">", "a"]]' \
+ '[["s", ">=", "b"]]' \
+ '[["s", "<", "c"]]' \
+ '[["s", "<=", "d"]]' \
+ '[["u", ">", ["uuid", "b10d28f7-af18-4a67-9e78-2a6394516c59"]]]' \
+ '[["u", ">=", ["uuid", "9179ca6d-6d65-400a-b455-3ad92783a099"]]]' \
+ '[["u", "<", ["uuid", "ad0fa355-8b84-4a36-a4b5-b2c1bfd91758"]]]' \
+ '[["u", "<=", ["uuid", "62315898-64e0-40b9-b26f-ff74225303e6"]]]' \
+ '[["i", ">", ["set", []]]]' \
+ '[["i", ">=", ["set", []]]]' \
+ '[["i", "<", ["set", []]]]' \
+ '[["i", "<=", ["set", []]]]' \
+ '[["i", ">", ["set", []]]]' \
+ '[["r", ">", ["set", []]]]' \
+ '[["r", ">=", ["set", []]]]' \
+ '[["r", "<", ["set", []]]]' \
+ '[["r", "<=", ["set", []]]]' \
+ '[["r", ">", ["set", []]]]' \
+ '[["b", ">", ["set", []]]]' \
+ '[["b", ">=", ["set", []]]]' \
+ '[["b", "<", ["set", []]]]' \
+ '[["b", "<=", ["set", []]]]' \
+ '[["b", ">", ["set", []]]]' \
+ '[["s", ">", ["set", []]]]' \
+ '[["s", ">=", ["set", []]]]' \
+ '[["s", "<", ["set", []]]]' \
+ '[["s", "<=", ["set", []]]]' \
+ '[["s", ">", ["set", []]]]' \
+ '[["u", ">", ["set", []]]]' \
+ '[["u", ">=", ["set", []]]]' \
+ '[["u", "<", ["set", []]]]' \
+ '[["u", "<=", ["set", []]]]' \
+ '[["u", ">", ["set", []]]]' \
+]],
+ [1], [], [[test-ovsdb: syntax "["b",">",true]": syntax error: Type mismatch: ">" operator may not be applied to column b of type set of up to 1 booleans.
+test-ovsdb: syntax "["b",">=",false]": syntax error: Type mismatch: ">=" operator may not be applied to column b of type set of up to 1 booleans.
+test-ovsdb: syntax "["b","<",false]": syntax error: Type mismatch: "<" operator may not be applied to column b of type set of up to 1 booleans.
+test-ovsdb: syntax "["b","<=",false]": syntax error: Type mismatch: "<=" operator may not be applied to column b of type set of up to 1 booleans.
+test-ovsdb: syntax "["s",">","a"]": syntax error: Type mismatch: ">" operator may not be applied to column s of type set of up to 1 strings.
+test-ovsdb: syntax "["s",">=","b"]": syntax error: Type mismatch: ">=" operator may not be applied to column s of type set of up to 1 strings.
+test-ovsdb: syntax "["s","<","c"]": syntax error: Type mismatch: "<" operator may not be applied to column s of type set of up to 1 strings.
+test-ovsdb: syntax "["s","<=","d"]": syntax error: Type mismatch: "<=" operator may not be applied to column s of type set of up to 1 strings.
+test-ovsdb: syntax "["u",">",["uuid","b10d28f7-af18-4a67-9e78-2a6394516c59"]]": syntax error: Type mismatch: ">" operator may not be applied to column u of type set of up to 1 uuids.
+test-ovsdb: syntax "["u",">=",["uuid","9179ca6d-6d65-400a-b455-3ad92783a099"]]": syntax error: Type mismatch: ">=" operator may not be applied to column u of type set of up to 1 uuids.
+test-ovsdb: syntax "["u","<",["uuid","ad0fa355-8b84-4a36-a4b5-b2c1bfd91758"]]": syntax error: Type mismatch: "<" operator may not be applied to column u of type set of up to 1 uuids.
+test-ovsdb: syntax "["u","<=",["uuid","62315898-64e0-40b9-b26f-ff74225303e6"]]": syntax error: Type mismatch: "<=" operator may not be applied to column u of type set of up to 1 uuids.
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["set",[]]": syntax error: set must have exactly one member but 0 are present
+test-ovsdb: syntax "["b",">",["set",[]]]": syntax error: Type mismatch: ">" operator may not be applied to column b of type set of up to 1 booleans.
+test-ovsdb: syntax "["b",">=",["set",[]]]": syntax error: Type mismatch: ">=" operator may not be applied to column b of type set of up to 1 booleans.
+test-ovsdb: syntax "["b","<",["set",[]]]": syntax error: Type mismatch: "<" operator may not be applied to column b of type set of up to 1 booleans.
+test-ovsdb: syntax "["b","<=",["set",[]]]": syntax error: Type mismatch: "<=" operator may not be applied to column b of type set of up to 1 booleans.
+test-ovsdb: syntax "["b",">",["set",[]]]": syntax error: Type mismatch: ">" operator may not be applied to column b of type set of up to 1 booleans.
+test-ovsdb: syntax "["s",">",["set",[]]]": syntax error: Type mismatch: ">" operator may not be applied to column s of type set of up to 1 strings.
+test-ovsdb: syntax "["s",">=",["set",[]]]": syntax error: Type mismatch: ">=" operator may not be applied to column s of type set of up to 1 strings.
+test-ovsdb: syntax "["s","<",["set",[]]]": syntax error: Type mismatch: "<" operator may not be applied to column s of type set of up to 1 strings.
+test-ovsdb: syntax "["s","<=",["set",[]]]": syntax error: Type mismatch: "<=" operator may not be applied to column s of type set of up to 1 strings.
+test-ovsdb: syntax "["s",">",["set",[]]]": syntax error: Type mismatch: ">" operator may not be applied to column s of type set of up to 1 strings.
+test-ovsdb: syntax "["u",">",["set",[]]]": syntax error: Type mismatch: ">" operator may not be applied to column u of type set of up to 1 uuids.
+test-ovsdb: syntax "["u",">=",["set",[]]]": syntax error: Type mismatch: ">=" operator may not be applied to column u of type set of up to 1 uuids.
+test-ovsdb: syntax "["u","<",["set",[]]]": syntax error: Type mismatch: "<" operator may not be applied to column u of type set of up to 1 uuids.
+test-ovsdb: syntax "["u","<=",["set",[]]]": syntax error: Type mismatch: "<=" operator may not be applied to column u of type set of up to 1 uuids.
+test-ovsdb: syntax "["u",">",["set",[]]]": syntax error: Type mismatch: ">" operator may not be applied to column u of type set of up to 1 uuids.
]])
AT_CLEANUP
@@ -600,7 +854,11 @@
[["i", ">", 1]],
[["i", "includes", 1]],
[["i", "excludes", 1]],
- [["i", ">", 0], ["i", "<", 2]]]' \
+ [["i", ">", 0], ["i", "<", 2]],
+ [["i", "==", ["set", []]]],
+ [["i", "!=", ["set", []]]],
+ [["i", "includes", ["set", []]]],
+ [["i", "excludes", ["set", []]]]]' \
'[{"i": ["set", []]},
{"i": ["set", [0]]},
{"i": ["set", [1]]},
@@ -614,7 +872,11 @@
condition 5: ---T
condition 6: --T-
condition 7: TT-T
-condition 8: --T-], [condition])
+condition 8: --T-
+condition 9: T---
+condition 10: -TTT
+condition 11: TTTT
+condition 12: TTTT], [condition])
OVSDB_CHECK_POSITIVE([evaluating conditions on optional strings],
[[evaluate-conditions \
@@ -654,7 +916,11 @@
[["r", ">", 5.0]],
[["r", "includes", 5.0]],
[["r", "excludes", 5.0]],
- [["r", "!=", 0], ["r", "!=", 5.1]]]' \
+ [["r", "!=", 0], ["r", "!=", 5.1]],
+ [["r", "==", ["set", []]]],
+ [["r", "!=", ["set", []]]],
+ [["r", "includes", ["set", []]]],
+ [["r", "excludes", ["set", []]]]]' \
'[{"r": ["set", [0]]},
{"r": ["set", [5.0]]},
{"r": ["set", [5.1]]},
@@ -668,7 +934,11 @@
condition 5: --T-
condition 6: -T--
condition 7: T-TT
-condition 8: -T-T], [condition])
+condition 8: -T-T
+condition 9: ---T
+condition 10: TTT-
+condition 11: TTTT
+condition 12: TTTT], [condition])
OVSDB_CHECK_POSITIVE([evaluating false boolean condition],
[[evaluate-conditions-any \
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/ovsdb-idl.at openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/ovsdb-idl.at
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/ovsdb-idl.at 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/ovsdb-idl.at 2020-03-11 16:15:44.000000000 +0000
@@ -1785,6 +1785,23 @@
008: End test
]])
+m4_define([CHECK_STREAM_OPEN_BLOCK],
+ [AT_SETUP([Check Stream open block - C - $1])
+ AT_SKIP_IF([test "$1" = "tcp6" && test "$IS_WIN32" = "yes"])
+ AT_SKIP_IF([test "$1" = "tcp6" && test "$HAVE_IPV6" = "no"])
+ AT_KEYWORDS([Check Stream open block $1])
+ AT_CHECK([ovsdb_start_idltest "ptcp:0:$2"])
+ PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT])
+ WRONG_PORT=$(($TCP_PORT+1))
+ AT_CHECK([test-stream tcp:$2:$TCP_PORT], [0], [ignore])
+ AT_CHECK([test-stream tcp:$2:$WRONG_PORT], [1], [ignore], [ignore])
+ OVSDB_SERVER_SHUTDOWN
+ AT_CHECK([test-stream tcp:$2:$TCP_PORT], [1], [ignore], [ignore])
+ AT_CLEANUP])
+
+CHECK_STREAM_OPEN_BLOCK([tcp], [127.0.0.1])
+CHECK_STREAM_OPEN_BLOCK([tcp6], [[[::1]]])
+
m4_define([CHECK_STREAM_OPEN_BLOCK_PY],
[AT_SETUP([$1])
AT_SKIP_IF([test $2 = no])
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/ovsdb-monitor.at openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/ovsdb-monitor.at
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/ovsdb-monitor.at 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/ovsdb-monitor.at 2020-03-11 16:15:44.000000000 +0000
@@ -589,3 +589,71 @@
[[[["name","==","one"]]]],
[[[false]]],
[[[true]]]])
+
+
+AT_SETUP(monitor-cond-change with many sessions pending)
+AT_KEYWORDS([ovsdb server monitor monitor-cond negative])
+ordinal_schema > schema
+AT_CHECK([ovsdb-tool create db schema], [0], [stdout], [ignore])
+
+AT_CAPTURE_FILE([ovsdb-server-log])
+AT_CHECK([ovsdb-server --detach --no-chdir --pidfile --remote=punix:socket --log-file="`pwd`"/ovsdb-server-log db >/dev/null 2>&1])
+on_exit 'kill `cat ovsdb-server.pid`'
+for txn in m4_foreach([txn], [[[["ordinals",
+ {"op": "insert",
+ "table": "ordinals",
+ "row": {"number": 0, "name": "zero"}},
+ {"op": "insert",
+ "table": "ordinals",
+ "row": {"number": 1, "name": "one"}},
+ {"op": "insert",
+ "table": "ordinals",
+ "row": {"number": 2, "name": "two"}}]]]], ['txn' ]); do
+ AT_CHECK([ovsdb-client transact unix:socket "$txn"], [0], [ignore], [ignore])
+done
+
+# 1001 clients monitoring column "name" and with condition for "name" only.
+# The clients are created in a way that the 991th client will request condition
+# change, so that the chance is high that the condition change will be handled
+# before some pending changes are freed.
+
+cond='[[["name","==","ten"]]]'
+for i in `seq 1 990`; do
+ AT_CHECK([ovsdb-client -vjsonrpc --pidfile=ovsdb-client$i.pid --detach --no-chdir -d json monitor-cond --format=csv unix:socket ordinals $cond ordinals ["name"]], [0], [ignore], [ignore])
+done
+
+AT_CHECK([ovsdb-client -vjsonrpc --pidfile --detach --no-chdir -d json monitor-cond --format=csv unix:socket ordinals $cond ordinals ["name"] > output],
+ [0], [ignore], [ignore])
+
+for i in `seq 991 1000`; do
+ AT_CHECK([ovsdb-client -vjsonrpc --pidfile=ovsdb-client$i.pid --detach --no-chdir -d json monitor-cond --format=csv unix:socket ordinals $cond ordinals ["name"]], [0], [ignore], [ignore])
+done
+
+for txn in m4_foreach([txn], [[[["ordinals",
+ {"op": "insert",
+ "table": "ordinals",
+ "row": {"number": 10, "name": "ten"}}]]]], ['txn' ]); do
+ AT_CHECK([ovsdb-client transact unix:socket "$txn"], [0],
+ [ignore], [ignore], [kill `cat server-pid client-pid`])
+done
+
+# Change the condition so that a new column "number" is added to monitor table.
+cond='[[["number","==",1]]]'
+AT_CHECK([ovs-appctl -t ovsdb-client ovsdb-client/cond_change ordinals $cond], [0], [ignore], [ignore])
+
+# Give some time for the server to flush and free pending changes
+# (to crash, when n_columns is not handled properly)
+sleep 1
+
+AT_CHECK([ovsdb-client transact unix:socket '[["ordinals"]]'], [0],
+ [ignore], [ignore])
+AT_CHECK([ovs-appctl -t ovsdb-server -e exit], [0], [ignore], [ignore])
+OVS_WAIT_UNTIL([test ! -e ovsdb-server.pid && test ! -e ovsdb-client.pid])
+AT_CHECK([$PYTHON $srcdir/ovsdb-monitor-sort.py < output | uuidfilt], [0], [[row,action,name
+<0>,insert,"""ten"""
+
+row,action,name
+<0>,delete,
+<1>,insert,"""one"""
+]], [ignore])
+AT_CLEANUP
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/packet-type-aware.at openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/packet-type-aware.at
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/packet-type-aware.at 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/packet-type-aware.at 2020-03-11 16:15:44.000000000 +0000
@@ -400,8 +400,8 @@
ovs-appctl dpctl/dump-flows --names dummy@ovs-dummy | strip_used | grep -v ipv6 | sort
], [0], [flow-dump from non-dpdk interfaces:
recirc_id(0),in_port(n3),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(dst=192.168.10.10,tos=0/0x3,frag=no), packets:1, bytes:98, used:0.0s, actions:pop_eth,clone(tnl_push(tnl_port(gre_sys),header(size=38,type=3,eth(dst=aa:55:00:00:00:02,src=aa:55:00:00:00:03,dl_type=0x0800),ipv4(src=30.0.0.3,dst=30.0.0.2,proto=47,tos=0,ttl=64,frag=0x4000),gre((flags=0x0,proto=0x800))),out_port(br-p3)),set(ipv4(src=20.0.0.3,dst=20.0.0.2)),tnl_pop(gre_sys))
-tunnel(src=10.0.0.2,dst=10.0.0.1,flags(-df-csum)),recirc_id(0),in_port(gre_sys),packet_type(ns=1,id=0x800),ipv4(dst=192.168.10.10,frag=no), packets:1, bytes:84, used:0.0s, actions:push_eth(src=00:00:00:00:00:00,dst=aa:55:aa:55:00:01),n1
-tunnel(src=20.0.0.3,dst=20.0.0.2,flags(-df-csum)),recirc_id(0),in_port(gre_sys),packet_type(ns=1,id=0x800),ipv4(dst=192.168.10.10,tos=0/0x3,frag=no), packets:1, bytes:84, used:0.0s, actions:clone(tnl_push(tnl_port(gre_sys),header(size=38,type=3,eth(dst=aa:55:00:00:00:01,src=aa:55:00:00:00:02,dl_type=0x0800),ipv4(src=20.0.0.2,dst=20.0.0.1,proto=47,tos=0,ttl=64,frag=0x4000),gre((flags=0x0,proto=0x800))),out_port(br-p2)),set(ipv4(src=10.0.0.2,dst=10.0.0.1)),tnl_pop(gre_sys))
+tunnel(src=10.0.0.2,dst=10.0.0.1,flags(-df-csum)),recirc_id(0),in_port(gre_sys),packet_type(ns=1,id=0x800),eth_type(0x0800),ipv4(dst=192.168.10.10,frag=no), packets:1, bytes:84, used:0.0s, actions:push_eth(src=00:00:00:00:00:00,dst=aa:55:aa:55:00:01),n1
+tunnel(src=20.0.0.3,dst=20.0.0.2,flags(-df-csum)),recirc_id(0),in_port(gre_sys),packet_type(ns=1,id=0x800),eth_type(0x0800),ipv4(dst=192.168.10.10,tos=0/0x3,frag=no), packets:1, bytes:84, used:0.0s, actions:clone(tnl_push(tnl_port(gre_sys),header(size=38,type=3,eth(dst=aa:55:00:00:00:01,src=aa:55:00:00:00:02,dl_type=0x0800),ipv4(src=20.0.0.2,dst=20.0.0.1,proto=47,tos=0,ttl=64,frag=0x4000),gre((flags=0x0,proto=0x800))),out_port(br-p2)),set(ipv4(src=10.0.0.2,dst=10.0.0.1)),tnl_pop(gre_sys))
])
# Clear up megaflow cache
@@ -505,7 +505,7 @@
ovs-appctl dpctl/dump-flows --names dummy@ovs-dummy | strip_used | grep -v ipv6 | sort
], [0], [flow-dump from non-dpdk interfaces:
recirc_id(0),in_port(n3),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(dst=192.168.10.20,tos=0/0x3,frag=no), packets:1, bytes:98, used:0.0s, actions:pop_eth,clone(tnl_push(tnl_port(gre_sys),header(size=38,type=3,eth(dst=aa:55:00:00:00:02,src=aa:55:00:00:00:03,dl_type=0x0800),ipv4(src=30.0.0.3,dst=30.0.0.2,proto=47,tos=0,ttl=64,frag=0x4000),gre((flags=0x0,proto=0x800))),out_port(br-p3)),set(ipv4(src=20.0.0.3,dst=20.0.0.2)),tnl_pop(gre_sys))
-tunnel(src=20.0.0.3,dst=20.0.0.2,flags(-df-csum)),recirc_id(0),in_port(gre_sys),packet_type(ns=1,id=0x800),ipv4(dst=192.168.10.20,frag=no), packets:1, bytes:84, used:0.0s, actions:drop
+tunnel(src=20.0.0.3,dst=20.0.0.2,flags(-df-csum)),recirc_id(0),in_port(gre_sys),packet_type(ns=1,id=0x800),eth_type(0x0800),ipv4(dst=192.168.10.20,frag=no), packets:1, bytes:84, used:0.0s, actions:drop
])
OVS_VSWITCHD_STOP(["/The Open vSwitch kernel module is probably not loaded/d"])
@@ -1020,7 +1020,7 @@
ovs-appctl dpctl/dump-flows --names dummy@ovs-dummy | strip_used | grep -v ipv6 | sort
], [0], [flow-dump from non-dpdk interfaces:
recirc_id(0),in_port(p0),packet_type(ns=0,id=0),eth(src=aa:bb:cc:00:00:02,dst=aa:bb:cc:00:00:01),eth_type(0x0800),ipv4(dst=20.0.0.1,proto=47,frag=no), packets:3, bytes:378, used:0.0s, actions:tnl_pop(gre_sys)
-tunnel(src=20.0.0.2,dst=20.0.0.1,flags(-df-csum)),recirc_id(0),in_port(gre_sys),packet_type(ns=1,id=0x8847),mpls(label=999/0x0,tc=0/0,ttl=64/0x0,bos=1/1), packets:3, bytes:264, used:0.0s, actions:push_eth(src=00:00:00:00:00:00,dst=00:00:00:00:00:00),pop_mpls(eth_type=0x800),recirc(0x1)
+tunnel(src=20.0.0.2,dst=20.0.0.1,flags(-df-csum)),recirc_id(0),in_port(gre_sys),packet_type(ns=1,id=0x8847),eth_type(0x8847),mpls(label=999/0x0,tc=0/0,ttl=64/0x0,bos=1/1), packets:3, bytes:264, used:0.0s, actions:push_eth(src=00:00:00:00:00:00,dst=00:00:00:00:00:00),pop_mpls(eth_type=0x800),recirc(0x1)
tunnel(src=20.0.0.2,dst=20.0.0.1,flags(-df-csum)),recirc_id(0x1),in_port(gre_sys),packet_type(ns=0,id=0),eth(dst=00:00:00:00:00:00),eth_type(0x0800),ipv4(ttl=64,frag=no), packets:3, bytes:294, used:0.0s, actions:set(ipv4(ttl=63)),int-br
])
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/system-kmod-macros.at openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/system-kmod-macros.at
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/system-kmod-macros.at 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/system-kmod-macros.at 2020-03-11 16:15:44.000000000 +0000
@@ -114,6 +114,13 @@
#
m4_define([CHECK_CONNTRACK_NAT])
+# CHECK_CT_DPIF_PER_ZONE_LIMIT()
+#
+# Perform requirements checks for running ovs-dpctl ct-[set|get|del]-limits per
+# zone. The kernel datapath does support this feature. Will remove this check
+# after both kernel and userspace datapath support it.
+m4_define([CHECK_CT_DPIF_PER_ZONE_LIMIT])
+
# CHECK_CT_DPIF_SET_GET_MAXCONNS()
#
# Perform requirements checks for running ovs-dpctl ct-set-maxconns or
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/system-traffic.at openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/system-traffic.at
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/system-traffic.at 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/system-traffic.at 2020-03-11 16:15:44.000000000 +0000
@@ -527,6 +527,46 @@
OVS_TRAFFIC_VSWITCHD_STOP
AT_CLEANUP
+AT_SETUP([datapath - flow resume with geneve tun_metadata])
+OVS_CHECK_GENEVE()
+
+OVS_TRAFFIC_VSWITCHD_START()
+ADD_BR([br-underlay])
+
+ADD_NAMESPACES(at_ns0)
+
+dnl Set up underlay link from host into the namespace using veth pair.
+ADD_VETH(p0, at_ns0, br-underlay, "172.31.1.1/24")
+AT_CHECK([ip addr add dev br-underlay "172.31.1.100/24"])
+AT_CHECK([ip link set dev br-underlay up])
+
+dnl Set up tunnel endpoints on OVS outside the namespace and with a native
+dnl linux device inside the namespace.
+ADD_OVS_TUNNEL([geneve], [br0], [at_gnv0], [172.31.1.1], [10.1.1.100/24])
+ADD_NATIVE_TUNNEL([geneve], [ns_gnv0], [at_ns0], [172.31.1.100], [10.1.1.1/24],
+ [vni 0])
+
+dnl Set up flows
+AT_DATA([flows.txt], [dnl
+table=0, arp action=NORMAL
+table=0, in_port=LOCAL icmp action=output:at_gnv0
+table=0, in_port=at_gnv0 icmp action=set_field:0xa->tun_metadata0,resubmit(,1)
+table=1, icmp action=controller(pause), resubmit(,2)
+table=2, tun_metadata0=0xa, icmp action=output:LOCAL
+])
+AT_CHECK([ovs-ofctl add-tlv-map br0 "{class=0xffff,type=0,len=4}->tun_metadata0"])
+AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
+AT_CHECK([ovs-ofctl add-flow br-underlay "actions=normal"])
+
+AT_CHECK([ovs-ofctl monitor br0 resume --detach --no-chdir --pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log])
+
+NS_CHECK_EXEC([at_ns0], [ping -q -c 3 10.1.1.100 | FORMAT_PING], [0], [dnl
+3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+
+OVS_TRAFFIC_VSWITCHD_STOP
+AT_CLEANUP
+
AT_SETUP([datapath - ping over geneve6 tunnel])
OVS_CHECK_GENEVE_UDP6ZEROCSUM()
@@ -2920,7 +2960,7 @@
AT_SETUP([conntrack - limit by zone])
CHECK_CONNTRACK()
-CHECK_CT_DPIF_FLUSH_BY_CT_TUPLE()
+CHECK_CT_DPIF_PER_ZONE_LIMIT()
OVS_TRAFFIC_VSWITCHD_START()
ADD_NAMESPACES(at_ns0, at_ns1)
@@ -3776,8 +3816,9 @@
dnl Checks the implementation of conntrack with FTP ALGs in combination with
dnl NAT, using the provided flow table.
m4_define([CHECK_FTP_NAT],
- [AT_SETUP([conntrack - FTP NAT $1])
+ [AT_SETUP([conntrack - FTP $1])
AT_SKIP_IF([test $HAVE_FTP = no])
+ AT_SKIP_IF([test $HAVE_LFTP = no])
CHECK_CONNTRACK()
CHECK_CONNTRACK_NAT()
CHECK_CONNTRACK_ALG()
@@ -3798,7 +3839,18 @@
OVS_START_L7([at_ns1], [ftp])
dnl FTP requests from p0->p1 should work fine.
- NS_CHECK_EXEC([at_ns0], [wget ftp://10.1.1.2 -4 --no-passive-ftp -t 3 -T 1 --retry-connrefused -v --server-response --no-remove-listing -o wget0.log -d])
+ AT_DATA([ftp.cmd], [dnl
+set net:max-retries 1
+set net:timeout 1
+set ftp:passive-mode off
+cache off
+connect ftp://anonymous:@10.1.1.2
+ls
+ls
+ls
+ls
+])
+ NS_CHECK_EXEC([at_ns0], [lftp -f ftp.cmd > lftp.log])
dnl Discards CLOSE_WAIT and CLOSING
AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1.2)], [0], [$4])
@@ -3806,7 +3858,7 @@
OVS_TRAFFIC_VSWITCHD_STOP
AT_CLEANUP])
-dnl CHECK_FTP_NAT_PRE_RECIRC(TITLE, IP_ADDR, IP_ADDR_AS_HEX)
+dnl CHECK_FTP_SNAT_PRE_RECIRC(TITLE, IP_ADDR, IP_ADDR_AS_HEX)
dnl
dnl Checks the implementation of conntrack with FTP ALGs in combination with
dnl NAT, with flow tables that implement the NATing as part of handling of
@@ -3814,8 +3866,8 @@
dnl
dnl IP_ADDR must specify the NAT address in standard "10.1.1.x" format,
dnl and IP_ADDR_AS_HEX must specify the same address as hex, eg 0x0a0101xx.
-m4_define([CHECK_FTP_NAT_PRE_RECIRC], [dnl
- CHECK_FTP_NAT([prerecirc $1], [$2], [dnl
+m4_define([CHECK_FTP_SNAT_PRE_RECIRC], [dnl
+ CHECK_FTP_NAT([SNAT prerecirc $1], [$2], [dnl
dnl track all IP traffic, de-mangle non-NEW connections
table=0 in_port=1, ip, action=ct(table=1,nat)
table=0 in_port=2, ip, action=ct(table=2,nat)
@@ -3869,7 +3921,7 @@
])
dnl Check that ct(nat,table=foo) works without TCP sequence adjustment.
-CHECK_FTP_NAT_PRE_RECIRC([], [10.1.1.9], [0x0a010109])
+CHECK_FTP_SNAT_PRE_RECIRC([], [10.1.1.9], [0x0a010109])
dnl Check that ct(nat,table=foo) works with TCP sequence adjustment.
dnl
@@ -3880,9 +3932,9 @@
dnl resize the packet and adjust TCP sequence numbers. This test is kept
dnl separate from the above to easier identify issues in this code on different
dnl kernels.
-CHECK_FTP_NAT_PRE_RECIRC([seqadj], [10.1.1.240], [0x0a0101f0])
+CHECK_FTP_SNAT_PRE_RECIRC([seqadj], [10.1.1.240], [0x0a0101f0])
-dnl CHECK_FTP_NAT_POST_RECIRC(TITLE, IP_ADDR, IP_ADDR_AS_HEX)
+dnl CHECK_FTP_SNAT_POST_RECIRC(TITLE, IP_ADDR, IP_ADDR_AS_HEX)
dnl
dnl Checks the implementation of conntrack with FTP ALGs in combination with
dnl NAT, with flow tables that implement the NATing after the first round
@@ -3891,8 +3943,8 @@
dnl
dnl IP_ADDR must specify the NAT address in standard "10.1.1.x" format,
dnl and IP_ADDR_AS_HEX must specify the same address as hex, eg 0x0a0101xx.
-m4_define([CHECK_FTP_NAT_POST_RECIRC], [dnl
- CHECK_FTP_NAT([postrecirc $1], [$2], [dnl
+m4_define([CHECK_FTP_SNAT_POST_RECIRC], [dnl
+ CHECK_FTP_NAT([SNAT postrecirc $1], [$2], [dnl
dnl track all IP traffic (this includes a helper call to non-NEW packets.)
table=0 ip, action=ct(table=1)
dnl
@@ -3935,7 +3987,7 @@
])
dnl Check that ct(nat,table=foo) works without TCP sequence adjustment.
-CHECK_FTP_NAT_POST_RECIRC([], [10.1.1.9], [0x0a010109])
+CHECK_FTP_SNAT_POST_RECIRC([], [10.1.1.9], [0x0a010109])
dnl Check that ct(nat,table=foo) works with TCP sequence adjustment.
dnl
@@ -3946,10 +3998,10 @@
dnl resize the packet and adjust TCP sequence numbers. This test is kept
dnl separate from the above to easier identify issues in this code on different
dnl kernels.
-CHECK_FTP_NAT_POST_RECIRC([seqadj], [10.1.1.240], [0x0a0101f0])
+CHECK_FTP_SNAT_POST_RECIRC([seqadj], [10.1.1.240], [0x0a0101f0])
-dnl CHECK_FTP_NAT_ORIG_TUPLE(TITLE, IP_ADDR, IP_ADDR_AS_HEX)
+dnl CHECK_FTP_SNAT_ORIG_TUPLE(TITLE, IP_ADDR, IP_ADDR_AS_HEX)
dnl
dnl Checks the implementation of conntrack original direction tuple matching
dnl with FTP ALGs in combination with NAT, with flow tables that implement
@@ -3959,8 +4011,8 @@
dnl
dnl IP_ADDR must specify the NAT address in standard "10.1.1.x" format,
dnl and IP_ADDR_AS_HEX must specify the same address as hex, eg 0x0a0101xx.
-m4_define([CHECK_FTP_NAT_ORIG_TUPLE], [dnl
- CHECK_FTP_NAT([orig tuple $1], [$2], [dnl
+m4_define([CHECK_FTP_SNAT_ORIG_TUPLE], [dnl
+ CHECK_FTP_NAT([SNAT orig tuple $1], [$2], [dnl
dnl Store zone in reg4 and packet direction in reg3 (IN=1, OUT=2).
dnl NAT is only applied to OUT-direction packets, so that ACL
dnl processing can be done with non-NATted headers.
@@ -4066,13 +4118,13 @@
dnl Check that ct(nat,table=foo) works without TCP sequence adjustment with
dnl an ACL table based on matching on conntrack original direction tuple only.
-CHECK_FTP_NAT_ORIG_TUPLE([], [10.1.1.9], [0x0a010109])
+CHECK_FTP_SNAT_ORIG_TUPLE([], [10.1.1.9], [0x0a010109])
dnl Check that ct(nat,table=foo) works with TCP sequence adjustment with
dnl an ACL table based on matching on conntrack original direction tuple only.
-CHECK_FTP_NAT_ORIG_TUPLE([seqadj], [10.1.1.240], [0x0a0101f0])
+CHECK_FTP_SNAT_ORIG_TUPLE([seqadj], [10.1.1.240], [0x0a0101f0])
-AT_SETUP([conntrack - IPv4 FTP Passive with NAT])
+AT_SETUP([conntrack - IPv4 FTP Passive with SNAT])
AT_SKIP_IF([test $HAVE_FTP = no])
CHECK_CONNTRACK()
CHECK_CONNTRACK_NAT()
@@ -4132,6 +4184,246 @@
OVS_TRAFFIC_VSWITCHD_STOP
AT_CLEANUP
+AT_SETUP([conntrack - IPv4 FTP Passive with DNAT])
+AT_SKIP_IF([test $HAVE_FTP = no])
+CHECK_CONNTRACK()
+CHECK_CONNTRACK_NAT()
+CHECK_CONNTRACK_ALG()
+
+OVS_TRAFFIC_VSWITCHD_START()
+
+ADD_NAMESPACES(at_ns0, at_ns1)
+
+ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24")
+NS_CHECK_EXEC([at_ns0], [ip link set dev p0 address e6:66:c1:11:11:11])
+NS_CHECK_EXEC([at_ns0], [arp -s 10.1.1.2 e6:66:c1:22:22:22])
+NS_CHECK_EXEC([at_ns0], [arp -s 10.1.1.240 e6:66:c1:22:22:22])
+
+ADD_VETH(p1, at_ns1, br0, "10.1.1.240/24")
+NS_CHECK_EXEC([at_ns1], [ip link set dev p1 address e6:66:c1:22:22:22])
+NS_CHECK_EXEC([at_ns1], [arp -s 10.1.1.1 e6:66:c1:11:11:11])
+
+dnl Allow any traffic from ns0->ns1.
+AT_DATA([flows.txt], [dnl
+dnl track all IPv4 traffic and NAT any established traffic.
+table=0 priority=10 ip, action=ct(nat,table=1)
+table=0 priority=0 action=drop
+dnl
+dnl Table 1
+dnl
+dnl Allow new FTP control connections.
+table=1 in_port=1 ct_state=+new tcp nw_src=10.1.1.1 tp_dst=21 action=ct(alg=ftp,commit,nat(dst=10.1.1.240)),2
+dnl Allow related TCP connections from port 1.
+table=1 in_port=1 ct_state=+new+rel tcp nw_src=10.1.1.1 action=ct(commit,nat),2
+dnl Allow established TCP connections both ways, post-NAT match.
+table=1 in_port=1 ct_state=+est tcp nw_dst=10.1.1.240 action=2
+table=1 in_port=2 ct_state=+est tcp nw_dst=10.1.1.1 action=1
+
+dnl Allow ICMP both ways.
+table=1 priority=100 in_port=1 icmp, action=2
+table=1 priority=100 in_port=2 icmp, action=1
+table=1 priority=0, action=drop
+])
+
+AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt])
+
+dnl Check that the stacks working to avoid races.
+OVS_WAIT_UNTIL([ip netns exec at_ns0 ping -c 1 10.1.1.240 >/dev/null])
+
+OVS_START_L7([at_ns1], [ftp])
+
+dnl FTP requests from p0->p1 should work fine.
+NS_CHECK_EXEC([at_ns0], [wget ftp://10.1.1.2 -t 3 -T 1 --retry-connrefused -v -o wget0.log])
+
+dnl Discards CLOSE_WAIT and CLOSING
+AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1.2)], [0], [dnl
+tcp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=,dport=),reply=(src=10.1.1.240,dst=10.1.1.1,sport=,dport=),protoinfo=(state=)
+tcp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=,dport=),reply=(src=10.1.1.240,dst=10.1.1.1,sport=,dport=),protoinfo=(state=),helper=ftp
+])
+
+OVS_TRAFFIC_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([conntrack - IPv4 FTP Passive with DNAT 2])
+AT_SKIP_IF([test $HAVE_FTP = no])
+CHECK_CONNTRACK()
+CHECK_CONNTRACK_NAT()
+CHECK_CONNTRACK_ALG()
+
+OVS_TRAFFIC_VSWITCHD_START()
+
+ADD_NAMESPACES(at_ns0, at_ns1)
+
+ADD_VETH(p0, at_ns0, br0, "10.1.1.1/16")
+NS_CHECK_EXEC([at_ns0], [ip link set dev p0 address e6:66:c1:11:11:11])
+NS_CHECK_EXEC([at_ns0], [arp -s 10.1.1.200 e6:66:c1:22:22:22])
+NS_CHECK_EXEC([at_ns0], [arp -s 10.1.100.1 e6:66:c1:22:22:22])
+
+ADD_VETH(p1, at_ns1, br0, "10.1.100.1/16")
+NS_CHECK_EXEC([at_ns1], [ip link set dev p1 address e6:66:c1:22:22:22])
+NS_CHECK_EXEC([at_ns1], [arp -s 10.1.1.1 e6:66:c1:11:11:11])
+
+dnl Allow any traffic from ns0->ns1.
+AT_DATA([flows.txt], [dnl
+dnl track all IPv4 traffic and NAT any established traffic.
+table=0 priority=10 ip, action=ct(nat,table=1)
+table=0 priority=0 action=drop
+dnl
+dnl Table 1
+dnl
+dnl Allow new FTP control connections.
+table=1 in_port=1 ct_state=+new tcp nw_src=10.1.1.1 tp_dst=21 action=ct(alg=ftp,commit,nat(dst=10.1.100.1)),2
+dnl Allow related TCP connections from port 1.
+table=1 in_port=1 ct_state=+new+rel tcp nw_src=10.1.1.1 action=ct(commit,nat),2
+dnl Allow established TCP connections both ways, post-NAT match.
+table=1 in_port=1 ct_state=+est tcp nw_dst=10.1.100.1 action=2
+table=1 in_port=2 ct_state=+est tcp nw_dst=10.1.1.1 action=1
+
+dnl Allow ICMP both ways.
+table=1 priority=100 in_port=1 icmp, action=2
+table=1 priority=100 in_port=2 icmp, action=1
+table=1 priority=0, action=drop
+])
+
+AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt])
+
+dnl Check that the stacks working to avoid races.
+OVS_WAIT_UNTIL([ip netns exec at_ns0 ping -c 1 10.1.100.1 >/dev/null])
+
+OVS_START_L7([at_ns1], [ftp])
+
+dnl FTP requests from p0->p1 should work fine.
+NS_CHECK_EXEC([at_ns0], [wget ftp://10.1.1.200 -t 3 -T 1 --retry-connrefused -v -o wget0.log])
+
+dnl Discards CLOSE_WAIT and CLOSING
+AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1.200)], [0], [dnl
+tcp,orig=(src=10.1.1.1,dst=10.1.1.200,sport=,dport=),reply=(src=10.1.100.1,dst=10.1.1.1,sport=,dport=),protoinfo=(state=)
+tcp,orig=(src=10.1.1.1,dst=10.1.1.200,sport=,dport=),reply=(src=10.1.100.1,dst=10.1.1.1,sport=,dport=),protoinfo=(state=),helper=ftp
+])
+
+OVS_TRAFFIC_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([conntrack - IPv4 FTP Active with DNAT])
+AT_SKIP_IF([test $HAVE_FTP = no])
+CHECK_CONNTRACK()
+CHECK_CONNTRACK_NAT()
+CHECK_CONNTRACK_ALG()
+
+OVS_TRAFFIC_VSWITCHD_START()
+
+ADD_NAMESPACES(at_ns0, at_ns1)
+
+ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24")
+NS_CHECK_EXEC([at_ns0], [ip link set dev p0 address e6:66:c1:11:11:11])
+NS_CHECK_EXEC([at_ns0], [arp -s 10.1.1.2 e6:66:c1:22:22:22])
+NS_CHECK_EXEC([at_ns0], [arp -s 10.1.1.240 e6:66:c1:22:22:22])
+
+ADD_VETH(p1, at_ns1, br0, "10.1.1.240/24")
+NS_CHECK_EXEC([at_ns1], [ip link set dev p1 address e6:66:c1:22:22:22])
+NS_CHECK_EXEC([at_ns1], [arp -s 10.1.1.1 e6:66:c1:11:11:11])
+
+dnl Allow any traffic from ns0->ns1.
+AT_DATA([flows.txt], [dnl
+dnl track all IPv4 traffic and NAT any established traffic.
+table=0 priority=10 ip, action=ct(nat,table=1)
+table=0 priority=0 action=drop
+dnl
+dnl Table 1
+dnl
+dnl Allow new FTP control connections.
+table=1 in_port=1 ct_state=+new tcp nw_src=10.1.1.1 tp_dst=21 action=ct(alg=ftp,commit,nat(dst=10.1.1.240)),2
+dnl Allow related TCP connections from port 1.
+table=1 in_port=2 ct_state=+new+rel tcp nw_src=10.1.1.240 action=ct(commit,nat),1
+dnl Allow established TCP connections both ways, post-NAT match.
+table=1 in_port=1 ct_state=+est tcp nw_dst=10.1.1.240 action=2
+table=1 in_port=2 ct_state=+est tcp nw_dst=10.1.1.1 action=1
+
+dnl Allow ICMP both ways.
+table=1 priority=100 in_port=1 icmp, action=2
+table=1 priority=100 in_port=2 icmp, action=1
+table=1 priority=0, action=drop
+])
+
+AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt])
+
+dnl Check that the stacks working to avoid races.
+OVS_WAIT_UNTIL([ip netns exec at_ns0 ping -c 1 10.1.1.240 >/dev/null])
+
+OVS_START_L7([at_ns1], [ftp])
+
+dnl FTP requests from p0->p1 should work fine.
+NS_CHECK_EXEC([at_ns0], [wget ftp://10.1.1.2 --no-passive-ftp -t 3 -T 1 --retry-connrefused -v -o wget0.log])
+
+dnl Discards CLOSE_WAIT and CLOSING
+AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1.2)], [0], [dnl
+tcp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=,dport=),reply=(src=10.1.1.240,dst=10.1.1.1,sport=,dport=),protoinfo=(state=),helper=ftp
+tcp,orig=(src=10.1.1.240,dst=10.1.1.1,sport=,dport=),reply=(src=10.1.1.1,dst=10.1.1.2,sport=,dport=),protoinfo=(state=)
+])
+
+OVS_TRAFFIC_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([conntrack - IPv4 FTP Active with DNAT with reverse skew])
+AT_SKIP_IF([test $HAVE_FTP = no])
+CHECK_CONNTRACK()
+CHECK_CONNTRACK_NAT()
+CHECK_CONNTRACK_ALG()
+
+OVS_TRAFFIC_VSWITCHD_START()
+
+ADD_NAMESPACES(at_ns0, at_ns1)
+
+ADD_VETH(p0, at_ns0, br0, "10.1.1.1/16")
+NS_CHECK_EXEC([at_ns0], [ip link set dev p0 address e6:66:c1:11:11:11])
+NS_CHECK_EXEC([at_ns0], [arp -s 10.1.1.2 e6:66:c1:22:22:22])
+NS_CHECK_EXEC([at_ns0], [arp -s 10.1.120.240 e6:66:c1:22:22:22])
+
+ADD_VETH(p1, at_ns1, br0, "10.1.1.2/16")
+NS_CHECK_EXEC([at_ns1], [ip link set dev p1 address e6:66:c1:22:22:22])
+NS_CHECK_EXEC([at_ns1], [arp -s 10.1.1.1 e6:66:c1:11:11:11])
+
+dnl Allow any traffic from ns0->ns1.
+AT_DATA([flows.txt], [dnl
+dnl track all IPv4 traffic and NAT any established traffic.
+table=0 priority=10 ip, action=ct(nat,table=1)
+table=0 priority=0 action=drop
+dnl
+dnl Table 1
+dnl
+dnl Allow new FTP control connections.
+table=1 in_port=1 ct_state=+new tcp nw_src=10.1.1.1 tp_dst=21 action=ct(alg=ftp,commit,nat(dst=10.1.1.2)),2
+dnl Allow related TCP connections from port 1.
+table=1 in_port=2 ct_state=+new+rel tcp nw_src=10.1.1.2 action=ct(commit,nat),1
+dnl Allow established TCP connections both ways, post-NAT match.
+table=1 in_port=1 ct_state=+est tcp nw_dst=10.1.1.2 action=2
+table=1 in_port=2 ct_state=+est tcp nw_dst=10.1.1.1 action=1
+
+dnl Allow ICMP both ways.
+table=1 priority=100 in_port=1 icmp, action=2
+table=1 priority=100 in_port=2 icmp, action=1
+table=1 priority=0, action=drop
+])
+
+AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt])
+
+dnl Check that the stacks working to avoid races.
+OVS_WAIT_UNTIL([ip netns exec at_ns0 ping -c 1 10.1.1.2 >/dev/null])
+
+OVS_START_L7([at_ns1], [ftp])
+
+dnl FTP requests from p0->p1 should work fine.
+NS_CHECK_EXEC([at_ns0], [wget ftp://10.1.120.240 --no-passive-ftp -t 3 -T 1 --retry-connrefused -v -o wget0.log])
+
+dnl Discards CLOSE_WAIT and CLOSING
+AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.120.240)], [0], [dnl
+tcp,orig=(src=10.1.1.1,dst=10.1.120.240,sport=,dport=),reply=(src=10.1.1.2,dst=10.1.1.1,sport=,dport=),protoinfo=(state=),helper=ftp
+tcp,orig=(src=10.1.1.2,dst=10.1.1.1,sport=,dport=),reply=(src=10.1.1.1,dst=10.1.120.240,sport=,dport=),protoinfo=(state=)
+])
+
+OVS_TRAFFIC_VSWITCHD_STOP
+AT_CLEANUP
+
AT_SETUP([conntrack - IPv6 HTTP with SNAT])
CHECK_CONNTRACK()
CHECK_CONNTRACK_NAT()
@@ -4273,7 +4565,7 @@
OVS_TRAFFIC_VSWITCHD_STOP
AT_CLEANUP
-AT_SETUP([conntrack - IPv6 FTP with NAT])
+AT_SETUP([conntrack - IPv6 FTP with SNAT])
AT_SKIP_IF([test $HAVE_FTP = no])
CHECK_CONNTRACK()
CHECK_CONNTRACK_NAT()
@@ -4333,7 +4625,7 @@
OVS_TRAFFIC_VSWITCHD_STOP
AT_CLEANUP
-AT_SETUP([conntrack - IPv6 FTP Passive with NAT])
+AT_SETUP([conntrack - IPv6 FTP Passive with SNAT])
AT_SKIP_IF([test $HAVE_FTP = no])
CHECK_CONNTRACK()
CHECK_CONNTRACK_NAT()
@@ -4394,7 +4686,7 @@
OVS_TRAFFIC_VSWITCHD_STOP
AT_CLEANUP
-AT_SETUP([conntrack - IPv6 FTP with NAT - orig tuple])
+AT_SETUP([conntrack - IPv6 FTP with SNAT - orig tuple])
AT_SKIP_IF([test $HAVE_FTP = no])
CHECK_CONNTRACK()
CHECK_CONNTRACK_NAT()
@@ -4454,7 +4746,7 @@
OVS_TRAFFIC_VSWITCHD_STOP
AT_CLEANUP
-AT_SETUP([conntrack - IPv4 TFTP with NAT])
+AT_SETUP([conntrack - IPv4 TFTP with SNAT])
AT_SKIP_IF([test $HAVE_TFTP = no])
CHECK_CONNTRACK()
CHECK_CONNTRACK_NAT()
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/system-userspace-macros.at openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/system-userspace-macros.at
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/system-userspace-macros.at 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/system-userspace-macros.at 2020-03-11 16:15:44.000000000 +0000
@@ -116,6 +116,15 @@
#
m4_define([CHECK_CONNTRACK_NAT])
+# CHECK_CT_DPIF_PER_ZONE_LIMIT()
+#
+# Perform requirements checks for running ovs-dpctl ct-[set|get|del]-limits per
+# zone. The userspace datapath does not support this feature yet.
+m4_define([CHECK_CT_DPIF_PER_ZONE_LIMIT],
+[
+ AT_SKIP_IF([:])
+])
+
# CHECK_CT_DPIF_SET_GET_MAXCONNS()
#
# Perform requirements checks for running ovs-dpctl ct-set-maxconns or
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/system-userspace-packet-type-aware.at openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/system-userspace-packet-type-aware.at
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/system-userspace-packet-type-aware.at 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/system-userspace-packet-type-aware.at 2020-03-11 16:15:44.000000000 +0000
@@ -252,39 +252,39 @@
### Verify datapath configuration
AT_CHECK([
- ovs-appctl dpif/show | grep -v hit | sed 's/\t/ /g'
+ ovs-appctl dpif/show | grep -v hit
], [0], [dnl
- br-in1:
- br-in1 65534/2: (tap)
- gre12 1020/14: (gre: remote_ip=10.0.0.2)
- gre12_l3 1021/14: (gre: packet_type=legacy_l3, remote_ip=10.0.0.2)
- gre13 1030/14: (gre: remote_ip=10.0.0.3)
- ovs-n1 10/15: (system)
- br-in2:
- br-in2 65534/3: (tap)
- gre21 2010/14: (gre: packet_type=ptap, remote_ip=20.0.0.1)
- gre23 2030/14: (gre: packet_type=ptap, remote_ip=20.0.0.3)
- ovs-n2 20/16: (system)
- br-in3:
- br-in3 65534/4: (tap)
- gre31 3010/14: (gre: remote_ip=30.0.0.1)
- gre32 3020/14: (gre: remote_ip=30.0.0.2)
- gre32_l3 3021/14: (gre: packet_type=legacy_l3, remote_ip=30.0.0.2)
- ovs-n3 30/17: (system)
- br-p1:
- br-p1 65534/5: (tap)
- p1-0 2/8: (system)
- br-p2:
- br-p2 65534/6: (tap)
- p2-0 2/9: (system)
- br-p3:
- br-p3 65534/7: (tap)
- p3-0 2/10: (system)
- br0:
- br0 65534/1: (tap)
- p0-1 10/11: (system)
- p0-2 20/12: (system)
- p0-3 30/13: (system)
+ br-in1:
+ br-in1 65534/2: (tap)
+ gre12 1020/14: (gre: remote_ip=10.0.0.2)
+ gre12_l3 1021/14: (gre: packet_type=legacy_l3, remote_ip=10.0.0.2)
+ gre13 1030/14: (gre: remote_ip=10.0.0.3)
+ ovs-n1 10/15: (system)
+ br-in2:
+ br-in2 65534/3: (tap)
+ gre21 2010/14: (gre: packet_type=ptap, remote_ip=20.0.0.1)
+ gre23 2030/14: (gre: packet_type=ptap, remote_ip=20.0.0.3)
+ ovs-n2 20/16: (system)
+ br-in3:
+ br-in3 65534/4: (tap)
+ gre31 3010/14: (gre: remote_ip=30.0.0.1)
+ gre32 3020/14: (gre: remote_ip=30.0.0.2)
+ gre32_l3 3021/14: (gre: packet_type=legacy_l3, remote_ip=30.0.0.2)
+ ovs-n3 30/17: (system)
+ br-p1:
+ br-p1 65534/5: (tap)
+ p1-0 2/8: (system)
+ br-p2:
+ br-p2 65534/6: (tap)
+ p2-0 2/9: (system)
+ br-p3:
+ br-p3 65534/7: (tap)
+ p3-0 2/10: (system)
+ br0:
+ br0 65534/1: (tap)
+ p0-1 10/11: (system)
+ p0-2 20/12: (system)
+ p0-3 30/13: (system)
])
### Test L3 forwarding flows
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/test-ovn.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/test-ovn.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/test-ovn.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/test-ovn.c 2020-03-11 16:15:44.000000000 +0000
@@ -182,6 +182,7 @@
dhcp_opt_add(dhcp_opts, "tcp_ttl", 37, "uint8");
dhcp_opt_add(dhcp_opts, "mtu", 26, "uint16");
dhcp_opt_add(dhcp_opts, "lease_time", 51, "uint32");
+ dhcp_opt_add(dhcp_opts, "wpad", 252, "str");
/* DHCPv6 options. */
hmap_init(dhcpv6_opts);
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/test-stream.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/test-stream.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/test-stream.c 1970-01-01 00:00:00.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/test-stream.c 2020-03-11 16:15:44.000000000 +0000
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2018 Ilya Maximets
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include
+
+#include "fatal-signal.h"
+#include "openvswitch/vlog.h"
+#include "stream.h"
+#include "util.h"
+
+VLOG_DEFINE_THIS_MODULE(test_stream);
+
+int
+main(int argc, char *argv[])
+{
+ int error;
+ struct stream *stream;
+
+ fatal_ignore_sigpipe();
+ set_program_name(argv[0]);
+
+ if (argc < 2) {
+ ovs_fatal(0, "usage: %s REMOTE", argv[0]);
+ }
+
+ error = stream_open_block(stream_open(argv[1], &stream, DSCP_DEFAULT),
+ &stream);
+ if (error) {
+ VLOG_ERR("stream_open_block(%s) failure: %s",
+ argv[1], ovs_strerror(error));
+ }
+ return (error || !stream) ? 1 : 0;
+}
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/tunnel.at openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/tunnel.at
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/tests/tunnel.at 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/tests/tunnel.at 2020-03-11 16:15:44.000000000 +0000
@@ -394,6 +394,68 @@
OVS_VSWITCHD_STOP
AT_CLEANUP
+AT_SETUP([tunnel - table version])
+dnl check if changes in the egress bridge flow table affects
+dnl discovering the link layer address of tunnel endpoints.
+OVS_VSWITCHD_START([add-port br0 p0 -- set Interface p0 type=dummy ofport_request=1 other-config:hwaddr=aa:55:aa:55:00:00])
+AT_CHECK([ovs-vsctl add-br int-br -- set bridge int-br datapath_type=dummy], [0])
+AT_CHECK([ovs-vsctl add-port int-br v1 -- set Interface v1 type=vxlan \
+ options:remote_ip=172.31.1.2 options:key=123 \
+ ofport_request=2 \
+ -- add-port int-br v2 -- set Interface v2 type=internal \
+ ofport_request=3 \
+ ], [0])
+
+AT_CHECK([ovs-appctl dpif/show], [0], [dnl
+dummy@ovs-dummy: hit:0 missed:0
+ br0:
+ br0 65534/100: (dummy-internal)
+ p0 1/1: (dummy)
+ int-br:
+ int-br 65534/2: (dummy-internal)
+ v1 2/4789: (vxlan: key=123, remote_ip=172.31.1.2)
+ v2 3/3: (dummy-internal)
+])
+
+dnl First setup dummy interface IP address, then add the route
+dnl so that tnl-port table can get valid IP address for the device.
+AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 172.31.1.1/24], [0], [OK
+])
+AT_CHECK([ovs-appctl ovs/route/add 172.31.1.0/24 br0], [0], [OK
+])
+
+dnl change the flow table to bump the internal table version
+AT_CHECK([ovs-ofctl add-flow int-br action=normal])
+AT_CHECK([ovs-ofctl add-flow br0 action=normal])
+AT_CHECK([ovs-ofctl del-flows br0])
+AT_CHECK([ovs-ofctl add-flow br0 action=normal])
+AT_CHECK([ovs-ofctl del-flows br0])
+AT_CHECK([ovs-ofctl add-flow br0 action=normal])
+AT_CHECK([ovs-ofctl del-flows br0])
+AT_CHECK([ovs-ofctl add-flow br0 action=normal])
+AT_CHECK([ovs-ofctl del-flows br0])
+AT_CHECK([ovs-ofctl add-flow br0 action=normal])
+AT_CHECK([ovs-ofctl del-flows br0])
+AT_CHECK([ovs-ofctl add-flow br0 action=normal])
+AT_CHECK([ovs-ofctl del-flows br0])
+AT_CHECK([ovs-ofctl add-flow br0 action=normal])
+AT_CHECK([ovs-ofctl del-flows br0])
+AT_CHECK([ovs-ofctl add-flow br0 action=normal])
+
+dnl Check Neighbour discovery.
+AT_CHECK([ovs-vsctl -- set Interface p0 options:pcap=p0.pcap])
+
+AT_CHECK([ovs-appctl netdev-dummy/receive int-br 'in_port(2),eth(src=aa:55:aa:55:00:00,dst=f8:bc:12:ff:ff:ff),eth_type(0x0800),ipv4(src=1.1.3.92,dst=1.1.3.88,proto=1,tos=0,ttl=64,frag=no),icmp(type=0,code=0)'])
+AT_CHECK([ovs-pcap p0.pcap > p0.pcap.txt 2>&1])
+
+dnl When the wrong version is used, the flow is not visible and the
+dnl packet is dropped.
+AT_CHECK([cat p0.pcap.txt | grep ffffffffffffaa55aa55000008060001080006040001aa55aa550000ac1f0101000000000000ac1f0102 | uniq], [0], [dnl
+ffffffffffffaa55aa55000008060001080006040001aa55aa550000ac1f0101000000000000ac1f0102
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
AT_SETUP([tunnel - LISP])
OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=lisp \
options:remote_ip=1.1.1.1 ofport_request=1])
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/.travis/linux-build.sh openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/.travis/linux-build.sh
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/.travis/linux-build.sh 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/.travis/linux-build.sh 2020-03-11 16:15:44.000000000 +0000
@@ -83,7 +83,7 @@
if [ "$DPDK" ]; then
if [ -z "$DPDK_VER" ]; then
- DPDK_VER="17.11.3"
+ DPDK_VER="17.11.6"
fi
install_dpdk $DPDK_VER
if [ "$CC" = "clang" ]; then
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/.travis/linux-prepare.sh openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/.travis/linux-prepare.sh
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/.travis/linux-prepare.sh 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/.travis/linux-prepare.sh 2020-03-11 16:15:44.000000000 +0000
@@ -2,6 +2,10 @@
set -ev
+# Logging to syslog could be way too slow on Travis.
+# Stopping the rsyslog daemon to allow tests to fit the time limit.
+sudo service rsyslog stop
+
# Build and install sparse.
#
# Explicitly disable sparse support for llvm because some travis
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/.travis.yml openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/.travis.yml
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/.travis.yml 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/.travis.yml 2020-03-11 16:15:44.000000000 +0000
@@ -26,8 +26,6 @@
before_script: export PATH=$PATH:$HOME/bin
-sudo: false
-
env:
- OPTS="--disable-ssl"
- TESTSUITE=1 KERNEL=3.16.54
@@ -36,8 +34,8 @@
- KERNEL=3.16.54 DPDK=1
- KERNEL=3.16.54 DPDK=1 OPTS="--enable-shared"
- KERNEL=4.15.18
- - KERNEL=4.14.63
- - KERNEL=4.9.120
+ - KERNEL=4.14.111
+ - KERNEL=4.9.149
- KERNEL=4.4.148
- KERNEL=3.16.57
- TESTSUITE=1 LIBS=-ljemalloc
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/utilities/ovs-ctl.in openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/utilities/ovs-ctl.in
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/utilities/ovs-ctl.in 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/utilities/ovs-ctl.in 2020-03-11 16:15:44.000000000 +0000
@@ -164,16 +164,14 @@
}
add_managers () {
- # Now that ovs-vswitchd has started and completed its initial
- # configuration, tell ovsdb-server to connect to the remote managers. We
- # used to do this at ovsdb-server startup time, but waiting for
- # ovs-vswitchd to finish configuring means that remote managers see less
- # churn in the database at startup or restart. (For example, managers
- # won't briefly see empty datapath-id or ofport columns for records that
- # exist at startup.)
+ # Tell ovsdb-server to connect to the remote managers. If ovs-vswitchd
+ # is not finished configuring, it may mean that remote managers will
+ # see more churn in the database at startup or restart. (For example,
+ # managers may briefly see empty datapath-id or ofport columns for
+ # records that exist at startup.). However, the alternative is a
+ # 'bricked' system, so we allow database connectivity regardless.
if test X"$OVSDB_SERVER" = Xyes || test X"$OVS_VSWITCHD" = Xyes; then
- if daemon_is_running ovsdb-server \
- && daemon_is_running ovs-vswitchd; then
+ if daemon_is_running ovsdb-server; then
action "Enabling remote OVSDB managers" \
ovs-appctl -t ovsdb-server ovsdb-server/add-remote \
db:Open_vSwitch,Open_vSwitch,manager_options
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/utilities/ovs-lib.in openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/utilities/ovs-lib.in
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/utilities/ovs-lib.in 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/utilities/ovs-lib.in 2020-03-11 16:15:44.000000000 +0000
@@ -127,7 +127,7 @@
pid_exists () {
# This is better than "kill -0" because it doesn't require permission to
# send a signal (so daemon_status in particular works as non-root).
- test -d /proc/"$1"
+ test -n "$1" && test -d /proc/"$1"
}
pid_comm_check () {
@@ -477,6 +477,7 @@
elif ovsdb_tool db-is-standalone "$DB_FILE"; then
# Convert standalone database to clustered.
backup_db || return 1
+ rm -f "$DB_FILE"
action "Creating cluster database $DB_FILE from existing one" \
ovsdb_tool create-cluster "$DB_FILE" "$backup" "$LOCAL_ADDR"
fi
@@ -608,9 +609,6 @@
stop_ovsdb
start_ovsdb || return 1
- if [ -n "$(ovs-dpctl show)" ]; then
- action "Flush old conntrack entries" ovs-appctl dpctl/flush-conntrack
- fi
stop_forwarding
if action "Saving interface configuration" save_interfaces; then
@@ -627,6 +625,14 @@
action "Removing datapath: $dp" ovs-dpctl del-dp "$dp"
done
+ if test -e /sys/module/ip_gre; then
+ action "Forcing removal of ip_gre module" rmmod ip_gre
+ fi
+
+ if test -e /sys/module/gre; then
+ action "Forcing removal of gre module" rmmod gre
+ fi
+
ovs_kmod_ctl remove
# Start vswitchd by asking it to wait till flow restore is finished.
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/utilities/ovs-ofctl.c openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/utilities/ovs-ofctl.c
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/utilities/ovs-ofctl.c 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/utilities/ovs-ofctl.c 2020-03-11 16:15:44.000000000 +0000
@@ -2958,7 +2958,8 @@
for (i = 0; i < n_gms; i++) {
struct ofputil_group_mod *gm = &gms[i];
- struct ofpbuf *request = ofputil_encode_group_mod(version, gm);
+ struct ofpbuf *request = ofputil_encode_group_mod(version, gm,
+ NULL, -1);
ovs_list_push_back(&requests, &request->list_node);
ofputil_uninit_group_mod(gm);
@@ -2991,7 +2992,7 @@
for (i = 0; i < n_gms; i++) {
gm = &gms[i];
- request = ofputil_encode_group_mod(version, gm);
+ request = ofputil_encode_group_mod(version, gm, NULL, -1);
transact_noreply(vconn, request);
ofputil_uninit_group_mod(gm);
}
@@ -4474,6 +4475,7 @@
} else if (retval) {
error = retval;
ovs_error(error, "%s: read failed", filename);
+ break;
}
pkt_metadata_init(&packet->md, u32_to_odp(ofp_to_u16(OFPP_ANY)));
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/utilities/ovs-save openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/utilities/ovs-save
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/utilities/ovs-save 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/utilities/ovs-save 2020-03-11 16:15:44.000000000 +0000
@@ -110,6 +110,17 @@
exit 1
fi
+ # OVS 2.7 and earlier do not enable OpenFlow 1.4 (by default) and lack
+ # other features needed to save and restore flows. Don't try.
+ case `ovs-appctl version | sed 1q` in
+ "ovs-vswitchd (Open vSwitch) 1."*.*)
+ return
+ ;;
+ "ovs-vswitchd (Open vSwitch) 2."[0-7].*)
+ return
+ ;;
+ esac
+
workdir=$(mktemp -d "${TMPDIR:-/tmp}/ovs-save.XXXXXXXXXX")
for bridge in "$@"; do
# Get the highest enabled OpenFlow version
@@ -117,15 +128,23 @@
printf "%s" "ovs-ofctl add-tlv-map ${bridge} '"
ovs-ofctl dump-tlv-map ${bridge} | \
- awk '/^ 0x/ {if (cnt != 0) printf ","; \
+ awk '/^ *0x/ {if (cnt != 0) printf ","; \
cnt++;printf "{class="$1",type="$2",len="$3"}->"$4}'
echo "'"
- printf "%s" "ovs-ofctl -O $ofp_version add-flows ${bridge} " \
- "\"$workdir/$bridge.flows.dump\""
+ # If possible use OpenFlow 1.4 atomic bundle txn for flows and groups
+ [ ${ofp_version#OpenFlow} -ge 14 ] && bundle=" --bundle" || bundle=""
+
+ echo "ovs-ofctl -O $ofp_version add-groups ${bridge} \
+ \"$workdir/$bridge.groups.dump\" ${bundle}"
+
+ echo "ovs-ofctl -O $ofp_version replace-flows ${bridge} \
+ \"$workdir/$bridge.flows.dump\" ${bundle}"
- # If possible, use OpenFlow 1.4 atomic bundle transaction to add flows
- [ ${ofp_version#OpenFlow} -ge 14 ] && echo " --bundle" || echo
+ ovs-ofctl -O $ofp_version dump-groups "$bridge" | \
+ sed -e '/^OFPST_GROUP_DESC/d' \
+ -e '/^NXST_GROUP_DESC/d' > \
+ "$workdir/$bridge.groups.dump"
ovs-ofctl -O $ofp_version dump-flows --no-names --no-stats "$bridge" | \
sed -e '/NXST_FLOW/d' \
diff -Nru openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/Vagrantfile openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/Vagrantfile
--- openvswitch-2.10.0+2018.08.28+git.8ca7c82b7d+ds1/Vagrantfile 2018-09-01 17:30:24.000000000 +0000
+++ openvswitch-2.10.4+2020.01.14.b2ccc307f1+dfsg1/Vagrantfile 2020-03-11 16:15:44.000000000 +0000
@@ -12,7 +12,8 @@
python-twisted python-zope-interface \
desktop-file-utils groff graphviz rpmdevtools nc curl \
wget python-six pyftpdlib checkpolicy selinux-policy-devel \
- libcap-ng-devel kernel-devel-`uname -r` ethtool python-tftpy
+ libcap-ng-devel kernel-devel-`uname -r` ethtool python-tftpy \
+ lftp
echo "search extra update built-in" >/etc/depmod.d/search_path.conf
SCRIPT
@@ -28,7 +29,8 @@
wget python-six ethtool \
libcap-ng-dev libssl-dev python-dev openssl \
python-pyftpdlib python-flake8 python-tftpy \
- linux-headers-`uname -r`
+ linux-headers-`uname -r` \
+ lftp
SCRIPT
$bootstrap_centos = <