odp-util: Fix IPFIX breakage with old kernel modules.
[cascardo/ovs.git] / lib / odp-util.c
index ce821c5..a8d561b 100644 (file)
@@ -1392,7 +1392,7 @@ generate_all_wildcard_mask(struct ofpbuf *ofp, const struct nlattr *key)
     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;
 
@@ -2563,9 +2563,8 @@ odp_flow_key_from_flow__(struct ofpbuf *buf, const struct flow *data,
                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);
@@ -2995,10 +2994,10 @@ parse_l2_5_onward(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1],
             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;
         }
@@ -3310,8 +3309,20 @@ odp_put_userspace_action(uint32_t pid,
     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;
     }
@@ -3436,9 +3447,8 @@ commit_mpls_action(const struct flow *flow, struct flow *base,
     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;