bond: Stop using tags.
[sliver-openvswitch.git] / lib / odp-util.c
index c05664c..50b7e81 100644 (file)
@@ -144,8 +144,9 @@ static void
 format_odp_sample_action(struct ds *ds, const struct nlattr *attr)
 {
     static const struct nl_policy ovs_sample_policy[] = {
-        [OVS_SAMPLE_ATTR_PROBABILITY] = { .type = NL_A_U32 },
-        [OVS_SAMPLE_ATTR_ACTIONS] = { .type = NL_A_NESTED }
+        { NL_A_NO_ATTR, 0, 0, false }, /* OVS_SAMPLE_ATTR_UNSPEC */
+        { NL_A_U32, 0, 0, false },     /* OVS_SAMPLE_ATTR_PROBABILITY */
+        { NL_A_NESTED, 0, 0, false },  /* OVS_SAMPLE_ATTR_ACTIONS */
     };
     struct nlattr *a[ARRAY_SIZE(ovs_sample_policy)];
     double percentage;
@@ -259,9 +260,9 @@ static void
 format_odp_userspace_action(struct ds *ds, const struct nlattr *attr)
 {
     static const struct nl_policy ovs_userspace_policy[] = {
-        [OVS_USERSPACE_ATTR_PID] = { .type = NL_A_U32 },
-        [OVS_USERSPACE_ATTR_USERDATA] = { .type = NL_A_UNSPEC,
-                                          .optional = true },
+        { NL_A_NO_ATTR, 0, 0, false }, /* OVS_USERSPACE_ATTR_UNSPEC */
+        { NL_A_U32, 0, 0, false },     /* OVS_USERSPACE_ATTR_PID */
+        { NL_A_UNSPEC, 0, 0, true },   /* OVS_USERSPACE_ATTR_USERDATA */
     };
     struct nlattr *a[ARRAY_SIZE(ovs_userspace_policy)];
     const struct nlattr *userdata_attr;
@@ -1058,7 +1059,7 @@ format_odp_key_attr(const struct nlattr *a, const struct nlattr *ma,
             ovs_be16 vlan_tci = nl_attr_get_be16(a);
             if (!is_exact) {
                 ovs_be16 mask = nl_attr_get_be16(ma);
-                ds_put_format(ds, "vid=%"PRIu16"/%"PRIx16",pcp=%d/0x%x,cfi=%d/%d",
+                ds_put_format(ds, "vid=%"PRIu16"/0x%"PRIx16",pcp=%d/0x%x,cfi=%d/%d",
                               vlan_tci_to_vid(vlan_tci),
                               vlan_tci_to_vid(mask),
                               vlan_tci_to_pcp(vlan_tci),
@@ -2310,6 +2311,17 @@ ovs_to_odp_frag(uint8_t nw_frag)
           : OVS_FRAG_TYPE_LATER);
 }
 
+static uint8_t
+ovs_to_odp_frag_mask(uint8_t nw_frag_mask)
+{
+    uint8_t frag_mask = ~(OVS_FRAG_TYPE_FIRST | OVS_FRAG_TYPE_LATER);
+
+    frag_mask |= (nw_frag_mask & FLOW_NW_FRAG_ANY) ? OVS_FRAG_TYPE_FIRST : 0;
+    frag_mask |= (nw_frag_mask & FLOW_NW_FRAG_LATER) ? OVS_FRAG_TYPE_LATER : 0;
+
+    return frag_mask;
+}
+
 static void
 odp_flow_key_from_flow__(struct ofpbuf *buf, const struct flow *data,
                          const struct flow *flow, odp_port_t odp_in_port)
@@ -2326,7 +2338,7 @@ odp_flow_key_from_flow__(struct ofpbuf *buf, const struct flow *data,
         nl_msg_put_u32(buf, OVS_KEY_ATTR_PRIORITY, data->skb_priority);
     }
 
-    if (flow->tunnel.ip_dst) {
+    if (flow->tunnel.ip_dst || is_mask) {
         tun_key_to_attr(buf, &data->tunnel);
     }
 
@@ -2390,7 +2402,8 @@ odp_flow_key_from_flow__(struct ofpbuf *buf, const struct flow *data,
         ipv4_key->ipv4_proto = data->nw_proto;
         ipv4_key->ipv4_tos = data->nw_tos;
         ipv4_key->ipv4_ttl = data->nw_ttl;
-        ipv4_key->ipv4_frag = ovs_to_odp_frag(data->nw_frag);
+        ipv4_key->ipv4_frag = is_mask ? ovs_to_odp_frag_mask(data->nw_frag)
+                                      : ovs_to_odp_frag(data->nw_frag);
     } else if (flow->dl_type == htons(ETH_TYPE_IPV6)) {
         struct ovs_key_ipv6 *ipv6_key;
 
@@ -2402,7 +2415,8 @@ odp_flow_key_from_flow__(struct ofpbuf *buf, const struct flow *data,
         ipv6_key->ipv6_proto = data->nw_proto;
         ipv6_key->ipv6_tclass = data->nw_tos;
         ipv6_key->ipv6_hlimit = data->nw_ttl;
-        ipv6_key->ipv6_frag = ovs_to_odp_frag(flow->nw_frag);
+        ipv6_key->ipv6_frag = is_mask ? ovs_to_odp_frag_mask(data->nw_frag)
+                                      : ovs_to_odp_frag(data->nw_frag);
     } else if (flow->dl_type == htons(ETH_TYPE_ARP) ||
                flow->dl_type == htons(ETH_TYPE_RARP)) {
         struct ovs_key_arp *arp_key;
@@ -2511,7 +2525,8 @@ uint32_t
 odp_flow_key_hash(const struct nlattr *key, size_t key_len)
 {
     BUILD_ASSERT_DECL(!(NLA_ALIGNTO % sizeof(uint32_t)));
-    return hash_words((const uint32_t *) key, key_len / sizeof(uint32_t), 0);
+    return hash_words(ALIGNED_CAST(const uint32_t *, key),
+                      key_len / sizeof(uint32_t), 0);
 }
 
 static void