diff --git a/NEWS b/NEWS
index 75f26ddb7..4043ecf20 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,6 @@
+OVN v21.12.1 - xx xxx xxxx
+--------------------------
+
OVN v21.12.0 - 22 Dec 2021
--------------------------
- Set ignore_lsp_down to true as default, so that ARP responder flows are
diff --git a/configure.ac b/configure.ac
index 48b4662f0..e44c86c74 100644
--- a/configure.ac
+++ b/configure.ac
@@ -13,7 +13,7 @@
# limitations under the License.
AC_PREREQ(2.63)
-AC_INIT(ovn, 21.12.0, bugs@openvswitch.org)
+AC_INIT(ovn, 21.12.1, bugs@openvswitch.org)
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_HEADERS([config.h])
diff --git a/controller/physical.c b/controller/physical.c
index 836fc769a..aa651b876 100644
--- a/controller/physical.c
+++ b/controller/physical.c
@@ -1477,10 +1477,12 @@ consider_mc_group(struct ovsdb_idl_index *sbrec_port_binding_by_name,
put_load(port->tunnel_key, MFF_LOG_OUTPORT, 0, 32,
&remote_ofpacts);
put_resubmit(OFTABLE_CHECK_LOOPBACK, &remote_ofpacts);
- } else if (local_binding_get_primary_pb(local_bindings, lport_name)
- || simap_contains(patch_ofports, port->logical_port)
- || (!strcmp(port->type, "l3gateway")
- && port->chassis == chassis)) {
+ } else if (port->chassis == chassis
+ && (local_binding_get_primary_pb(local_bindings, lport_name)
+ || !strcmp(port->type, "l3gateway"))) {
+ put_load(port->tunnel_key, MFF_LOG_OUTPORT, 0, 32, &ofpacts);
+ put_resubmit(OFTABLE_CHECK_LOOPBACK, &ofpacts);
+ } else if (simap_contains(patch_ofports, port->logical_port)) {
put_load(port->tunnel_key, MFF_LOG_OUTPORT, 0, 32, &ofpacts);
put_resubmit(OFTABLE_CHECK_LOOPBACK, &ofpacts);
} else if (!strcmp(port->type, "chassisredirect")
diff --git a/controller/pinctrl.c b/controller/pinctrl.c
index f0667807e..d2bb7f441 100644
--- a/controller/pinctrl.c
+++ b/controller/pinctrl.c
@@ -1624,12 +1624,8 @@ pinctrl_handle_icmp(struct rconn *swconn, const struct flow *ip_flow,
struct dp_packet packet;
dp_packet_use_stub(&packet, packet_stub, sizeof packet_stub);
- dp_packet_clear(&packet);
- packet.packet_type = htonl(PT_ETH);
-
- struct eth_header *eh = dp_packet_put_zeros(&packet, sizeof *eh);
- eh->eth_dst = loopback ? ip_flow->dl_src : ip_flow->dl_dst;
- eh->eth_src = loopback ? ip_flow->dl_dst : ip_flow->dl_src;
+ struct eth_addr eth_src = loopback ? ip_flow->dl_dst : ip_flow->dl_src;
+ struct eth_addr eth_dst = loopback ? ip_flow->dl_src : ip_flow->dl_dst;
if (get_dl_type(ip_flow) == htons(ETH_TYPE_IP)) {
struct ip_header *in_ip = dp_packet_l3(pkt_in);
@@ -1642,27 +1638,8 @@ pinctrl_handle_icmp(struct rconn *swconn, const struct flow *ip_flow,
return;
}
- struct ip_header *nh = dp_packet_put_zeros(&packet, sizeof *nh);
-
- eh->eth_type = htons(ETH_TYPE_IP);
- dp_packet_set_l3(&packet, nh);
- nh->ip_ihl_ver = IP_IHL_VER(5, 4);
- nh->ip_tot_len = htons(sizeof(struct ip_header) +
- sizeof(struct icmp_header));
- nh->ip_proto = IPPROTO_ICMP;
- nh->ip_frag_off = htons(IP_DF);
ovs_be32 nw_src = loopback ? ip_flow->nw_dst : ip_flow->nw_src;
ovs_be32 nw_dst = loopback ? ip_flow->nw_src : ip_flow->nw_dst;
- packet_set_ipv4(&packet, nw_src, nw_dst, ip_flow->nw_tos, 255);
-
- uint8_t icmp_code = 1;
- if (set_icmp_code && in_ip->ip_proto == IPPROTO_UDP) {
- icmp_code = 3;
- }
-
- struct icmp_header *ih = dp_packet_put_zeros(&packet, sizeof *ih);
- dp_packet_set_l4(&packet, ih);
- packet_set_icmp(&packet, ICMP4_DST_UNREACH, icmp_code);
/* RFC 1122: 3.2.2 MUST send at least the IP header and 8 bytes
* of header. MAY send more.
@@ -1671,51 +1648,40 @@ pinctrl_handle_icmp(struct rconn *swconn, const struct flow *ip_flow,
* So, lets return as much as we can. */
/* Calculate available room to include the original IP + data. */
- nh = dp_packet_l3(&packet);
- uint16_t room = 576 - (sizeof *eh + ntohs(nh->ip_tot_len));
+ uint16_t room = 576 - (sizeof(struct eth_header)
+ + sizeof(struct ip_header)
+ + sizeof(struct icmp_header));
if (in_ip_len > room) {
in_ip_len = room;
}
- dp_packet_put(&packet, in_ip, in_ip_len);
- /* dp_packet_put may reallocate the buffer. Get the l3 and l4
- * header pointers again. */
- nh = dp_packet_l3(&packet);
- ih = dp_packet_l4(&packet);
- uint16_t ip_total_len = ntohs(nh->ip_tot_len) + in_ip_len;
- nh->ip_tot_len = htons(ip_total_len);
+ uint16_t ip_total_len = sizeof(struct icmp_header) + in_ip_len;
+
+ pinctrl_compose_ipv4(&packet, eth_src, eth_dst, nw_src, nw_dst,
+ IPPROTO_ICMP, 255, ip_total_len);
+
+ uint8_t icmp_code = 1;
+ if (set_icmp_code && in_ip->ip_proto == IPPROTO_UDP) {
+ icmp_code = 3;
+ }
+
+ struct icmp_header *ih = dp_packet_l4(&packet);
+ packet_set_icmp(&packet, ICMP4_DST_UNREACH, icmp_code);
+
+ /* Include original IP + data. */
+ void *data = ih + 1;
+ memcpy(data, in_ip, in_ip_len);
+
ih->icmp_csum = 0;
ih->icmp_csum = csum(ih, sizeof *ih + in_ip_len);
- nh->ip_csum = 0;
- nh->ip_csum = csum(nh, sizeof *nh);
-
} else {
- struct ip6_hdr *nh = dp_packet_put_zeros(&packet, sizeof *nh);
- struct icmp6_data_header *ih;
- uint32_t icmpv6_csum;
- struct ip6_hdr *in_ip = dp_packet_l3(pkt_in);
-
- eh->eth_type = htons(ETH_TYPE_IPV6);
- dp_packet_set_l3(&packet, nh);
- nh->ip6_vfc = 0x60;
- nh->ip6_nxt = IPPROTO_ICMPV6;
- nh->ip6_plen = htons(ICMP6_DATA_HEADER_LEN);
+ struct ovs_16aligned_ip6_hdr *in_ip = dp_packet_l3(pkt_in);
+ uint16_t in_ip_len = (uint16_t) sizeof *in_ip + ntohs(in_ip->ip6_plen);
+
const struct in6_addr *ip6_src =
loopback ? &ip_flow->ipv6_dst : &ip_flow->ipv6_src;
const struct in6_addr *ip6_dst =
loopback ? &ip_flow->ipv6_src : &ip_flow->ipv6_dst;
- packet_set_ipv6(&packet, ip6_src, ip6_dst, ip_flow->nw_tos,
- ip_flow->ipv6_label, 255);
-
- ih = dp_packet_put_zeros(&packet, sizeof *ih);
- dp_packet_set_l4(&packet, ih);
- ih->icmp6_base.icmp6_type = ICMP6_DST_UNREACH;
- ih->icmp6_base.icmp6_code = 1;
-
- if (set_icmp_code && in_ip->ip6_nxt == IPPROTO_UDP) {
- ih->icmp6_base.icmp6_code = ICMP6_DST_UNREACH_NOPORT;
- }
- ih->icmp6_base.icmp6_cksum = 0;
/* RFC 4443: 3.1.
*
@@ -1730,20 +1696,33 @@ pinctrl_handle_icmp(struct rconn *swconn, const struct flow *ip_flow,
* | exceeding the minimum IPv6 MTU [IPv6] |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
-
- uint16_t room = 1280 - (sizeof *eh + sizeof *nh +
- ICMP6_DATA_HEADER_LEN);
- uint16_t in_ip_len = (uint16_t) sizeof *in_ip + ntohs(in_ip->ip6_plen);
+ uint16_t room = 1280 - (sizeof(struct eth_header)
+ + sizeof(struct ip6_hdr)
+ + ICMP6_DATA_HEADER_LEN);
if (in_ip_len > room) {
in_ip_len = room;
}
- dp_packet_put(&packet, in_ip, in_ip_len);
- nh = dp_packet_l3(&packet);
- nh->ip6_plen = htons(ICMP6_DATA_HEADER_LEN + in_ip_len);
+ uint16_t ip_total_len =
+ sizeof(struct icmp6_data_header) + in_ip_len;
+ pinctrl_compose_ipv6(&packet, eth_src, eth_dst,
+ CONST_CAST(struct in6_addr *, ip6_src),
+ CONST_CAST(struct in6_addr *, ip6_dst),
+ IPPROTO_ICMPV6, 255, ip_total_len);
- icmpv6_csum = packet_csum_pseudoheader6(dp_packet_l3(&packet));
- ih = dp_packet_l4(&packet);
+ struct icmp6_data_header *ih = dp_packet_l4(&packet);
+ ih->icmp6_base.icmp6_type = ICMP6_DST_UNREACH;
+ ih->icmp6_base.icmp6_code = 1;
+
+ if (set_icmp_code && in_ip->ip6_nxt == IPPROTO_UDP) {
+ ih->icmp6_base.icmp6_code = ICMP6_DST_UNREACH_NOPORT;
+ }
+ ih->icmp6_base.icmp6_cksum = 0;
+
+ void *data = ih + 1;
+ memcpy(data, in_ip, in_ip_len);
+ uint32_t icmpv6_csum =
+ packet_csum_pseudoheader6(dp_packet_l3(&packet));
ih->icmp6_base.icmp6_cksum = csum_finish(
csum_continue(icmpv6_csum, ih,
in_ip_len + ICMP6_DATA_HEADER_LEN));
@@ -1777,7 +1756,6 @@ pinctrl_handle_tcp_reset(struct rconn *swconn, const struct flow *ip_flow,
struct dp_packet packet;
dp_packet_use_stub(&packet, packet_stub, sizeof packet_stub);
- packet.packet_type = htonl(PT_ETH);
struct eth_addr eth_src = loopback ? ip_flow->dl_dst : ip_flow->dl_src;
struct eth_addr eth_dst = loopback ? ip_flow->dl_src : ip_flow->dl_dst;
@@ -1798,8 +1776,8 @@ pinctrl_handle_tcp_reset(struct rconn *swconn, const struct flow *ip_flow,
IPPROTO_TCP, 63, TCP_HEADER_LEN);
}
- struct tcp_header *th = dp_packet_put_zeros(&packet, sizeof *th);
- dp_packet_set_l4(&packet, th);
+ struct tcp_header *th = dp_packet_l4(&packet);
+
th->tcp_dst = ip_flow->tp_src;
th->tcp_src = ip_flow->tp_dst;
@@ -1825,18 +1803,6 @@ pinctrl_handle_tcp_reset(struct rconn *swconn, const struct flow *ip_flow,
dp_packet_uninit(&packet);
}
-static void dp_packet_put_sctp_abort(struct dp_packet *packet,
- bool reflect_tag)
-{
- struct sctp_chunk_header abort = {
- .sctp_chunk_type = SCTP_CHUNK_TYPE_ABORT,
- .sctp_chunk_flags = reflect_tag ? SCTP_ABORT_CHUNK_FLAG_T : 0,
- .sctp_chunk_len = htons(SCTP_CHUNK_HEADER_LEN),
- };
-
- dp_packet_put(packet, &abort, sizeof abort);
-}
-
static void
pinctrl_handle_sctp_abort(struct rconn *swconn, const struct flow *ip_flow,
struct dp_packet *pkt_in,
@@ -1870,7 +1836,7 @@ pinctrl_handle_sctp_abort(struct rconn *swconn, const struct flow *ip_flow,
return;
}
- const struct sctp_init_chunk *sh_in_init = NULL;
+ const struct sctp_16aligned_init_chunk *sh_in_init = NULL;
if (sh_in_chunk->sctp_chunk_type == SCTP_CHUNK_TYPE_INIT) {
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
sh_in_init = dp_packet_at(pkt_in, pkt_in->l4_ofs +
@@ -1909,8 +1875,7 @@ pinctrl_handle_sctp_abort(struct rconn *swconn, const struct flow *ip_flow,
SCTP_CHUNK_HEADER_LEN);
}
- struct sctp_header *sh = dp_packet_put_zeros(&packet, sizeof *sh);
- dp_packet_set_l4(&packet, sh);
+ struct sctp_header *sh = dp_packet_l4(&packet);
sh->sctp_dst = ip_flow->tp_src;
sh->sctp_src = ip_flow->tp_dst;
put_16aligned_be32(&sh->sctp_csum, 0);
@@ -1918,7 +1883,7 @@ pinctrl_handle_sctp_abort(struct rconn *swconn, const struct flow *ip_flow,
bool tag_reflected;
if (get_16aligned_be32(&sh_in->sctp_vtag) == 0 && sh_in_init) {
/* See RFC 4960 Section 8.4, item 3. */
- put_16aligned_be32(&sh->sctp_vtag, sh_in_init->initiate_tag);
+ sh->sctp_vtag = sh_in_init->initiate_tag;
tag_reflected = false;
} else {
/* See RFC 4960 Section 8.4, item 8. */
@@ -1926,7 +1891,11 @@ pinctrl_handle_sctp_abort(struct rconn *swconn, const struct flow *ip_flow,
tag_reflected = true;
}
- dp_packet_put_sctp_abort(&packet, tag_reflected);
+ struct sctp_chunk_header *ah =
+ ALIGNED_CAST(struct sctp_chunk_header *, sh + 1);
+ ah->sctp_chunk_type = SCTP_CHUNK_TYPE_ABORT;
+ ah->sctp_chunk_flags = tag_reflected ? SCTP_ABORT_CHUNK_FLAG_T : 0,
+ ah->sctp_chunk_len = htons(SCTP_CHUNK_HEADER_LEN),
put_16aligned_be32(&sh->sctp_csum, crc32c((void *) sh,
dp_packet_l4_size(&packet)));
@@ -2942,7 +2911,7 @@ pinctrl_handle_dns_lookup(
goto exit;
}
- uint16_t query_type = ntohs(*ALIGNED_CAST(const ovs_be16 *, in_dns_data));
+ uint16_t query_type = ntohs(get_unaligned_be16((void *) in_dns_data));
/* Supported query types - A, AAAA, ANY and PTR */
if (!(query_type == DNS_QUERY_TYPE_A || query_type == DNS_QUERY_TYPE_AAAA
|| query_type == DNS_QUERY_TYPE_ANY
@@ -4564,16 +4533,15 @@ pinctrl_compose_ipv4(struct dp_packet *packet, struct eth_addr eth_src,
ovs_be32 ipv4_dst, uint8_t ip_proto, uint8_t ttl,
uint16_t ip_payload_len)
{
- dp_packet_clear(packet);
- packet->packet_type = htonl(PT_ETH);
-
- struct eth_header *eh = dp_packet_put_zeros(packet, sizeof *eh);
- struct ip_header *nh = dp_packet_put_zeros(packet, sizeof *nh);
+ struct ip_header *nh;
+ size_t ip_tot_len = sizeof *nh + ip_payload_len;
- eh->eth_dst = eth_dst;
- eh->eth_src = eth_src;
- eh->eth_type = htons(ETH_TYPE_IP);
- dp_packet_set_l3(packet, nh);
+ /* Need to deal with odd-sized IP length while making sure that the
+ * packet is still aligned. Reserve 2 bytes for potential VLAN tags.
+ */
+ dp_packet_reserve(packet,
+ sizeof(struct eth_header) + ROUND_UP(ip_tot_len, 2) + 2);
+ nh = eth_compose(packet, eth_dst, eth_src, ETH_TYPE_IP, ip_tot_len);
nh->ip_ihl_ver = IP_IHL_VER(5, 4);
nh->ip_tot_len = htons(sizeof *nh + ip_payload_len);
nh->ip_tos = IP_DSCP_CS6;
@@ -4584,6 +4552,7 @@ pinctrl_compose_ipv4(struct dp_packet *packet, struct eth_addr eth_src,
nh->ip_csum = 0;
nh->ip_csum = csum(nh, sizeof *nh);
+ dp_packet_set_l4(packet, nh + 1);
}
static void
@@ -4592,23 +4561,21 @@ pinctrl_compose_ipv6(struct dp_packet *packet, struct eth_addr eth_src,
struct in6_addr *ipv6_dst, uint8_t ip_proto, uint8_t ttl,
uint16_t ip_payload_len)
{
- dp_packet_clear(packet);
- packet->packet_type = htonl(PT_ETH);
-
- struct eth_header *eh = dp_packet_put_zeros(packet, sizeof *eh);
- struct ip6_hdr *nh = dp_packet_put_zeros(packet, sizeof *nh);
-
- eh->eth_dst = eth_dst;
- eh->eth_src = eth_src;
- eh->eth_type = htons(ETH_TYPE_IPV6);
- dp_packet_set_l3(packet, nh);
- dp_packet_set_l4(packet, nh + 1);
+ struct ip6_hdr *nh;
+ size_t ip_tot_len = sizeof *nh + ip_payload_len;
+ /* Need to deal with odd-sized IP length while making sure that the
+ * packet is still aligned. Reserve 2 bytes for potential VLAN tags.
+ */
+ dp_packet_reserve(packet,
+ sizeof(struct eth_header) + ROUND_UP(ip_tot_len, 2) + 2);
+ nh = eth_compose(packet, eth_dst, eth_src, ETH_TYPE_IPV6, ip_tot_len);
nh->ip6_vfc = 0x60;
nh->ip6_nxt = ip_proto;
nh->ip6_plen = htons(ip_payload_len);
packet_set_ipv6(packet, ipv6_src, ipv6_dst, 0, 0, ttl);
+ dp_packet_set_l4(packet, nh + 1);
}
/*
@@ -5400,10 +5367,6 @@ ip_mcast_querier_send_igmp(struct rconn *swconn, struct ip_mcast_snoop *ip_ms)
ip_ms->cfg.query_ipv4_dst,
IPPROTO_IGMP, 1, sizeof(struct igmpv3_query_header));
- struct igmpv3_query_header *igh =
- dp_packet_put_zeros(&packet, sizeof *igh);
- dp_packet_set_l4(&packet, igh);
-
/* IGMP query max-response in tenths of seconds. */
uint8_t max_response = ip_ms->cfg.query_max_resp_s * 10;
uint8_t qqic = max_response;
@@ -5449,15 +5412,10 @@ ip_mcast_querier_send_mld(struct rconn *swconn, struct ip_mcast_snoop *ip_ms)
IPPROTO_HOPOPTS, 1,
IPV6_EXT_HEADER_LEN + MLD_QUERY_HEADER_LEN);
- struct ipv6_ext_header *ext_hdr =
- dp_packet_put_zeros(&packet, IPV6_EXT_HEADER_LEN);
+ struct ipv6_ext_header *ext_hdr = dp_packet_l4(&packet);
packet_set_ipv6_ext_header(ext_hdr, IPPROTO_ICMPV6, 0, mld_router_alert,
ARRAY_SIZE(mld_router_alert));
- struct mld_header *mh =
- dp_packet_put_zeros(&packet, MLD_QUERY_HEADER_LEN);
- dp_packet_set_l4(&packet, mh);
-
/* MLD query max-response in milliseconds. */
uint16_t max_response = ip_ms->cfg.query_max_resp_s * 1000;
uint8_t qqic = ip_ms->cfg.query_max_resp_s;
@@ -6033,6 +5991,8 @@ pinctrl_handle_put_nd_ra_opts(
struct dp_packet pkt_out;
dp_packet_init(&pkt_out, new_packet_size);
dp_packet_clear(&pkt_out);
+ /* Properly align after the ethernet header */
+ dp_packet_reserve(&pkt_out, 2);
dp_packet_prealloc_tailroom(&pkt_out, new_packet_size);
pkt_out_ptr = &pkt_out;
@@ -6155,23 +6115,26 @@ wait_controller_event(struct ovsdb_idl_txn *ovnsb_idl_txn)
static bool
pinctrl_handle_empty_lb_backends_opts(struct ofpbuf *userdata)
{
- struct controller_event_opt_header *userdata_opt;
+ struct controller_event_opt_header opt_hdr;
+ void *userdata_opt;
uint32_t hash = 0;
char *vip = NULL;
char *protocol = NULL;
char *load_balancer = NULL;
while (userdata->size) {
- userdata_opt = ofpbuf_try_pull(userdata, sizeof *userdata_opt);
+ userdata_opt = ofpbuf_try_pull(userdata, sizeof opt_hdr);
if (!userdata_opt) {
return false;
}
- size_t size = ntohs(userdata_opt->size);
+ memcpy(&opt_hdr, userdata_opt, sizeof opt_hdr);
+
+ size_t size = ntohs(opt_hdr.size);
char *userdata_opt_data = ofpbuf_try_pull(userdata, size);
if (!userdata_opt_data) {
return false;
}
- switch (ntohs(userdata_opt->opt_code)) {
+ switch (ntohs(opt_hdr.opt_code)) {
case EMPTY_LB_VIP:
vip = xmemdup0(userdata_opt_data, size);
break;
@@ -6820,8 +6783,6 @@ bfd_monitor_put_bfd_msg(struct bfd_entry *entry, struct dp_packet *packet,
{
int payload_len = sizeof(struct udp_header) + sizeof(struct bfd_msg);
- /* Properly align after the ethernet header */
- dp_packet_reserve(packet, 2);
if (IN6_IS_ADDR_V4MAPPED(&entry->ip_src)) {
ovs_be32 ip_src = in6_addr_get_mapped_ipv4(&entry->ip_src);
ovs_be32 ip_dst = in6_addr_get_mapped_ipv4(&entry->ip_dst);
@@ -6833,13 +6794,13 @@ bfd_monitor_put_bfd_msg(struct bfd_entry *entry, struct dp_packet *packet,
MAXTTL, payload_len);
}
- struct udp_header *udp = dp_packet_put_zeros(packet, sizeof *udp);
+ struct udp_header *udp = dp_packet_l4(packet);
udp->udp_len = htons(payload_len);
udp->udp_csum = 0;
udp->udp_src = htons(entry->udp_src);
udp->udp_dst = htons(BFD_DEST_PORT);
- struct bfd_msg *msg = dp_packet_put_zeros(packet, sizeof *msg);
+ struct bfd_msg *msg = ALIGNED_CAST(struct bfd_msg *, udp + 1);
msg->vers_diag = (BFD_VERSION << 5);
msg->mult = entry->local_mult;
msg->length = BFD_PACKET_LEN;
@@ -7383,7 +7344,7 @@ svc_monitor_send_tcp_health_check__(struct rconn *swconn,
ip4_src, in6_addr_get_mapped_ipv4(&svc_mon->ip),
IPPROTO_TCP, 63, TCP_HEADER_LEN);
- struct tcp_header *th = dp_packet_put_zeros(&packet, sizeof *th);
+ struct tcp_header *th = dp_packet_l4(&packet);
dp_packet_set_l4(&packet, th);
th->tcp_dst = htons(svc_mon->proto_port);
th->tcp_src = tcp_src;
@@ -7446,13 +7407,12 @@ svc_monitor_send_udp_health_check(struct rconn *swconn,
ip4_src, in6_addr_get_mapped_ipv4(&svc_mon->ip),
IPPROTO_UDP, 63, UDP_HEADER_LEN + 8);
- struct udp_header *uh = dp_packet_put_zeros(&packet, sizeof *uh);
+ struct udp_header *uh = dp_packet_l4(&packet);
dp_packet_set_l4(&packet, uh);
uh->udp_dst = htons(svc_mon->proto_port);
uh->udp_src = udp_src;
uh->udp_len = htons(UDP_HEADER_LEN + 8);
uh->udp_csum = 0;
- dp_packet_put_zeros(&packet, 8);
uint64_t ofpacts_stub[4096 / 8];
struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(ofpacts_stub);
diff --git a/debian/changelog b/debian/changelog
index 0cc5f14ac..0d8593083 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+OVN (21.12.1-1) unstable; urgency=low
+ [ OVN team ]
+ * New upstream version
+
+ -- OVN team <dev@openvswitch.org> Wed, 22 Dec 2021 09:45:52 -0500
+
ovn (21.12.0-1) unstable; urgency=low
* New upstream version
diff --git a/lib/actions.c b/lib/actions.c
index da00ee349..a78d01198 100644
--- a/lib/actions.c
+++ b/lib/actions.c
@@ -1842,19 +1842,20 @@ encode_event_empty_lb_backends_opts(struct ofpbuf *ofpacts,
{
for (const struct ovnact_gen_option *o = event->options;
o < &event->options[event->n_options]; o++) {
- struct controller_event_opt_header *hdr =
- ofpbuf_put_uninit(ofpacts, sizeof *hdr);
+
+ /* All empty_lb_backends fields are of type 'str' */
+ ovs_assert(!strcmp(o->option->type, "str"));
+
const union expr_constant *c = o->value.values;
- size_t size;
- hdr->opt_code = htons(o->option->code);
- if (!strcmp(o->option->type, "str")) {
- size = strlen(c->string);
- hdr->size = htons(size);
- ofpbuf_put(ofpacts, c->string, size);
- } else {
- /* All empty_lb_backends fields are of type 'str' */
- OVS_NOT_REACHED();
- }
+ size_t size = strlen(c->string);
+ struct controller_event_opt_header hdr =
+ (struct controller_event_opt_header) {
+ .opt_code = htons(o->option->code),
+ .size = htons(size),
+ };
+
+ memcpy(ofpbuf_put_uninit(ofpacts, sizeof hdr), &hdr, sizeof hdr);
+ ofpbuf_put(ofpacts, c->string, size);
}
}
diff --git a/lib/ovn-l7.h b/lib/ovn-l7.h
index 9a33f5cda..256e963d9 100644
--- a/lib/ovn-l7.h
+++ b/lib/ovn-l7.h
@@ -502,7 +502,7 @@ struct mld_query_header {
ovs_be16 csum;
ovs_be16 max_resp;
ovs_be16 rsvd;
- struct in6_addr group;
+ union ovs_16aligned_in6_addr group;
uint8_t srs_qrv;
uint8_t qqic;
ovs_be16 nsrcs;
@@ -518,7 +518,9 @@ packet_set_mld_query(struct dp_packet *packet, uint16_t max_resp,
const struct in6_addr *group,
bool srs, uint8_t qrv, uint8_t qqic)
{
- struct mld_query_header *mqh = dp_packet_l4(packet);
+ struct ipv6_ext_header *ext_hdr = dp_packet_l4(packet);
+ struct mld_query_header *mqh = ALIGNED_CAST(struct mld_query_header *,
+ ext_hdr + 1);
mqh->type = MLD_QUERY;
mqh->code = 0;
mqh->max_resp = htons(max_resp);
diff --git a/lib/ovn-util.h b/lib/ovn-util.h
index a923c3b65..b212c64b7 100644
--- a/lib/ovn-util.h
+++ b/lib/ovn-util.h
@@ -261,14 +261,16 @@ struct sctp_chunk_header {
BUILD_ASSERT_DECL(SCTP_CHUNK_HEADER_LEN == sizeof(struct sctp_chunk_header));
#define SCTP_INIT_CHUNK_LEN 16
-struct sctp_init_chunk {
- ovs_be32 initiate_tag;
- ovs_be32 a_rwnd;
+struct sctp_16aligned_init_chunk {
+ ovs_16aligned_be32 initiate_tag;
+ ovs_16aligned_be32 a_rwnd;
ovs_be16 num_outbound_streams;
ovs_be16 num_inbound_streams;
- ovs_be32 initial_tsn;
+ ovs_16aligned_be32 initial_tsn;
};
-BUILD_ASSERT_DECL(SCTP_INIT_CHUNK_LEN == sizeof(struct sctp_init_chunk));
+BUILD_ASSERT_DECL(
+ SCTP_INIT_CHUNK_LEN == sizeof(struct sctp_16aligned_init_chunk)
+);
/* These are the only SCTP chunk types that OVN cares about.
* There is no need to define the other chunk types until they are
diff --git a/tests/ovn.at b/tests/ovn.at
index 9ec62e321..92e284e8a 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -9658,8 +9658,8 @@ as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
# expected packet at foo2
packet=${dst_mac}${src_mac}8100000208004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
-echo $packet > expected
-OVN_CHECK_PACKETS([hv2/vm2-tx.pcap], [expected])
+echo $packet > expected2
+OVN_CHECK_PACKETS([hv2/vm2-tx.pcap], [expected2])
# Send ip packets between foo1 and bar2 (different switch, different HV)
src_mac="f00000010205"
@@ -9673,8 +9673,8 @@ as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
src_mac="000000010204"
dst_mac="f00000010208"
packet=${dst_mac}${src_mac}8100000108004500001c000000003f110100${src_ip}${dst_ip}0035111100080000
-echo $packet >> expected
-OVN_CHECK_PACKETS([hv2/vm2-tx.pcap], [expected])
+echo $packet >> expected2
+OVN_CHECK_PACKETS([hv2/vm2-tx.pcap], [expected2])
# Send ip packets between foo1 and bar1
# (different switch, loopback to same vm but different tag)
@@ -9703,11 +9703,11 @@ as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
# expected packet at bar3
packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
-echo $packet > expected
-OVN_CHECK_PACKETS([hv1/bar3-tx.pcap], [expected])
+echo $packet > expected3
+OVN_CHECK_PACKETS([hv1/bar3-tx.pcap], [expected3])
# Send ip packets between foo1 and vm1.
-(different switch, container to the VM hosting it.)
+# (different switch, container to the VM hosting it.)
src_mac="f00000010205"
dst_mac="000000010203"
src_ip=`ip_to_hex 192 168 1 2`
@@ -9723,7 +9723,7 @@ echo $packet >> expected1
OVN_CHECK_PACKETS([hv1/vm1-tx.pcap], [expected1])
# Send packets from vm1 to bar1.
-(different switch, A hosting VM to a container inside it)
+# (different switch, A hosting VM to a container inside it)
src_mac="f00000010203"
dst_mac="000000010202"
src_ip=`ip_to_hex 172 16 1 2`
@@ -9739,6 +9739,7 @@ echo $packet >> expected1
OVN_CHECK_PACKETS([hv1/vm1-tx.pcap], [expected1])
# Send broadcast packet from foo1. foo1 should not receive the same packet.
+# But foo2 should.
src_mac="f00000010205"
dst_mac="ffffffffffff"
src_ip=`ip_to_hex 192 168 1 2`
@@ -9749,6 +9750,11 @@ as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
# expected packet at VM1
OVN_CHECK_PACKETS([hv1/vm1-tx.pcap], [expected1])
+# expected packet at foo2
+packet=${dst_mac}${src_mac}8100000208004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
+echo $packet >> expected2
+OVN_CHECK_PACKETS([hv2/vm2-tx.pcap], [expected2])
+
# Test binding of parent and container ports.
ovn-nbctl lsp-set-options vm1 requested-chassis=foo