int size = nl_attr_get_size(key);
if (odp_flow_key_attr_len(type) >=0) {
- memset(nl_msg_put_unspec_uninit(ofp, type, size), 0, size);
+ nl_msg_put_unspec_zero(ofp, type, size);
} else {
size_t nested_mask;
flow->dl_type == htons(ETH_TYPE_RARP)) {
struct ovs_key_arp *arp_key;
- arp_key = nl_msg_put_unspec_uninit(buf, OVS_KEY_ATTR_ARP,
- sizeof *arp_key);
- memset(arp_key, 0, sizeof *arp_key);
+ arp_key = nl_msg_put_unspec_zero(buf, OVS_KEY_ATTR_ARP,
+ sizeof *arp_key);
arp_key->arp_sip = data->nw_src;
arp_key->arp_tip = data->nw_dst;
arp_key->arp_op = htons(data->nw_proto);
flow->tp_dst = udp_key->udp_dst;
expected_bit = OVS_KEY_ATTR_UDP;
}
- } else if (flow->nw_proto == IPPROTO_SCTP
- && (flow->dl_type == htons(ETH_TYPE_IP) ||
- flow->dl_type == htons(ETH_TYPE_IPV6))
- && !(flow->nw_frag & FLOW_NW_FRAG_LATER)) {
+ } else if (src_flow->nw_proto == IPPROTO_SCTP
+ && (src_flow->dl_type == htons(ETH_TYPE_IP) ||
+ src_flow->dl_type == htons(ETH_TYPE_IPV6))
+ && !(src_flow->nw_frag & FLOW_NW_FRAG_LATER)) {
if (!is_mask) {
expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_SCTP;
}
nl_msg_put_u32(odp_actions, OVS_USERSPACE_ATTR_PID, pid);
if (userdata) {
userdata_ofs = odp_actions->size + NLA_HDRLEN;
- nl_msg_put_unspec(odp_actions, OVS_USERSPACE_ATTR_USERDATA,
- userdata, userdata_size);
+
+ /* The OVS kernel module before OVS 1.11 and the upstream Linux kernel
+ * module before Linux 3.10 required the userdata to be exactly 8 bytes
+ * long:
+ *
+ * - The kernel rejected shorter userdata with -ERANGE.
+ *
+ * - The kernel silently dropped userdata beyond the first 8 bytes.
+ *
+ * Thus, for maximum compatibility, always put at least 8 bytes. (We
+ * separately disable features that required more than 8 bytes.) */
+ memcpy(nl_msg_put_unspec_zero(odp_actions, OVS_USERSPACE_ATTR_USERDATA,
+ MAX(8, userdata_size)),
+ userdata, userdata_size);
} else {
userdata_ofs = 0;
}
case 1: {
struct ovs_action_push_mpls *mpls;
- mpls = nl_msg_put_unspec_uninit(odp_actions, OVS_ACTION_ATTR_PUSH_MPLS,
- sizeof *mpls);
- memset(mpls, 0, sizeof *mpls);
+ mpls = nl_msg_put_unspec_zero(odp_actions, OVS_ACTION_ATTR_PUSH_MPLS,
+ sizeof *mpls);
mpls->mpls_ethertype = flow->dl_type;
mpls->mpls_lse = flow->mpls_lse;
break;