diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml
index fc75581486..6f5139304a 100644
--- a/.github/workflows/build-and-test.yml
+++ b/.github/workflows/build-and-test.yml
@@ -238,6 +238,14 @@ jobs:
if: matrix.m32 != ''
run: sudo apt install -y gcc-multilib
+ - name: Reduce ASLR entropy
+ if: matrix.sanitizers != ''
+ # Asan in llvm 14 provided in ubuntu-22.04 is incompatible with
+ # high-entropy ASLR configured in much newer kernels that GitHub
+ # runners are using leading to random crashes:
+ # https://github.com/actions/runner-images/issues/9491
+ run: sudo sysctl -w vm.mmap_rnd_bits=28
+
- name: prepare
run: ./.ci/linux-prepare.sh
diff --git a/AUTHORS.rst b/AUTHORS.rst
index aa9284fb16..80678854bd 100644
--- a/AUTHORS.rst
+++ b/AUTHORS.rst
@@ -588,6 +588,7 @@ David Evans davidjoshuaevans@gmail.com
David Palma palma@onesource.pt
David van Moolenbroek dvmoolenbroek@aimvalley.nl
Derek Cormier derek.cormier@lab.ntt.co.jp
+Derrick Lim derrick.lim@rakuten.com
Dhaval Badiani dbadiani@vmware.com
DK Moon
Ding Zhi zhi.ding@6wind.com
diff --git a/Documentation/intro/install/windows.rst b/Documentation/intro/install/windows.rst
index fce099d5dc..efdb8aebce 100644
--- a/Documentation/intro/install/windows.rst
+++ b/Documentation/intro/install/windows.rst
@@ -112,7 +112,7 @@ The following explains the steps in some detail.
`OpenSSL for Windows <https://wiki.openssl.org/index.php/Binaries>`__
Note down the directory where OpenSSL is installed (e.g.:
- ``C:/OpenSSL-Win32``) for later use.
+ ``C:/OpenSSL-Win64``) for later use.
.. note::
@@ -182,7 +182,7 @@ To configure with SSL support, add the requisite additional options:
--localstatedir="C:/openvswitch/var"
--sysconfdir="C:/openvswitch/etc" \
--with-pthread="C:/pthread" \
- --enable-ssl --with-openssl="C:/OpenSSL-Win32"
+ --enable-ssl --with-openssl="C:/OpenSSL-Win64"
Finally, to the kernel module also:
@@ -194,7 +194,7 @@ Finally, to the kernel module also:
--localstatedir="C:/openvswitch/var" \
--sysconfdir="C:/openvswitch/etc" \
--with-pthread="C:/pthread" \
- --enable-ssl --with-openssl="C:/OpenSSL-Win32" \
+ --enable-ssl --with-openssl="C:/OpenSSL-Win64" \
--with-vstudiotarget="<target type>" \
--with-vstudiotargetver="<target versions>"
diff --git a/NEWS b/NEWS
index 8888fb3ec5..4bfb341cf4 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,6 @@
+v3.3.1 - xx xxx xxxx
+--------------------
+
v3.3.0 - 16 Feb 2024
--------------------
- OVSDB:
diff --git a/configure.ac b/configure.ac
index 05afbb9cc8..a3ea65c0fa 100644
--- a/configure.ac
+++ b/configure.ac
@@ -13,7 +13,7 @@
# limitations under the License.
AC_PREREQ(2.63)
-AC_INIT(openvswitch, 3.3.0, bugs@openvswitch.org)
+AC_INIT(openvswitch, 3.3.1, bugs@openvswitch.org)
AC_CONFIG_SRCDIR([vswitchd/ovs-vswitchd.c])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_AUX_DIR([build-aux])
diff --git a/debian/changelog b/debian/changelog
index 2049ddaa26..22c767a4ce 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+openvswitch (3.3.1-1) unstable; urgency=low
+ [ Open vSwitch team ]
+ * New upstream version
+
+ -- Open vSwitch team <dev@openvswitch.org> Fri, 16 Feb 2024 12:25:58 +0100
+
openvswitch (3.3.0-1) unstable; urgency=low
* New upstream version
diff --git a/lib/bfd.c b/lib/bfd.c
index 9af258917b..b8149e7897 100644
--- a/lib/bfd.c
+++ b/lib/bfd.c
@@ -1130,10 +1130,11 @@ bfd_set_state(struct bfd *bfd, enum state state, enum diag diag)
if (!VLOG_DROP_INFO(&rl)) {
struct ds ds = DS_EMPTY_INITIALIZER;
- ds_put_format(&ds, "%s: BFD state change: %s->%s"
- " \"%s\"->\"%s\".\n",
+ ds_put_format(&ds, "%s: BFD state change: (bfd.SessionState: %s,"
+ " bfd.LocalDiag: \"%s\") -> (bfd.SessionState: %s,"
+ " bfd.LocalDiag: \"%s\")\n",
bfd->name, bfd_state_str(bfd->state),
- bfd_state_str(state), bfd_diag_str(bfd->diag),
+ bfd_diag_str(bfd->diag), bfd_state_str(state),
bfd_diag_str(diag));
bfd_put_details(&ds, bfd);
VLOG_INFO("%s", ds_cstr(&ds));
diff --git a/lib/conntrack.c b/lib/conntrack.c
index 013709bd62..6d02eaba8b 100644
--- a/lib/conntrack.c
+++ b/lib/conntrack.c
@@ -2637,25 +2637,19 @@ conntrack_dump_start(struct conntrack *ct, struct conntrack_dump *dump,
dump->ct = ct;
*ptot_bkts = 1; /* Need to clean up the callers. */
+ dump->cursor = cmap_cursor_start(&ct->conns);
return 0;
}
int
conntrack_dump_next(struct conntrack_dump *dump, struct ct_dpif_entry *entry)
{
- struct conntrack *ct = dump->ct;
long long now = time_msec();
- for (;;) {
- struct cmap_node *cm_node = cmap_next_position(&ct->conns,
- &dump->cm_pos);
- if (!cm_node) {
- break;
- }
- struct conn_key_node *keyn;
- struct conn *conn;
+ struct conn_key_node *keyn;
+ struct conn *conn;
- INIT_CONTAINER(keyn, cm_node, cm_node);
+ CMAP_CURSOR_FOR_EACH_CONTINUE (keyn, cm_node, &dump->cursor) {
if (keyn->dir != CT_DIR_FWD) {
continue;
}
diff --git a/lib/conntrack.h b/lib/conntrack.h
index 0a888be455..6339701627 100644
--- a/lib/conntrack.h
+++ b/lib/conntrack.h
@@ -101,8 +101,8 @@ struct conntrack_dump {
struct conntrack *ct;
unsigned bucket;
union {
- struct cmap_position cm_pos;
struct hmap_position hmap_pos;
+ struct cmap_cursor cursor;
};
bool filter_zone;
uint16_t zone;
diff --git a/lib/dp-packet.c b/lib/dp-packet.c
index 305822293b..df7bf8e6b3 100644
--- a/lib/dp-packet.c
+++ b/lib/dp-packet.c
@@ -592,6 +592,18 @@ dp_packet_ol_send_prepare(struct dp_packet *p, uint64_t flags)
if (dp_packet_hwol_is_tunnel_geneve(p) ||
dp_packet_hwol_is_tunnel_vxlan(p)) {
tnl_inner = true;
+
+ /* If the TX interface doesn't support UDP tunnel offload but does
+ * support inner checksum offload and an outer UDP checksum is
+ * required, then we can't offload inner checksum either. As that would
+ * invalidate the outer checksum. */
+ if (!(flags & NETDEV_TX_OFFLOAD_OUTER_UDP_CKSUM) &&
+ dp_packet_hwol_is_outer_udp_cksum(p)) {
+ flags &= ~(NETDEV_TX_OFFLOAD_TCP_CKSUM |
+ NETDEV_TX_OFFLOAD_UDP_CKSUM |
+ NETDEV_TX_OFFLOAD_SCTP_CKSUM |
+ NETDEV_TX_OFFLOAD_IPV4_CKSUM);
+ }
}
if (dp_packet_hwol_tx_ip_csum(p)) {
diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c
index 45f61930d4..8c52accff9 100644
--- a/lib/netdev-dpdk.c
+++ b/lib/netdev-dpdk.c
@@ -607,6 +607,9 @@ int netdev_dpdk_get_vid(const struct netdev_dpdk *dev);
struct ingress_policer *
netdev_dpdk_get_ingress_policer(const struct netdev_dpdk *dev);
+static void netdev_dpdk_mbuf_dump(const char *prefix, const char *message,
+ const struct rte_mbuf *);
+
static bool
is_dpdk_class(const struct netdev_class *class)
{
@@ -2569,9 +2572,29 @@ netdev_dpdk_prep_hwol_packet(struct netdev_dpdk *dev, struct rte_mbuf *mbuf)
struct dp_packet *pkt = CONTAINER_OF(mbuf, struct dp_packet, mbuf);
struct tcp_header *th;
- if (!(mbuf->ol_flags & (RTE_MBUF_F_TX_IP_CKSUM | RTE_MBUF_F_TX_L4_MASK
- | RTE_MBUF_F_TX_TCP_SEG))) {
- mbuf->ol_flags &= ~(RTE_MBUF_F_TX_IPV4 | RTE_MBUF_F_TX_IPV6);
+ const uint64_t all_requests = (RTE_MBUF_F_TX_IP_CKSUM |
+ RTE_MBUF_F_TX_L4_MASK |
+ RTE_MBUF_F_TX_OUTER_IP_CKSUM |
+ RTE_MBUF_F_TX_OUTER_UDP_CKSUM |
+ RTE_MBUF_F_TX_TCP_SEG);
+ const uint64_t all_marks = (RTE_MBUF_F_TX_IPV4 |
+ RTE_MBUF_F_TX_IPV6 |
+ RTE_MBUF_F_TX_OUTER_IPV4 |
+ RTE_MBUF_F_TX_OUTER_IPV6 |
+ RTE_MBUF_F_TX_TUNNEL_MASK);
+
+ if (!(mbuf->ol_flags & all_requests)) {
+ /* No offloads requested, no marks should be set. */
+ mbuf->ol_flags &= ~all_marks;
+
+ uint64_t unexpected = mbuf->ol_flags & RTE_MBUF_F_TX_OFFLOAD_MASK;
+ if (OVS_UNLIKELY(unexpected)) {
+ VLOG_WARN_RL(&rl, "%s: Unexpected Tx offload flags: %#"PRIx64,
+ netdev_get_name(&dev->up), unexpected);
+ netdev_dpdk_mbuf_dump(netdev_get_name(&dev->up),
+ "Packet with unexpected ol_flags", mbuf);
+ return false;
+ }
return true;
}
@@ -2664,6 +2687,35 @@ netdev_dpdk_prep_hwol_batch(struct netdev_dpdk *dev, struct rte_mbuf **pkts,
return cnt;
}
+static void
+netdev_dpdk_mbuf_dump(const char *prefix, const char *message,
+ const struct rte_mbuf *mbuf)
+{
+ static struct vlog_rate_limit dump_rl = VLOG_RATE_LIMIT_INIT(5, 5);
+ char *response = NULL;
+ FILE *stream;
+ size_t size;
+
+ if (VLOG_DROP_DBG(&dump_rl)) {
+ return;
+ }
+
+ stream = open_memstream(&response, &size);
+ if (!stream) {
+ VLOG_ERR("Unable to open memstream for mbuf dump: %s.",
+ ovs_strerror(errno));
+ return;
+ }
+
+ rte_pktmbuf_dump(stream, mbuf, rte_pktmbuf_pkt_len(mbuf));
+
+ fclose(stream);
+
+ VLOG_DBG(prefix ? "%s: %s:\n%s" : "%s%s:\n%s",
+ prefix ? prefix : "", message, response);
+ free(response);
+}
+
/* Tries to transmit 'pkts' to txq 'qid' of device 'dev'. Takes ownership of
* 'pkts', even in case of failure.
*
@@ -2680,6 +2732,8 @@ netdev_dpdk_eth_tx_burst(struct netdev_dpdk *dev, int qid,
VLOG_WARN_RL(&rl, "%s: Output batch contains invalid packets. "
"Only %u/%u are valid: %s", netdev_get_name(&dev->up),
nb_tx_prep, cnt, rte_strerror(rte_errno));
+ netdev_dpdk_mbuf_dump(netdev_get_name(&dev->up),
+ "First invalid packet", pkts[nb_tx_prep]);
}
while (nb_tx != nb_tx_prep) {
diff --git a/lib/netdev-dummy.c b/lib/netdev-dummy.c
index cd7e85a818..e8bbf8d514 100644
--- a/lib/netdev-dummy.c
+++ b/lib/netdev-dummy.c
@@ -39,6 +39,7 @@
#include "pcap-file.h"
#include "openvswitch/poll-loop.h"
#include "openvswitch/shash.h"
+#include "ovs-router.h"
#include "sset.h"
#include "stream.h"
#include "unaligned.h"
@@ -2084,11 +2085,20 @@ netdev_dummy_ip4addr(struct unixctl_conn *conn, int argc OVS_UNUSED,
if (netdev && is_dummy_class(netdev->netdev_class)) {
struct in_addr ip, mask;
+ struct in6_addr ip6;
+ uint32_t plen;
char *error;
- error = ip_parse_masked(argv[2], &ip.s_addr, &mask.s_addr);
+ error = ip_parse_cidr(argv[2], &ip.s_addr, &plen);
if (!error) {
+ mask.s_addr = be32_prefix_mask(plen);
netdev_dummy_add_in4(netdev, ip, mask);
+
+ /* Insert local route entry for the new address. */
+ in6_addr_set_mapped_ipv4(&ip6, ip.s_addr);
+ ovs_router_force_insert(0, &ip6, plen + 96, true, argv[1],
+ &in6addr_any, &ip6);
+
unixctl_command_reply(conn, "OK");
} else {
unixctl_command_reply_error(conn, error);
@@ -2118,6 +2128,11 @@ netdev_dummy_ip6addr(struct unixctl_conn *conn, int argc OVS_UNUSED,
mask = ipv6_create_mask(plen);
netdev_dummy_add_in6(netdev, &ip6, &mask);
+
+ /* Insert local route entry for the new address. */
+ ovs_router_force_insert(0, &ip6, plen, true, argv[1],
+ &in6addr_any, &ip6);
+
unixctl_command_reply(conn, "OK");
} else {
unixctl_command_reply_error(conn, error);
diff --git a/lib/ovs-router.c b/lib/ovs-router.c
index ca014d80ed..3d84c9a30a 100644
--- a/lib/ovs-router.c
+++ b/lib/ovs-router.c
@@ -330,6 +330,20 @@ ovs_router_insert(uint32_t mark, const struct in6_addr *ip_dst, uint8_t plen,
}
}
+/* The same as 'ovs_router_insert', but it adds the route even if updates
+ * from the system routing table are disabled. Used for unit tests. */
+void
+ovs_router_force_insert(uint32_t mark, const struct in6_addr *ip_dst,
+ uint8_t plen, bool local, const char output_bridge[],
+ const struct in6_addr *gw,
+ const struct in6_addr *prefsrc)
+{
+ uint8_t priority = local ? plen + 64 : plen;
+
+ ovs_router_insert__(mark, priority, local, ip_dst, plen,
+ output_bridge, gw, prefsrc);
+}
+
static void
rt_entry_delete__(const struct cls_rule *cr)
{
diff --git a/lib/ovs-router.h b/lib/ovs-router.h
index eb4ff85d9e..d7dc7e55f3 100644
--- a/lib/ovs-router.h
+++ b/lib/ovs-router.h
@@ -34,6 +34,11 @@ void ovs_router_insert(uint32_t mark, const struct in6_addr *ip_dst,
uint8_t plen, bool local,
const char output_bridge[], const struct in6_addr *gw,
const struct in6_addr *prefsrc);
+void ovs_router_force_insert(uint32_t mark, const struct in6_addr *ip_dst,
+ uint8_t plen, bool local,
+ const char output_bridge[],
+ const struct in6_addr *gw,
+ const struct in6_addr *prefsrc);
void ovs_router_flush(void);
void ovs_router_disable_system_routing_table(void);
diff --git a/m4/ax_check_openssl.m4 b/m4/ax_check_openssl.m4
index 281d4dc65e..faa5babde2 100644
--- a/m4/ax_check_openssl.m4
+++ b/m4/ax_check_openssl.m4
@@ -81,7 +81,8 @@ AC_DEFUN([AX_CHECK_OPENSSL], [
SSL_INCLUDES="-I$ssldir/include"
SSL_LDFLAGS="-L$ssldir/lib"
if test "$WIN32" = "yes"; then
- SSL_LIBS="-lssleay32 -llibeay32"
+ SSL_LDFLAGS="$SSL_LDFLAGS -L$ssldir/lib/VC/x64/MT"
+ SSL_LIBS="-llibssl -llibcrypto"
SSL_DIR=/$(echo ${ssldir} | ${SED} -e 's/://')
else
SSL_LIBS="-lssl -lcrypto"
diff --git a/ofproto/bond.c b/ofproto/bond.c
index cfdf44f854..c31869a4c7 100644
--- a/ofproto/bond.c
+++ b/ofproto/bond.c
@@ -186,7 +186,7 @@ static struct bond_member *choose_output_member(const struct bond *,
struct flow_wildcards *,
uint16_t vlan)
OVS_REQ_RDLOCK(rwlock);
-static void update_recirc_rules__(struct bond *);
+static void update_recirc_rules(struct bond *) OVS_REQ_WRLOCK(rwlock);
static bool bond_may_recirc(const struct bond *);
static void bond_update_post_recirc_rules__(struct bond *, bool force)
OVS_REQ_WRLOCK(rwlock);
@@ -299,7 +299,10 @@ bond_unref(struct bond *bond)
}
free(bond->hash);
bond->hash = NULL;
- update_recirc_rules__(bond);
+
+ ovs_rwlock_wrlock(&rwlock);
+ update_recirc_rules(bond);
+ ovs_rwlock_unlock(&rwlock);
hmap_destroy(&bond->pr_rule_ops);
free(bond->primary);
@@ -331,17 +334,8 @@ add_pr_rule(struct bond *bond, const struct match *match,
hmap_insert(&bond->pr_rule_ops, &pr_op->hmap_node, hash);
}
-/* This function should almost never be called directly.
- * 'update_recirc_rules()' should be called instead. Since
- * this function modifies 'bond->pr_rule_ops', it is only
- * safe when 'rwlock' is held.
- *
- * However, when the 'bond' is the only reference in the system,
- * calling this function avoid acquiring lock only to satisfy
- * lock annotation. Currently, only 'bond_unref()' calls
- * this function directly. */
static void
-update_recirc_rules__(struct bond *bond)
+update_recirc_rules(struct bond *bond) OVS_REQ_WRLOCK(rwlock)
{
struct match match;
struct bond_pr_rule_op *pr_op;
@@ -407,6 +401,15 @@ update_recirc_rules__(struct bond *bond)
VLOG_ERR("failed to remove post recirculation flow %s", err_s);
free(err_s);
+ } else if (bond->hash) {
+ /* If the flow deletion failed, a subsequent call to
+ * ofproto_dpif_add_internal_flow() would just modify the
+ * flow preserving its statistics. Therefore, only reset
+ * the entry's byte counter if it succeeds. */
+ uint32_t hash = pr_op->match.flow.dp_hash & BOND_MASK;
+ struct bond_entry *entry = &bond->hash[hash];
+
+ entry->pr_tx_bytes = 0;
}
hmap_remove(&bond->pr_rule_ops, &pr_op->hmap_node);
@@ -421,12 +424,6 @@ update_recirc_rules__(struct bond *bond)
ofpbuf_uninit(&ofpacts);
}
-static void
-update_recirc_rules(struct bond *bond)
- OVS_REQ_RDLOCK(rwlock)
-{
- update_recirc_rules__(bond);
-}
/* Updates 'bond''s overall configuration to 's'.
*
diff --git a/ofproto/ofproto-dpif-trace.c b/ofproto/ofproto-dpif-trace.c
index b86e7fe07e..87506aa785 100644
--- a/ofproto/ofproto-dpif-trace.c
+++ b/ofproto/ofproto-dpif-trace.c
@@ -845,17 +845,35 @@ ofproto_trace(struct ofproto_dpif *ofproto, const struct flow *flow,
bool names)
{
struct ovs_list recirc_queue = OVS_LIST_INITIALIZER(&recirc_queue);
+ int recirculations = 0;
+
ofproto_trace__(ofproto, flow, packet, &recirc_queue,
ofpacts, ofpacts_len, output, names);
struct oftrace_recirc_node *recirc_node;
LIST_FOR_EACH_POP (recirc_node, node, &recirc_queue) {
+ if (recirculations++ > 4096) {
+ ds_put_cstr(output, "\n\n");
+ ds_put_char_multiple(output, '=', 79);
+ ds_put_cstr(output, "\nTrace reached the recirculation limit."
+ " Sopping the trace here.");
+ ds_put_format(output,
+ "\nQueued but not processed: %"PRIuSIZE
+ " recirculations.",
+ ovs_list_size(&recirc_queue) + 1);
+ oftrace_recirc_node_destroy(recirc_node);
+ break;
+ }
ofproto_trace_recirc_node(recirc_node, next_ct_states, output);
ofproto_trace__(ofproto, &recirc_node->flow, recirc_node->packet,
&recirc_queue, ofpacts, ofpacts_len, output,
names);
oftrace_recirc_node_destroy(recirc_node);
}
+ /* Destroy remaining recirculation nodes, if any. */
+ LIST_FOR_EACH_POP (recirc_node, node, &recirc_queue) {
+ oftrace_recirc_node_destroy(recirc_node);
+ }
}
void
diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
index 1cf4d5f7c9..89f183182e 100644
--- a/ofproto/ofproto-dpif-xlate.c
+++ b/ofproto/ofproto-dpif-xlate.c
@@ -3815,6 +3815,8 @@ native_tunnel_output(struct xlate_ctx *ctx, const struct xport *xport,
if (flow->tunnel.ip_src) {
in6_addr_set_mapped_ipv4(&s_ip6, flow->tunnel.ip_src);
+ } else if (ipv6_addr_is_set(&flow->tunnel.ipv6_src)) {
+ s_ip6 = flow->tunnel.ipv6_src;
}
err = tnl_route_lookup_flow(ctx, flow, &d_ip6, &s_ip6, &out_dev);
diff --git a/tests/nsh.at b/tests/nsh.at
index 55296e5593..0040a50b36 100644
--- a/tests/nsh.at
+++ b/tests/nsh.at
@@ -521,51 +521,45 @@ AT_CHECK([
set interface vxlangpe32 type=vxlan options:exts=gpe options:remote_ip=30.0.0.2 options:packet_type=ptap ofport_request=3020
ovs-appctl netdev-dummy/ip4addr br-p1 10.0.0.1/24
- ovs-appctl ovs/route/add 10.0.0.0/24 br-p1
ovs-appctl tnl/arp/set br-p1 10.0.0.1 $HWADDR_BRP1
ovs-appctl tnl/arp/set br-p1 10.0.0.2 $HWADDR_BRP2
ovs-appctl tnl/arp/set br-p1 10.0.0.3 $HWADDR_BRP3
ovs-appctl netdev-dummy/ip4addr br-p2 20.0.0.2/24
- ovs-appctl ovs/route/add 20.0.0.0/24 br-p2
ovs-appctl tnl/arp/set br-p2 20.0.0.1 $HWADDR_BRP1
ovs-appctl tnl/arp/set br-p2 20.0.0.2 $HWADDR_BRP2
ovs-appctl tnl/arp/set br-p2 20.0.0.3 $HWADDR_BRP3
ovs-appctl netdev-dummy/ip4addr br-p3 30.0.0.3/24
- ovs-appctl ovs/route/add 30.0.0.0/24 br-p3
ovs-appctl tnl/arp/set br-p3 30.0.0.1 $HWADDR_BRP1
ovs-appctl tnl/arp/set br-p3 30.0.0.2 $HWADDR_BRP2
ovs-appctl tnl/arp/set br-p3 30.0.0.3 $HWADDR_BRP3
], [0], [stdout])
AT_CHECK([
- ovs-appctl ovs/route/add 10.0.0.0/24 br-p1
ovs-appctl tnl/arp/set br-p1 10.0.0.1 $HWADDR_BRP1
ovs-appctl tnl/arp/set br-p1 10.0.0.2 $HWADDR_BRP2
ovs-appctl tnl/arp/set br-p1 10.0.0.3 $HWADDR_BRP3
], [0], [stdout])
AT_CHECK([
- ovs-appctl ovs/route/add 20.0.0.0/24 br-p2
ovs-appctl tnl/arp/set br-p2 20.0.0.1 $HWADDR_BRP1
ovs-appctl tnl/arp/set br-p2 20.0.0.2 $HWADDR_BRP2
ovs-appctl tnl/arp/set br-p2 20.0.0.3 $HWADDR_BRP3
], [0], [stdout])
AT_CHECK([
- ovs-appctl ovs/route/add 30.0.0.0/24 br-p3
ovs-appctl tnl/arp/set br-p3 30.0.0.1 $HWADDR_BRP1
ovs-appctl tnl/arp/set br-p3 30.0.0.2 $HWADDR_BRP2
ovs-appctl tnl/arp/set br-p3 30.0.0.3 $HWADDR_BRP3
], [0], [stdout])
AT_CHECK([
- ovs-appctl ovs/route/show | grep User:
+ ovs-appctl ovs/route/show | grep Cached: | sort
], [0], [dnl
-User: 10.0.0.0/24 dev br-p1 SRC 10.0.0.1
-User: 20.0.0.0/24 dev br-p2 SRC 20.0.0.2
-User: 30.0.0.0/24 dev br-p3 SRC 30.0.0.3
+Cached: 10.0.0.0/24 dev br-p1 SRC 10.0.0.1 local
+Cached: 20.0.0.0/24 dev br-p2 SRC 20.0.0.2 local
+Cached: 30.0.0.0/24 dev br-p3 SRC 30.0.0.3 local
])
AT_CHECK([
diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
index e305e7b9cd..a1393f7f8e 100644
--- a/tests/ofproto-dpif.at
+++ b/tests/ofproto-dpif.at
@@ -547,6 +547,23 @@ ovs-appctl time/warp 1000 100
ovs-appctl bond/show > bond3.txt
AT_CHECK([sed -n '/member p2/,/^$/p' bond3.txt | grep 'hash'], [0], [ignore])
+# Check that both ports doing down and back up doesn't break statistics.
+AT_CHECK([ovs-appctl netdev-dummy/set-admin-state p1 down], 0, [OK
+])
+AT_CHECK([ovs-appctl netdev-dummy/set-admin-state p2 down], 0, [OK
+])
+ovs-appctl time/warp 1000 100
+AT_CHECK([ovs-appctl netdev-dummy/set-admin-state p1 up], 0, [OK
+])
+AT_CHECK([ovs-appctl netdev-dummy/set-admin-state p2 up], 0, [OK
+])
+ovs-appctl time/warp 1000 100
+
+AT_CHECK([SEND_TCP_BOND_PKTS([p5], [5], [65500])])
+# We sent 49125 KB of data total in 3 batches. No hash should have more
+# than that amount of load. Just checking that it is within 5 digits.
+AT_CHECK([ovs-appctl bond/show | grep -E '[[0-9]]{6}'], [1])
+
OVS_VSWITCHD_STOP()
AT_CLEANUP
@@ -7653,12 +7670,14 @@ dummy@ovs-dummy: hit:0 missed:0
vm1 5/3: (dummy: ifindex=2011)
])
-dnl set up route to 1.1.2.92 via br0 and action=normal
+dnl Add 1.1.2.92 to br0 and action=normal
AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 1.1.2.88/24], [0], [OK
])
-AT_CHECK([ovs-appctl ovs/route/add 1.1.2.92/24 br0], [0], [OK
-])
AT_CHECK([ovs-ofctl add-flow br0 action=normal])
+dnl Checking that a local route for added IP was successfully installed.
+AT_CHECK([ovs-appctl ovs/route/show | grep Cached], [0], [dnl
+Cached: 1.1.2.0/24 dev br0 SRC 1.1.2.88 local
+])
dnl Prime ARP Cache for 1.1.2.92
AT_CHECK([ovs-appctl netdev-dummy/receive p0 'recirc_id(0),in_port(1),eth(src=f8:bc:12:44:34:b6,dst=ff:ff:ff:ff:ff:ff),eth_type(0x0806),arp(sip=1.1.2.92,tip=1.1.2.88,op=2,sha=f8:bc:12:44:34:b6,tha=00:00:00:00:00:00)'])
@@ -7669,10 +7688,13 @@ ovs-vsctl \
--id=@sf create sflow targets=\"127.0.0.1:$SFLOW_PORT\" agent=127.0.0.1 \
header=128 sampling=1 polling=0
-dnl set up route to 192.168.1.2 via br0
+dnl Add 192.168.1.2 to br0,
AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 192.168.1.1/16], [0], [OK
])
-AT_CHECK([ovs-appctl ovs/route/add 192.168.0.0/16 br0], [0], [OK
+dnl Checking that a local route for added IP was successfully installed.
+AT_CHECK([ovs-appctl ovs/route/show | grep Cached | sort], [0], [dnl
+Cached: 1.1.2.0/24 dev br0 SRC 1.1.2.88 local
+Cached: 192.168.0.0/16 dev br0 SRC 192.168.1.1 local
])
dnl add rule for int-br to force packet onto tunnel. There is no ifindex
diff --git a/tests/ovsdb-server.at b/tests/ovsdb-server.at
index b8ccc4c8e2..ce6d32aee1 100644
--- a/tests/ovsdb-server.at
+++ b/tests/ovsdb-server.at
@@ -936,8 +936,10 @@ AT_CHECK_UNQUOTED(
[ignore])
# The error message for being unable to negotiate a shared ciphersuite
# is 'sslv3 alert handshake failure'. This is not the clearest message.
+# In openssl 3.2.0 all the error messages were updated to replace 'sslv3'
+# with 'ssl/tls'.
AT_CHECK_UNQUOTED(
- [grep "sslv3 alert handshake failure" output], [0],
+ [grep -E "(sslv3|ssl/tls) alert handshake failure" output], [0],
[stdout],
[ignore])
OVSDB_SERVER_SHUTDOWN(["
diff --git a/tests/packet-type-aware.at b/tests/packet-type-aware.at
index 14cebf6efa..d634930fd5 100644
--- a/tests/packet-type-aware.at
+++ b/tests/packet-type-aware.at
@@ -142,30 +142,27 @@ AT_CHECK([
### Setup GRE tunnels
AT_CHECK([
ovs-appctl netdev-dummy/ip4addr br-p1 10.0.0.1/24 &&
- ovs-appctl ovs/route/add 10.0.0.0/24 br-p1 &&
ovs-appctl tnl/arp/set br-p1 10.0.0.1 $HWADDR_BRP1 &&
ovs-appctl tnl/arp/set br-p1 10.0.0.2 $HWADDR_BRP2 &&
ovs-appctl tnl/arp/set br-p1 10.0.0.3 $HWADDR_BRP3 &&
ovs-appctl netdev-dummy/ip4addr br-p2 20.0.0.2/24 &&
- ovs-appctl ovs/route/add 20.0.0.0/24 br-p2 &&
ovs-appctl tnl/arp/set br-p2 20.0.0.1 $HWADDR_BRP1 &&
ovs-appctl tnl/arp/set br-p2 20.0.0.2 $HWADDR_BRP2 &&
ovs-appctl tnl/arp/set br-p2 20.0.0.3 $HWADDR_BRP3 &&
ovs-appctl netdev-dummy/ip4addr br-p3 30.0.0.3/24 &&
- ovs-appctl ovs/route/add 30.0.0.0/24 br-p3 &&
ovs-appctl tnl/arp/set br-p3 30.0.0.1 $HWADDR_BRP1 &&
ovs-appctl tnl/arp/set br-p3 30.0.0.2 $HWADDR_BRP2 &&
ovs-appctl tnl/arp/set br-p3 30.0.0.3 $HWADDR_BRP3
], [0], [ignore])
AT_CHECK([
- ovs-appctl ovs/route/show | grep User:
+ ovs-appctl ovs/route/show | grep Cached: | sort
], [0], [dnl
-User: 10.0.0.0/24 dev br-p1 SRC 10.0.0.1
-User: 20.0.0.0/24 dev br-p2 SRC 20.0.0.2
-User: 30.0.0.0/24 dev br-p3 SRC 30.0.0.3
+Cached: 10.0.0.0/24 dev br-p1 SRC 10.0.0.1 local
+Cached: 20.0.0.0/24 dev br-p2 SRC 20.0.0.2 local
+Cached: 30.0.0.0/24 dev br-p3 SRC 30.0.0.3 local
])
AT_CHECK([
@@ -681,14 +678,13 @@ AT_CHECK([
AT_CHECK([
ovs-appctl netdev-dummy/ip4addr br2 10.0.0.1/24 &&
- ovs-appctl ovs/route/add 10.0.0.0/24 br2 &&
ovs-appctl tnl/arp/set br2 10.0.0.2 de:af:be:ef:ba:be
], [0], [ignore])
AT_CHECK([
- ovs-appctl ovs/route/show | grep User:
+ ovs-appctl ovs/route/show | grep Cached:
], [0], [dnl
-User: 10.0.0.0/24 dev br2 SRC 10.0.0.1
+Cached: 10.0.0.0/24 dev br2 SRC 10.0.0.1 local
])
@@ -955,7 +951,6 @@ AT_CHECK([
AT_CHECK([
ovs-appctl netdev-dummy/ip4addr br0 20.0.0.1/24 &&
- ovs-appctl ovs/route/add 20.0.0.2/24 br0 &&
ovs-appctl tnl/neigh/set br0 20.0.0.1 aa:bb:cc:00:00:01 &&
ovs-appctl tnl/neigh/set br0 20.0.0.2 aa:bb:cc:00:00:02
], [0], [ignore])
@@ -963,9 +958,9 @@ AT_CHECK([
ovs-appctl time/warp 1000
AT_CHECK([
- ovs-appctl ovs/route/show | grep User
+ ovs-appctl ovs/route/show | grep Cached:
],[0], [dnl
-User: 20.0.0.0/24 dev br0 SRC 20.0.0.1
+Cached: 20.0.0.0/24 dev br0 SRC 20.0.0.1 local
])
AT_CHECK([
diff --git a/tests/system-layer3-tunnels.at b/tests/system-layer3-tunnels.at
index 6fbdedb64f..5dcdd2afae 100644
--- a/tests/system-layer3-tunnels.at
+++ b/tests/system-layer3-tunnels.at
@@ -98,61 +98,6 @@ NS_CHECK_EXEC([at_ns0], [ping -s 3200 -q -c 3 -i 0.3 -W 2 10.1.1.2 | FORMAT_PING
OVS_TRAFFIC_VSWITCHD_STOP
AT_CLEANUP
-AT_SETUP([layer3 - use non-local port as tunnel endpoint])
-
-OVS_VSWITCHD_START([add-port br0 p0 -- set Interface p0 type=dummy ofport_request=1])
-AT_CHECK([ovs-vsctl add-port br0 vtep0 -- set int vtep0 type=dummy], [0])
-AT_CHECK([ovs-vsctl add-br int-br -- set bridge int-br datapath_type=dummy], [0])
-AT_CHECK([ovs-vsctl add-port int-br t1 -- set Interface t1 type=gre \
- options:remote_ip=1.1.2.92 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)
- vtep0 2/2: (dummy)
- int-br:
- int-br 65534/3: (dummy-internal)
- t1 3/4: (gre: remote_ip=1.1.2.92)
-])
-
-AT_CHECK([ovs-appctl netdev-dummy/ip4addr vtep0 1.1.2.88/24], [0], [OK
-])
-AT_CHECK([ovs-appctl ovs/route/add 1.1.2.92/24 vtep0], [0], [OK
-])
-AT_CHECK([ovs-ofctl add-flow br0 action=normal])
-AT_CHECK([ovs-ofctl add-flow int-br action=normal])
-
-dnl Use arp request and reply to achieve tunnel next hop mac binding
-dnl By default, vtep0's MAC address is aa:55:aa:55:00:03
-AT_CHECK([ovs-appctl netdev-dummy/receive vtep0 'recirc_id(0),in_port(2),eth(dst=ff:ff:ff:ff:ff:ff,src=aa:55:aa:55:00:03),eth_type(0x0806),arp(tip=1.1.2.92,sip=1.1.2.88,op=1,sha=aa:55:aa:55:00:03,tha=00:00:00:00:00:00)'])
-AT_CHECK([ovs-appctl netdev-dummy/receive p0 'recirc_id(0),in_port(1),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:03),eth_type(0x0806),arp(sip=1.1.2.92,tip=1.1.2.88,op=2,sha=f8:bc:12:44:34:b6,tha=aa:55:aa:55:00:03)'])
-
-AT_CHECK([ovs-appctl tnl/neigh/show | tail -n+3 | sort], [0], [dnl
-1.1.2.92 f8:bc:12:44:34:b6 br0
-])
-
-AT_CHECK([ovs-appctl ovs/route/show | tail -n+2 | sort], [0], [dnl
-User: 1.1.2.0/24 dev vtep0 SRC 1.1.2.88
-])
-
-dnl Check GRE tunnel pop
-AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:03),eth_type(0x0800),ipv4(src=1.1.2.92,dst=1.1.2.88,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout])
-
-AT_CHECK([tail -1 stdout], [0],
- [Datapath actions: tnl_pop(4)
-])
-
-dnl Check GRE tunnel push
-AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(3),eth(dst=f9:bc:12:44:34:b6,src=af:55:aa:55:00:03),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.92,proto=1,tos=0,ttl=64,frag=no)'], [0], [stdout])
-AT_CHECK([tail -1 stdout], [0],
- [Datapath actions: tnl_push(tnl_port(4),header(size=38,type=3,eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:03,dl_type=0x0800),ipv4(src=1.1.2.88,dst=1.1.2.92,proto=47,tos=0,ttl=64,frag=0x4000),gre((flags=0x0,proto=0x6558))),out_port(2)),1
-])
-
-OVS_VSWITCHD_STOP
-AT_CLEANUP
-
AT_SETUP([layer3 - ping over MPLS Bareudp])
OVS_CHECK_BAREUDP()
OVS_TRAFFIC_VSWITCHD_START([_ADD_BR([br1])])
diff --git a/tests/system-traffic.at b/tests/system-traffic.at
index 98e494abf4..2d12d558ec 100644
--- a/tests/system-traffic.at
+++ b/tests/system-traffic.at
@@ -6388,6 +6388,7 @@ OVS_TRAFFIC_VSWITCHD_STOP
AT_CLEANUP
AT_SETUP([conntrack - SNAT with port range with exhaustion])
+OVS_CHECK_GITHUB_ACTION()
CHECK_CONNTRACK()
CHECK_CONNTRACK_NAT()
OVS_TRAFFIC_VSWITCHD_START()
@@ -8389,6 +8390,53 @@ AT_CHECK([ovs-pcap client.pcap | grep 000000002010000000002000], [0], [dnl
OVS_TRAFFIC_VSWITCHD_STOP
AT_CLEANUP
+AT_SETUP([conntrack - Flush many conntrack entries by port])
+CHECK_CONNTRACK()
+OVS_TRAFFIC_VSWITCHD_START()
+
+ADD_NAMESPACES(at_ns0, at_ns1)
+
+ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24")
+ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24")
+
+AT_DATA([flows.txt], [dnl
+priority=100,in_port=1,udp,action=ct(zone=1,commit),2
+])
+
+AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt])
+
+dnl 20 packets from port 1 and 1 packet from port 2.
+flow_l3="\
+ eth_src=50:54:00:00:00:09,eth_dst=50:54:00:00:00:0a,dl_type=0x0800,\
+ nw_src=10.1.1.1,nw_dst=10.1.1.2,nw_proto=17,nw_ttl=64,nw_frag=no"
+
+for i in $(seq 1 20); do
+ frame=$(ovs-ofctl compose-packet --bare "$flow_l3, udp_src=1,udp_dst=$i")
+ AT_CHECK([ovs-ofctl -O OpenFlow13 packet-out br0 "in_port=1 packet=$frame actions=resubmit(,0)"])
+done
+frame=$(ovs-ofctl compose-packet --bare "$flow_l3, udp_src=2,udp_dst=1")
+AT_CHECK([ovs-ofctl -O OpenFlow13 packet-out br0 "in_port=1 packet=$frame actions=resubmit(,0)"])
+
+: > conntrack
+
+for i in $(seq 1 20); do
+ echo "udp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=1,dport=${i}),reply=(src=10.1.1.2,dst=10.1.1.1,sport=${i},dport=1),zone=1" >> conntrack
+done
+echo "udp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=2,dport=1),reply=(src=10.1.1.2,dst=10.1.1.1,sport=1,dport=2),zone=1" >> conntrack
+
+sort conntrack > expout
+
+AT_CHECK([ovs-appctl dpctl/dump-conntrack zone=1 | grep -F "src=10.1.1.1," | sort ], [0], [expout])
+
+dnl Check that flushing conntrack by port 1 flush all ct for port 1 but keeps ct for port 2.
+AT_CHECK([ovs-appctl dpctl/flush-conntrack zone=1 'ct_nw_proto=17,ct_tp_src=1'])
+AT_CHECK([ovs-appctl dpctl/dump-conntrack zone=1 | grep -F "src=10.1.1.1," | sort ], [0], [dnl
+udp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=2,dport=1),reply=(src=10.1.1.2,dst=10.1.1.1,sport=1,dport=2),zone=1
+])
+
+OVS_TRAFFIC_VSWITCHD_STOP
+AT_CLEANUP
+
AT_BANNER([IGMP])
AT_SETUP([IGMP - flood under normal action])
diff --git a/tests/tunnel-push-pop-ipv6.at b/tests/tunnel-push-pop-ipv6.at
index a8dd28c5b5..3f2cf84292 100644
--- a/tests/tunnel-push-pop-ipv6.at
+++ b/tests/tunnel-push-pop-ipv6.at
@@ -19,11 +19,12 @@ AT_CHECK([ovs-vsctl add-port int-br3 t3 -- set Interface t3 type=srv6 \
options:srv6_flowlabel=compute \
], [0])
-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.
+dnl Setup dummy interface IP address.
AT_CHECK([ovs-appctl netdev-dummy/ip6addr br0 2001:cafe::88/24], [0], [OK
])
-AT_CHECK([ovs-appctl ovs/route/add 2001:cafe::0/24 br0], [0], [OK
+dnl Checking that a local routes for added IPs were successfully installed.
+AT_CHECK([ovs-appctl ovs/route/show | grep Cached], [0], [dnl
+Cached: 2001:ca00::/24 dev br0 SRC 2001:cafe::88 local
])
AT_CHECK([ovs-appctl tnl/neigh/set br0 2001:cafe::91 aa:55:aa:55:00:01], [0], [OK
])
@@ -105,13 +106,15 @@ dummy@ovs-dummy: hit:0 missed:0
t2 2/6: (ip6gre: remote_ip=2001:cafe::92)
])
-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.
+dnl Setup dummy interface IP addresses.
AT_CHECK([ovs-appctl netdev-dummy/ip6addr br0 2001:cafe::88/24], [0], [OK
])
AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 1.1.2.88/24], [0], [OK
])
-AT_CHECK([ovs-appctl ovs/route/add 2001:cafe::92/24 br0], [0], [OK
+dnl Checking that a local routes for added IPs were successfully installed.
+AT_CHECK([ovs-appctl ovs/route/show | grep Cached | sort], [0], [dnl
+Cached: 1.1.2.0/24 dev br0 SRC 1.1.2.88 local
+Cached: 2001:ca00::/24 dev br0 SRC 2001:cafe::88 local
])
AT_CHECK([ovs-ofctl add-flow br0 action=normal])
@@ -179,13 +182,15 @@ dummy@ovs-dummy: hit:0 missed:0
t3 3/6: (ip6erspan: erspan_dir=1, erspan_hwid=0x7, erspan_ver=2, key=567, remote_ip=2001:cafe::93)
])
-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.
+dnl Setup dummy interface IP addresses.
AT_CHECK([ovs-appctl netdev-dummy/ip6addr br0 2001:cafe::88/24], [0], [OK
])
AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 1.1.2.88/24], [0], [OK
])
-AT_CHECK([ovs-appctl ovs/route/add 2001:cafe::92/24 br0], [0], [OK
+dnl Checking that a local routes for added IPs were successfully installed.
+AT_CHECK([ovs-appctl ovs/route/show | grep Cached | sort], [0], [dnl
+Cached: 1.1.2.0/24 dev br0 SRC 1.1.2.88 local
+Cached: 2001:ca00::/24 dev br0 SRC 2001:cafe::88 local
])
AT_CHECK([ovs-ofctl add-flow br0 action=normal])
@@ -316,14 +321,15 @@ srv6_sys (6) ref_cnt=1
vxlan_sys_4789 (4789) ref_cnt=2
])
-
-dnl First setup dummy interface IP address, then add the route
-dnl so that tnl-port table can get valid IP address for the device.
+dnl Setup dummy interface IP addresses.
AT_CHECK([ovs-appctl netdev-dummy/ip6addr br0 2001:cafe::88/24], [0], [OK
])
AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 1.1.2.88/24], [0], [OK
])
-AT_CHECK([ovs-appctl ovs/route/add 2001:cafe::92/24 br0], [0], [OK
+dnl Checking that a local routes for added IPs were successfully installed.
+AT_CHECK([ovs-appctl ovs/route/show | grep Cached | sort], [0], [dnl
+Cached: 1.1.2.0/24 dev br0 SRC 1.1.2.88 local
+Cached: 2001:ca00::/24 dev br0 SRC 2001:cafe::88 local
])
AT_CHECK([ovs-ofctl add-flow br0 action=normal])
@@ -636,3 +642,87 @@ Listening ports:
OVS_VSWITCHD_STOP
AT_CLEANUP
+
+AT_SETUP([tunnel_push_pop_ipv6 - local_ip configuration])
+
+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-appctl vlog/set dpif_netdev:dbg])
+AT_CHECK([ovs-vsctl add-br int-br -- set bridge int-br datapath_type=dummy])
+AT_CHECK([ovs-vsctl add-port int-br t2 \
+ -- set Interface t2 type=geneve \
+ options:local_ip=2001:beef::88 \
+ options:remote_ip=2001:cafe::92 \
+ options:key=123 ofport_request=2])
+
+dnl Setup multiple IP addresses.
+AT_CHECK([ovs-appctl netdev-dummy/ip6addr br0 2001:cafe::88/64], [0], [OK
+])
+AT_CHECK([ovs-appctl netdev-dummy/ip6addr br0 2001:beef::88/64], [0], [OK
+])
+dnl Checking that a local route for added IP was successfully installed.
+AT_CHECK([ovs-appctl ovs/route/show | grep Cached | sort], [0], [dnl
+Cached: 2001:beef::/64 dev br0 SRC 2001:beef::88 local
+Cached: 2001:cafe::/64 dev br0 SRC 2001:cafe::88 local
+])
+AT_CHECK([ovs-ofctl add-flow br0 action=normal])
+AT_CHECK([ovs-ofctl add-flow int-br action=normal])
+
+dnl This Neighbor Advertisement from p0 has two effects:
+dnl 1. The neighbor cache will learn that 2001:cafe::92 is at f8:bc:12:44:34:b6.
+dnl 2. The br0 mac learning will learn that f8:bc:12:44:34:b6 is on p0.
+AT_CHECK([ovs-appctl netdev-dummy/receive p0 dnl
+ 'recirc_id(0),in_port(1),dnl
+ eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x86dd),dnl
+ ipv6(src=2001:cafe::92,dst=2001:cafe::88,label=0,proto=58,tclass=0,hlimit=255,frag=no),dnl
+ icmpv6(type=136,code=0),dnl
+ nd(target=2001:cafe::92,sll=00:00:00:00:00:00,tll=f8:bc:12:44:34:b6)'
+])
+
+dnl Check that local_ip is used for encapsulation in the trace.
+AT_CHECK([ovs-appctl ofproto/trace int-br in_port=LOCAL \
+ | grep -E 'tunnel|actions'], [0], [dnl
+ -> output to native tunnel
+ -> tunneling to 2001:cafe::92 via br0
+ -> tunneling from aa:55:aa:55:00:00 2001:beef::88 to f8:bc:12:44:34:b6 2001:cafe::92
+Datapath actions: tnl_push(tnl_port(6081),header(size=70,type=5,dnl
+eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:00,dl_type=0x86dd),dnl
+ipv6(src=2001:beef::88,dst=2001:cafe::92,label=0,proto=17,tclass=0x0,hlimit=64),dnl
+udp(src=0,dst=6081,csum=0xffff),geneve(vni=0x7b)),out_port(100)),1
+])
+
+dnl Now check that the packet actually has the local_ip in the header.
+AT_CHECK([ovs-vsctl -- set Interface p0 options:tx_pcap=p0.pcap])
+
+packet=50540000000a5054000000091234
+eth=f8bc124434b6aa55aa55000086dd
+ip6=60000000001e11402001beef0000000000000000000000882001cafe000000000000000000000092
+dnl Source port is based on a packet hash, so it may differ depending on the
+dnl compiler flags and CPU type. Same for UDP checksum. Masked with '....'.
+udp=....17c1001e....
+geneve=0000655800007b00
+encap=${eth}${ip6}${udp}${geneve}
+dnl Output to tunnel from a int-br internal port.
+dnl Checking that the packet arrived and it was correctly encapsulated.
+AT_CHECK([ovs-appctl netdev-dummy/receive int-br "${packet}"])
+OVS_WAIT_UNTIL([test $(ovs-pcap p0.pcap | grep -c "${encap}${packet}") -eq 1])
+dnl Sending again to exercise the non-miss upcall path.
+AT_CHECK([ovs-appctl netdev-dummy/receive int-br "${packet}"])
+OVS_WAIT_UNTIL([test $(ovs-pcap p0.pcap | grep -c "${encap}${packet}") -eq 2])
+
+dnl Finally, checking that the datapath flow also has a local_ip.
+AT_CHECK([ovs-appctl dpctl/dump-flows | grep tnl_push \
+ | strip_ufid | strip_used], [0], [dnl
+recirc_id(0),in_port(2),packet_type(ns=0,id=0),dnl
+eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x1234), dnl
+packets:1, bytes:14, used:0.0s, dnl
+actions:tnl_push(tnl_port(6081),header(size=70,type=5,dnl
+eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:00,dl_type=0x86dd),dnl
+ipv6(src=2001:beef::88,dst=2001:cafe::92,label=0,proto=17,tclass=0x0,hlimit=64),dnl
+udp(src=0,dst=6081,csum=0xffff),geneve(vni=0x7b)),out_port(100)),1
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
diff --git a/tests/tunnel-push-pop.at b/tests/tunnel-push-pop.at
index b1440f5904..97405636f9 100644
--- a/tests/tunnel-push-pop.at
+++ b/tests/tunnel-push-pop.at
@@ -30,17 +30,15 @@ dummy@ovs-dummy: hit:0 missed:0
t4 5/3: (erspan: erspan_dir=flow, erspan_hwid=flow, erspan_idx=flow, erspan_ver=flow, key=56, remote_ip=flow)
])
-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.
+dnl Setup dummy interface IP addresses.
AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 1.1.2.88/24], [0], [OK
])
AT_CHECK([ovs-appctl netdev-dummy/ip6addr br0 2001:cafe::88/24], [0], [OK
])
-
-AT_CHECK([ovs-appctl ovs/route/add 1.1.2.92/24 br0], [0], [OK
-])
-
-AT_CHECK([ovs-appctl ovs/route/add 1.1.2.92/24 br0 pkt_mark=1234], [0], [OK
+dnl Checking that a local routes for added IPs were successfully installed.
+AT_CHECK([ovs-appctl ovs/route/show | grep Cached | sort], [0], [dnl
+Cached: 1.1.2.0/24 dev br0 SRC 1.1.2.88 local
+Cached: 2001:ca00::/24 dev br0 SRC 2001:cafe::88 local
])
AT_CHECK([ovs-ofctl add-flow br0 action=normal])
@@ -237,18 +235,21 @@ dummy@ovs-dummy: hit:0 missed:0
t8 9/2152: (gtpu: key=123, remote_ip=1.1.2.92)
])
-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.
+dnl Setup dummy interface IP addresses.
AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 1.1.2.88/24], [0], [OK
])
AT_CHECK([ovs-appctl netdev-dummy/ip6addr br0 2001:cafe::88/24], [0], [OK
])
-
-AT_CHECK([ovs-appctl ovs/route/add 1.1.2.92/24 br0], [0], [OK
-])
-
+dnl Add a static route with a mark.
AT_CHECK([ovs-appctl ovs/route/add 1.1.2.92/24 br0 pkt_mark=1234], [0], [OK
])
+dnl Checking that local routes for added IPs and the static route with a mark
+dnl were successfully installed.
+AT_CHECK([ovs-appctl ovs/route/show | grep br0 | sort], [0], [dnl
+Cached: 1.1.2.0/24 dev br0 SRC 1.1.2.88 local
+Cached: 2001:ca00::/24 dev br0 SRC 2001:cafe::88 local
+User: 1.1.2.0/24 MARK 1234 dev br0 SRC 1.1.2.88
+])
AT_CHECK([ovs-ofctl add-flow br0 action=normal])
@@ -690,12 +691,12 @@ AT_CHECK([ovs-vsctl add-port int-br t2 -- set Interface t2 type=geneve \
options:remote_ip=1.1.2.92 options:key=123 ofport_request=2 \
])
-dnl First setup dummy interface IP address, then add the route
-dnl so that tnl-port table can get valid IP address for the device.
+dnl Setup dummy interface IP address.
AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 1.1.2.88/24], [0], [OK
])
-
-AT_CHECK([ovs-appctl ovs/route/add 1.1.2.92/24 br0], [0], [OK
+dnl Checking that a local route for added IP was successfully installed.
+AT_CHECK([ovs-appctl ovs/route/show | grep Cached], [0], [dnl
+Cached: 1.1.2.0/24 dev br0 SRC 1.1.2.88 local
])
AT_CHECK([ovs-ofctl add-flow br0 action=normal])
@@ -731,11 +732,12 @@ AT_CHECK([ovs-vsctl add-port int-br t2 dnl
-- set Interface t2 type=geneve options:remote_ip=1.1.2.92 dnl
options:key=123 ofport_request=2])
-dnl First setup dummy interface IP address, then add the route
-dnl so that tnl-port table can get valid IP address for the device.
+dnl Setup dummy interface IP address.
AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 1.1.2.88/24], [0], [OK
])
-AT_CHECK([ovs-appctl ovs/route/add 1.1.2.92/24 br0], [0], [OK
+dnl Checking that a local route for added IP was successfully installed.
+AT_CHECK([ovs-appctl ovs/route/show | grep Cached], [0], [dnl
+Cached: 1.1.2.0/24 dev br0 SRC 1.1.2.88 local
])
AT_CHECK([ovs-ofctl add-flow br0 action=normal])
@@ -777,6 +779,88 @@ AT_CHECK([ovs-appctl dpctl/dump-flows | grep -q 'slow_path(action)'], [0])
OVS_VSWITCHD_STOP
AT_CLEANUP
+AT_SETUP([tunnel_push_pop - local_ip configuration])
+
+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-appctl vlog/set dpif_netdev:dbg])
+AT_CHECK([ovs-vsctl add-br int-br -- set bridge int-br datapath_type=dummy])
+AT_CHECK([ovs-vsctl add-port int-br t2 \
+ -- set Interface t2 type=geneve \
+ options:local_ip=2.2.2.88 \
+ options:remote_ip=1.1.2.92 \
+ options:key=123 ofport_request=2])
+
+dnl Setup multiple IP addresses.
+AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 1.1.2.88/24], [0], [OK
+])
+AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 2.2.2.88/24], [0], [OK
+])
+dnl Checking that a local route for added IP was successfully installed.
+AT_CHECK([ovs-appctl ovs/route/show | grep Cached | sort], [0], [dnl
+Cached: 1.1.2.0/24 dev br0 SRC 1.1.2.88 local
+Cached: 2.2.2.0/24 dev br0 SRC 2.2.2.88 local
+])
+AT_CHECK([ovs-ofctl add-flow br0 action=normal])
+AT_CHECK([ovs-ofctl add-flow int-br action=normal])
+
+dnl This ARP reply from p0 has two effects:
+dnl 1. The ARP cache will learn that 1.1.2.92 is at f8:bc:12:44:34:b6.
+dnl 2. The br0 mac learning will learn that f8:bc:12:44:34:b6 is on p0.
+AT_CHECK([ovs-appctl netdev-dummy/receive p0 dnl
+ 'recirc_id(0),in_port(1),dnl
+ eth(src=f8:bc:12:44:34:b6,dst=ff:ff:ff:ff:ff:ff),eth_type(0x0806),dnl
+ arp(sip=1.1.2.92,tip=1.1.2.88,op=2,sha=f8:bc:12:44:34:b6,tha=00:00:00:00:00:00)'
+])
+
+dnl Check that local_ip is used for encapsulation in the trace.
+AT_CHECK([ovs-appctl ofproto/trace int-br in_port=LOCAL \
+ | grep -E 'tunnel|actions'], [0], [dnl
+ -> output to native tunnel
+ -> tunneling to 1.1.2.92 via br0
+ -> tunneling from aa:55:aa:55:00:00 2.2.2.88 to f8:bc:12:44:34:b6 1.1.2.92
+Datapath actions: tnl_push(tnl_port(6081),header(size=50,type=5,dnl
+eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:00,dl_type=0x0800),dnl
+ipv4(src=2.2.2.88,dst=1.1.2.92,proto=17,tos=0,ttl=64,frag=0x4000),dnl
+udp(src=0,dst=6081,csum=0x0),geneve(vni=0x7b)),out_port(100)),1
+])
+
+dnl Now check that the packet actually has the local_ip in the header.
+AT_CHECK([ovs-vsctl -- set Interface p0 options:tx_pcap=p0.pcap])
+
+packet=50540000000a5054000000091234
+eth=f8bc124434b6aa55aa5500000800
+ip4=450000320000400040113305020202580101025c
+dnl Source port is based on a packet hash, so it may differ depending on the
+dnl compiler flags and CPU type. Masked with '....'.
+udp=....17c1001e0000
+geneve=0000655800007b00
+encap=${eth}${ip4}${udp}${geneve}
+dnl Output to tunnel from a int-br internal port.
+dnl Checking that the packet arrived and it was correctly encapsulated.
+AT_CHECK([ovs-appctl netdev-dummy/receive int-br "${packet}"])
+OVS_WAIT_UNTIL([test $(ovs-pcap p0.pcap | grep -c "${encap}${packet}") -eq 1])
+dnl Sending again to exercise the non-miss upcall path.
+AT_CHECK([ovs-appctl netdev-dummy/receive int-br "${packet}"])
+OVS_WAIT_UNTIL([test $(ovs-pcap p0.pcap | grep -c "${encap}${packet}") -eq 2])
+
+dnl Finally, checking that the datapath flow also has a local_ip.
+AT_CHECK([ovs-appctl dpctl/dump-flows | grep tnl_push \
+ | strip_ufid | strip_used], [0], [dnl
+recirc_id(0),in_port(2),packet_type(ns=0,id=0),dnl
+eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x1234), dnl
+packets:1, bytes:14, used:0.0s, dnl
+actions:tnl_push(tnl_port(6081),header(size=50,type=5,dnl
+eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:00,dl_type=0x0800),dnl
+ipv4(src=2.2.2.88,dst=1.1.2.92,proto=17,tos=0,ttl=64,frag=0x4000),dnl
+udp(src=0,dst=6081,csum=0x0),geneve(vni=0x7b)),out_port(100)),1
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
AT_SETUP([tunnel_push_pop - underlay bridge match])
OVS_VSWITCHD_START([add-port br0 p0 -- set Interface p0 type=dummy ofport_request=1 other-config:hwaddr=aa:55:aa:55:00:00])
@@ -796,8 +880,11 @@ dummy@ovs-dummy: hit:0 missed:0
AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 1.1.2.88/24], [0], [OK
])
-AT_CHECK([ovs-appctl ovs/route/add 1.1.2.92/24 br0], [0], [OK
+dnl Checking that a local route for added IP was successfully installed.
+AT_CHECK([ovs-appctl ovs/route/show | grep Cached], [0], [dnl
+Cached: 1.1.2.0/24 dev br0 SRC 1.1.2.88 local
])
+
AT_CHECK([ovs-ofctl add-flow br0 'arp,priority=1,action=normal'])
dnl Use arp reply to achieve tunnel next hop mac binding
@@ -840,11 +927,12 @@ AT_CHECK([ovs-vsctl add-port int-br t2 dnl
-- set Interface t2 type=geneve options:remote_ip=1.1.2.92 dnl
options:key=123 ofport_request=2])
-dnl First setup dummy interface IP address, then add the route
-dnl so that tnl-port table can get valid IP address for the device.
+dnl Setup dummy interface IP address.
AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 1.1.2.88/24], [0], [OK
])
-AT_CHECK([ovs-appctl ovs/route/add 1.1.2.92/24 br0], [0], [OK
+dnl Checking that a local route for added IP was successfully installed.
+AT_CHECK([ovs-appctl ovs/route/show | grep Cached], [0], [dnl
+Cached: 1.1.2.0/24 dev br0 SRC 1.1.2.88 local
])
AT_CHECK([ovs-ofctl add-flow br0 action=normal])
@@ -908,10 +996,12 @@ AT_CHECK([ovs-vsctl set port p8 tag=42 dnl
-- set port br0 tag=42 dnl
-- set port p7 tag=200])
-dnl Set IP address and route for br0.
+dnl Set an IP address for br0.
AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 10.0.0.2/24], [0], [OK
])
-AT_CHECK([ovs-appctl ovs/route/add 10.0.0.11/24 br0], [0], [OK
+dnl Checking that a local route for added IP was successfully installed.
+AT_CHECK([ovs-appctl ovs/route/show | grep Cached], [0], [dnl
+Cached: 10.0.0.0/24 dev br0 SRC 10.0.0.2 local
])
dnl Send an ARP reply to port b8 on br0, so that packets will be forwarded
@@ -953,10 +1043,12 @@ AT_CHECK([ovs-vsctl add-port ovs-tun0 tun0 dnl
-- add-port ovs-tun0 p7 dnl
-- set interface p7 type=dummy ofport_request=7])
-dnl Set IP address and route for br0.
+dnl Set an IP address for br0.
AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 10.0.0.2/24], [0], [OK
])
-AT_CHECK([ovs-appctl ovs/route/add 10.0.0.11/24 br0], [0], [OK
+dnl Checking that a local route for added IP was successfully installed.
+AT_CHECK([ovs-appctl ovs/route/show | grep Cached], [0], [dnl
+Cached: 10.0.0.0/24 dev br0 SRC 10.0.0.2 local
])
dnl Send an ARP reply to port b8 on br0, so that packets will be forwarded
@@ -993,3 +1085,81 @@ udp(src=0,dst=4789,csum=0x0),vxlan(flags=0x8000000,vni=0x0)),out_port(100)),8),7
OVS_VSWITCHD_STOP
AT_CLEANUP
+
+AT_SETUP([tunnel_push_pop - use non-local port as tunnel endpoint])
+
+OVS_VSWITCHD_START([add-port br0 p0 \
+ -- set Interface p0 type=dummy ofport_request=1])
+
+dnl Adding another port separately to ensure that it gets an
+dnl aa:55:aa:55:00:03 MAC address (dummy port number 3).
+AT_CHECK([ovs-vsctl add-port br0 vtep0 \
+ -- set interface vtep0 type=dummy ofport_request=2])
+AT_CHECK([ovs-vsctl \
+ -- add-br int-br \
+ -- set bridge int-br datapath_type=dummy \
+ -- set Interface int-br ofport_request=3])
+AT_CHECK([ovs-vsctl \
+ -- add-port int-br t1 \
+ -- set Interface t1 type=gre ofport_request=4 \
+ options:remote_ip=1.1.2.92
+])
+
+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)
+ vtep0 2/2: (dummy)
+ int-br:
+ int-br 65534/3: (dummy-internal)
+ t1 4/4: (gre: remote_ip=1.1.2.92)
+])
+
+AT_CHECK([ovs-appctl netdev-dummy/ip4addr vtep0 1.1.2.88/24], [0], [OK
+])
+dnl Checking that a local route for added IP was successfully installed.
+AT_CHECK([ovs-appctl ovs/route/show | grep Cached], [0], [dnl
+Cached: 1.1.2.0/24 dev vtep0 SRC 1.1.2.88 local
+])
+
+AT_CHECK([ovs-ofctl add-flow br0 action=normal])
+AT_CHECK([ovs-ofctl add-flow int-br action=normal])
+
+dnl Use arp request and reply to achieve tunnel next hop mac binding.
+dnl By default, vtep0's MAC address is aa:55:aa:55:00:03.
+AT_CHECK([ovs-appctl netdev-dummy/receive vtep0 'recirc_id(0),in_port(2),dnl
+ eth(dst=ff:ff:ff:ff:ff:ff,src=aa:55:aa:55:00:03),eth_type(0x0806),dnl
+ arp(tip=1.1.2.92,sip=1.1.2.88,op=1,sha=aa:55:aa:55:00:03,tha=00:00:00:00:00:00)'])
+AT_CHECK([ovs-appctl netdev-dummy/receive p0 'recirc_id(0),in_port(1),dnl
+ eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:03),eth_type(0x0806),dnl
+ arp(sip=1.1.2.92,tip=1.1.2.88,op=2,sha=f8:bc:12:44:34:b6,tha=aa:55:aa:55:00:03)'])
+
+AT_CHECK([ovs-appctl tnl/neigh/show | tail -n+3 | sort], [0], [dnl
+1.1.2.92 f8:bc:12:44:34:b6 br0
+])
+
+dnl Check GRE tunnel pop.
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),dnl
+ eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:03),eth_type(0x0800),dnl
+ ipv4(src=1.1.2.92,dst=1.1.2.88,proto=47,tos=0,ttl=64,frag=no)'],
+[0], [stdout])
+
+AT_CHECK([tail -1 stdout], [0],
+ [Datapath actions: tnl_pop(4)
+])
+
+dnl Check GRE tunnel push.
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(3),dnl
+ eth(dst=f9:bc:12:44:34:b6,src=af:55:aa:55:00:03),eth_type(0x0800),dnl
+ ipv4(src=1.1.3.88,dst=1.1.3.92,proto=1,tos=0,ttl=64,frag=no)'],
+[0], [stdout])
+AT_CHECK([tail -1 stdout], [0],
+ [Datapath actions: tnl_push(tnl_port(4),header(size=38,type=3,dnl
+eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:03,dl_type=0x0800),dnl
+ipv4(src=1.1.2.88,dst=1.1.2.92,proto=47,tos=0,ttl=64,frag=0x4000),dnl
+gre((flags=0x0,proto=0x6558))),out_port(2)),1
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
diff --git a/tests/tunnel.at b/tests/tunnel.at
index 282651ac73..71e7c2df4e 100644
--- a/tests/tunnel.at
+++ b/tests/tunnel.at
@@ -524,11 +524,12 @@ dummy@ovs-dummy: hit:0 missed:0
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.
+dnl Setup dummy interface IP address.
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 Checking that a local route for added IP was successfully installed.
+AT_CHECK([ovs-appctl ovs/route/show | grep Cached], [0], [dnl
+Cached: 172.31.1.0/24 dev br0 SRC 172.31.1.1 local
])
dnl change the flow table to bump the internal table version
@@ -1276,15 +1277,12 @@ OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=dummy \
ofport_request=2])
OVS_VSWITCHD_DISABLE_TUNNEL_PUSH_POP
-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.
+dnl Setup dummy interface IP address.
AT_CHECK([ovs-appctl netdev-dummy/ip6addr br0 fc00::1/64], [0], [OK
])
-AT_CHECK([ovs-appctl ovs/route/add fc00::0/64 br0], [0], [OK
-])
-AT_CHECK([ovs-appctl ovs/route/show], [0], [dnl
-Route Table:
-User: fc00::/64 dev br0 SRC fc00::1
+dnl Checking that a local route for added IP was successfully installed.
+AT_CHECK([ovs-appctl ovs/route/show | grep Cached], [0], [dnl
+Cached: fc00::/64 dev br0 SRC fc00::1 local
])
AT_DATA([flows.txt], [dnl
diff --git a/utilities/ovs-pki.in b/utilities/ovs-pki.in
index e0ba910f94..285018e41e 100755
--- a/utilities/ovs-pki.in
+++ b/utilities/ovs-pki.in
@@ -57,6 +57,77 @@ FreeBSD|NetBSD|Darwin)
;;
esac
+case $(uname -s) in
+MINGW*|MSYS*)
+ chmod()
+ {
+ local PERM=$1
+ local FILE=$2
+ local INH=
+
+ if test -d "${FILE}"; then
+ # Inheritance rules for folders: apply to a folder itself,
+ # subfolders and files within.
+ INH='(OI)(CI)'
+ fi
+
+ case "${PERM}" in
+ *700 | *600)
+ # Reset all own and inherited ACEs and grant full access to the
+ # "Creator Owner". We're giving full access even for 0600,
+ # because it doesn't matter for a use case of ovs-pki.
+ icacls "${FILE}" /inheritance:r /grant:r "*S-1-3-0:${INH}F"
+ ;;
+ *750)
+ # Reset all own and inherited ACEs, grant full access to the
+ # "Creator Owner" and a read+execute access to the "Creator Group".
+ icacls "${FILE}" /inheritance:r /grant:r \
+ "*S-1-3-0:${INH}F" "*S-1-3-1:${INH}RX"
+ ;;
+ *)
+ echo >&2 "Unable to set ${PERM} mode for ${FILE}."
+ exit 1
+ ;;
+ esac
+ }
+
+ mkdir()
+ {
+ ARG_P=
+ PERM=
+ for arg; do
+ shift
+ case ${arg} in
+ -m?*)
+ PERM=${arg#??}
+ continue
+ ;;
+ -m)
+ PERM=$1
+ shift
+ continue
+ ;;
+ -p)
+ ARG_P=-p
+ continue
+ ;;
+ *)
+ set -- "$@" "${arg}"
+ ;;
+ esac
+ done
+
+ command mkdir ${ARG_P} $@
+ if [ ${PERM} ]; then
+ for dir; do
+ shift
+ chmod ${PERM} ${dir}
+ done
+ fi
+ }
+ ;;
+esac
+
for option; do
# This option-parsing mechanism borrowed from a Autoconf-generated
# configure script under the following license:
@@ -466,14 +537,24 @@ CN = $cn
[ v3_req ]
subjectAltName = DNS:$cn
EOF
+ # It is important to create private keys in $TMP because umask doesn't
+ # work on Windows and permissions there are inherited from the folder.
+ # umask itself is still needed though to ensure correct permissions
+ # on non-Windows platforms.
if test $keytype = rsa; then
- (umask 077 && openssl genrsa -out "$1-privkey.pem" $bits) 1>&3 2>&3 \
- || exit $?
+ (umask 077 && openssl genrsa -out "$TMP/privkey.pem" $bits) \
+ 1>&3 2>&3 || exit $?
else
must_exist "$dsaparam"
- (umask 077 && openssl gendsa -out "$1-privkey.pem" "$dsaparam") \
+ (umask 077 && openssl gendsa -out "$TMP/privkey.pem" "$dsaparam") \
1>&3 2>&3 || exit $?
fi
+ # Windows: applying permissions (ACEs) to the file itself, just in case.
+ # 'mv' should technically preserve all the inherited ACEs from a TMP
+ # folder, but it's better to not rely on that.
+ chmod 0600 "$TMP/privkey.pem"
+ mv "$TMP/privkey.pem" "$1-privkey.pem"
+
openssl req -config "$TMP/req.cnf" -new -text \
-key "$1-privkey.pem" -out "$1-req.pem" 1>&3 2>&3
}