utils: Introduce xsleep for RCU quiescent state
[sliver-openvswitch.git] / lib / odp-util.c
index b81d0d2..7c6aad4 100644 (file)
@@ -149,9 +149,8 @@ static void
 format_odp_sample_action(struct ds *ds, const struct nlattr *attr)
 {
     static const struct nl_policy ovs_sample_policy[] = {
-        { 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 */
+        [OVS_SAMPLE_ATTR_PROBABILITY] = { .type = NL_A_U32 },
+        [OVS_SAMPLE_ATTR_ACTIONS] = { .type = NL_A_NESTED }
     };
     struct nlattr *a[ARRAY_SIZE(ovs_sample_policy)];
     double percentage;
@@ -255,9 +254,9 @@ static void
 format_odp_userspace_action(struct ds *ds, const struct nlattr *attr)
 {
     static const struct nl_policy ovs_userspace_policy[] = {
-        { 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 */
+        [OVS_USERSPACE_ATTR_PID] = { .type = NL_A_U32 },
+        [OVS_USERSPACE_ATTR_USERDATA] = { .type = NL_A_UNSPEC,
+                                          .optional = true },
     };
     struct nlattr *a[ARRAY_SIZE(ovs_userspace_policy)];
     const struct nlattr *userdata_attr;
@@ -872,7 +871,8 @@ tun_key_to_attr(struct ofpbuf *a, const struct flow_tnl *tun_key)
 
     tun_key_ofs = nl_msg_start_nested(a, OVS_KEY_ATTR_TUNNEL);
 
-    if (tun_key->flags & FLOW_TNL_F_KEY) {
+    /* tun_id != 0 without FLOW_TNL_F_KEY is valid if tun_key is a mask. */
+    if (tun_key->tun_id || tun_key->flags & FLOW_TNL_F_KEY) {
         nl_msg_put_be64(a, OVS_TUNNEL_KEY_ATTR_ID, tun_key->tun_id);
     }
     if (tun_key->ip_src) {
@@ -2646,8 +2646,8 @@ odp_key_from_pkt_metadata(struct ofpbuf *buf, const struct pkt_metadata *md)
 
     /* Add an ingress port attribute if 'odp_in_port' is not the magical
      * value "ODPP_NONE". */
-    if (md->in_port != ODPP_NONE) {
-        nl_msg_put_odp_port(buf, OVS_KEY_ATTR_IN_PORT, md->in_port);
+    if (md->in_port.odp_port != ODPP_NONE) {
+        nl_msg_put_odp_port(buf, OVS_KEY_ATTR_IN_PORT, md->in_port.odp_port);
     }
 }
 
@@ -2662,8 +2662,7 @@ odp_key_to_pkt_metadata(const struct nlattr *key, size_t key_len,
         1u << OVS_KEY_ATTR_SKB_MARK | 1u << OVS_KEY_ATTR_TUNNEL |
         1u << OVS_KEY_ATTR_IN_PORT;
 
-    memset(md, 0, sizeof *md);
-    md->in_port = ODPP_NONE;
+    *md = PKT_METADATA_INITIALIZER(ODPP_NONE);
 
     NL_ATTR_FOR_EACH (nla, left, key, key_len) {
         uint16_t type = nl_attr_type(nla);
@@ -2690,7 +2689,7 @@ odp_key_to_pkt_metadata(const struct nlattr *key, size_t key_len,
                 wanted_attrs &= ~(1u << OVS_KEY_ATTR_TUNNEL);
             }
         } else if (type == OVS_KEY_ATTR_IN_PORT) {
-            md->in_port = nl_attr_get_odp_port(nla);
+            md->in_port.odp_port = nl_attr_get_odp_port(nla);
             wanted_attrs &= ~(1u << OVS_KEY_ATTR_IN_PORT);
         }
 
@@ -3147,7 +3146,6 @@ parse_8021q_onward(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1],
            ? attrs[OVS_KEY_ATTR_ENCAP] : NULL);
     enum odp_key_fitness encap_fitness;
     enum odp_key_fitness fitness;
-    ovs_be16 tci;
 
     /* Calculate fitness of outer attributes. */
     if (!is_mask) {
@@ -3164,35 +3162,32 @@ parse_8021q_onward(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1],
     fitness = check_expectations(present_attrs, out_of_range_attr,
                                  expected_attrs, key, key_len);
 
-    /* Get the VLAN TCI value. */
-    if (!is_mask && !(present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_VLAN))) {
-        return ODP_FIT_TOO_LITTLE;
+    /* Set vlan_tci.
+     * Remove the TPID from dl_type since it's not the real Ethertype.  */
+    flow->dl_type = htons(0);
+    flow->vlan_tci = (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_VLAN)
+                      ? nl_attr_get_be16(attrs[OVS_KEY_ATTR_VLAN])
+                      : htons(0));
+    if (!is_mask) {
+        if (!(present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_VLAN))) {
+            return ODP_FIT_TOO_LITTLE;
+        } else if (flow->vlan_tci == htons(0)) {
+            /* Corner case for a truncated 802.1Q header. */
+            if (fitness == ODP_FIT_PERFECT && nl_attr_get_size(encap)) {
+                return ODP_FIT_TOO_MUCH;
+            }
+            return fitness;
+        } else if (!(flow->vlan_tci & htons(VLAN_CFI))) {
+            VLOG_ERR_RL(&rl, "OVS_KEY_ATTR_VLAN 0x%04"PRIx16" is nonzero "
+                        "but CFI bit is not set", ntohs(flow->vlan_tci));
+            return ODP_FIT_ERROR;
+        }
     } else {
-        tci = (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_VLAN)
-               ? nl_attr_get_be16(attrs[OVS_KEY_ATTR_VLAN])
-               : htons(0));
-        if (!is_mask) {
-            if (tci == htons(0)) {
-                /* Corner case for a truncated 802.1Q header. */
-                if (fitness == ODP_FIT_PERFECT && nl_attr_get_size(encap)) {
-                    return ODP_FIT_TOO_MUCH;
-                }
-                return fitness;
-            } else if (!(tci & htons(VLAN_CFI))) {
-                VLOG_ERR_RL(&rl, "OVS_KEY_ATTR_VLAN 0x%04"PRIx16" is nonzero "
-                            "but CFI bit is not set", ntohs(tci));
-                return ODP_FIT_ERROR;
-            }
+        if (!(present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_ENCAP))) {
+            return fitness;
         }
-        /* Set vlan_tci.
-         * Remove the TPID from dl_type since it's not the real Ethertype.  */
-        flow->dl_type = htons(0);
-        flow->vlan_tci = tci;
     }
 
-    if (is_mask && !(present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_ENCAP))) {
-        return fitness;
-    }
     /* Now parse the encapsulated attributes. */
     if (!parse_flow_nlattrs(nl_attr_get(encap), nl_attr_get_size(encap),
                             attrs, &present_attrs, &out_of_range_attr)) {
@@ -3548,10 +3543,6 @@ commit_mpls_action(const struct flow *flow, struct flow *base,
     while (base_n < flow_n) {
         struct ovs_action_push_mpls *mpls;
 
-        /* If there's a VLAN tag, pop it off so that our new MPLS label doesn't
-         * end up outside it. */
-        pop_vlan(base, odp_actions, wc);
-
         mpls = nl_msg_put_unspec_zero(odp_actions,
                                       OVS_ACTION_ATTR_PUSH_MPLS,
                                       sizeof *mpls);