log errors from host command
[sliver-openvswitch.git] / lib / meta-flow.c
index 6b3b5eb..ce061a3 100644 (file)
@@ -27,6 +27,7 @@
 #include "dynamic-string.h"
 #include "ofp-errors.h"
 #include "ofp-util.h"
+#include "ovs-thread.h"
 #include "packets.h"
 #include "random.h"
 #include "shash.h"
@@ -136,14 +137,14 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
         0, NULL,
         0, NULL,
     }, {
-        MFF_SKB_MARK, "skb_mark", NULL,
+        MFF_PKT_MARK, "pkt_mark", NULL,
         MF_FIELD_SIZES(be32),
-        MFM_NONE,
+        MFM_FULLY,
         MFS_HEXADECIMAL,
         MFP_NONE,
-        false,
-        0, NULL,
-        0, NULL,
+        true,
+        NXM_NX_PKT_MARK, "NXM_NX_PKT_MARK",
+        NXM_NX_PKT_MARK, "NXM_NX_PKT_MARK",
     },
 
 #define REGISTER(IDX)                           \
@@ -580,13 +581,17 @@ struct nxm_field {
 };
 
 /* Contains 'struct nxm_field's. */
-static struct hmap all_fields = HMAP_INITIALIZER(&all_fields);
+static struct hmap all_fields;
+
+/* Maps from an mf_field's 'name' or 'extra_name' to the mf_field. */
+static struct shash mf_by_name;
 
 /* Rate limit for parse errors.  These always indicate a bug in an OpenFlow
  * controller and so there's not much point in showing a lot of them. */
 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
 
 const struct mf_field *mf_from_nxm_header__(uint32_t header);
+static void nxm_init(void);
 
 /* Returns the field with the given 'id'. */
 const struct mf_field *
@@ -601,19 +606,7 @@ mf_from_id(enum mf_field_id id)
 const struct mf_field *
 mf_from_name(const char *name)
 {
-    static struct shash mf_by_name = SHASH_INITIALIZER(&mf_by_name);
-
-    if (shash_is_empty(&mf_by_name)) {
-        const struct mf_field *mf;
-
-        for (mf = mf_fields; mf < &mf_fields[MFF_N_IDS]; mf++) {
-            shash_add_once(&mf_by_name, mf->name, mf);
-            if (mf->extra_name) {
-                shash_add_once(&mf_by_name, mf->extra_name, mf);
-            }
-        }
-    }
-
+    nxm_init();
     return shash_find_data(&mf_by_name, name);
 }
 
@@ -641,24 +634,36 @@ nxm_init_add_field(const struct mf_field *mf, uint32_t header)
 }
 
 static void
-nxm_init(void)
+nxm_do_init(void)
 {
     const struct mf_field *mf;
 
+    hmap_init(&all_fields);
+    shash_init(&mf_by_name);
     for (mf = mf_fields; mf < &mf_fields[MFF_N_IDS]; mf++) {
         nxm_init_add_field(mf, mf->nxm_header);
         if (mf->oxm_header != mf->nxm_header) {
             nxm_init_add_field(mf, mf->oxm_header);
         }
+
+        shash_add_once(&mf_by_name, mf->name, mf);
+        if (mf->extra_name) {
+            shash_add_once(&mf_by_name, mf->extra_name, mf);
+        }
     }
 }
 
+static void
+nxm_init(void)
+{
+    static pthread_once_t once = PTHREAD_ONCE_INIT;
+    pthread_once(&once, nxm_do_init);
+}
+
 const struct mf_field *
 mf_from_nxm_header(uint32_t header)
 {
-    if (hmap_is_empty(&all_fields)) {
-        nxm_init();
-    }
+    nxm_init();
     return mf_from_nxm_header__(header);
 }
 
@@ -701,8 +706,8 @@ mf_is_all_wild(const struct mf_field *mf, const struct flow_wildcards *wc)
         return !wc->masks.in_port.ofp_port;
     case MFF_SKB_PRIORITY:
         return !wc->masks.skb_priority;
-    case MFF_SKB_MARK:
-        return !wc->masks.skb_mark;
+    case MFF_PKT_MARK:
+        return !wc->masks.pkt_mark;
     CASE_MFF_REGS:
         return !wc->masks.regs[mf->id - MFF_REG0];
 
@@ -907,7 +912,7 @@ mf_is_value_valid(const struct mf_field *mf, const union mf_value *value)
     case MFF_METADATA:
     case MFF_IN_PORT:
     case MFF_SKB_PRIORITY:
-    case MFF_SKB_MARK:
+    case MFF_PKT_MARK:
     CASE_MFF_REGS:
     case MFF_ETH_SRC:
     case MFF_ETH_DST:
@@ -1021,8 +1026,8 @@ mf_get_value(const struct mf_field *mf, const struct flow *flow,
         value->be32 = htonl(flow->skb_priority);
         break;
 
-    case MFF_SKB_MARK:
-        value->be32 = htonl(flow->skb_mark);
+    case MFF_PKT_MARK:
+        value->be32 = htonl(flow->pkt_mark);
         break;
 
     CASE_MFF_REGS:
@@ -1211,8 +1216,8 @@ mf_set_value(const struct mf_field *mf,
         match_set_skb_priority(match, ntohl(value->be32));
         break;
 
-    case MFF_SKB_MARK:
-        match_set_skb_mark(match, ntohl(value->be32));
+    case MFF_PKT_MARK:
+        match_set_pkt_mark(match, ntohl(value->be32));
         break;
 
     CASE_MFF_REGS:
@@ -1400,8 +1405,8 @@ mf_set_flow_value(const struct mf_field *mf,
         flow->skb_priority = ntohl(value->be32);
         break;
 
-    case MFF_SKB_MARK:
-        flow->skb_mark = ntohl(value->be32);
+    case MFF_PKT_MARK:
+        flow->pkt_mark = ntohl(value->be32);
         break;
 
     CASE_MFF_REGS:
@@ -1602,9 +1607,9 @@ mf_set_wild(const struct mf_field *mf, struct match *match)
         match->wc.masks.skb_priority = 0;
         break;
 
-    case MFF_SKB_MARK:
-        match->flow.skb_mark = 0;
-        match->wc.masks.skb_mark = 0;
+    case MFF_PKT_MARK:
+        match->flow.pkt_mark = 0;
+        match->wc.masks.pkt_mark = 0;
         break;
 
     CASE_MFF_REGS:
@@ -1775,7 +1780,6 @@ mf_set(const struct mf_field *mf,
     switch (mf->id) {
     case MFF_IN_PORT:
     case MFF_IN_PORT_OXM:
-    case MFF_SKB_MARK:
     case MFF_SKB_PRIORITY:
     case MFF_ETH_TYPE:
     case MFF_DL_VLAN:
@@ -1824,6 +1828,11 @@ mf_set(const struct mf_field *mf,
                              ntohl(value->be32), ntohl(mask->be32));
         break;
 
+    case MFF_PKT_MARK:
+        match_set_pkt_mark_masked(match, ntohl(value->be32),
+                                  ntohl(mask->be32));
+        break;
+
     case MFF_ETH_DST:
         match_set_dl_dst_masked(match, value->mac, mask->mac);
         break;
@@ -1980,7 +1989,7 @@ mf_random_value(const struct mf_field *mf, union mf_value *value)
     case MFF_TUN_FLAGS:
     case MFF_METADATA:
     case MFF_IN_PORT:
-    case MFF_SKB_MARK:
+    case MFF_PKT_MARK:
     case MFF_SKB_PRIORITY:
     CASE_MFF_REGS:
     case MFF_ETH_SRC:
@@ -2112,20 +2121,25 @@ mf_from_ethernet_string(const struct mf_field *mf, const char *s,
                         uint8_t mac[ETH_ADDR_LEN],
                         uint8_t mask[ETH_ADDR_LEN])
 {
-    ovs_assert(mf->n_bytes == ETH_ADDR_LEN);
+    int n;
 
-    switch (sscanf(s, ETH_ADDR_SCAN_FMT"/"ETH_ADDR_SCAN_FMT,
-                   ETH_ADDR_SCAN_ARGS(mac), ETH_ADDR_SCAN_ARGS(mask))){
-    case ETH_ADDR_SCAN_COUNT * 2:
-        return NULL;
+    ovs_assert(mf->n_bytes == ETH_ADDR_LEN);
 
-    case ETH_ADDR_SCAN_COUNT:
+    n = -1;
+    if (sscanf(s, ETH_ADDR_SCAN_FMT"%n", ETH_ADDR_SCAN_ARGS(mac), &n) > 0
+        && n == strlen(s)) {
         memset(mask, 0xff, ETH_ADDR_LEN);
         return NULL;
+    }
 
-    default:
-        return xasprintf("%s: invalid Ethernet address", s);
+    n = -1;
+    if (sscanf(s, ETH_ADDR_SCAN_FMT"/"ETH_ADDR_SCAN_FMT"%n",
+               ETH_ADDR_SCAN_ARGS(mac), ETH_ADDR_SCAN_ARGS(mask), &n) > 0
+        && n == strlen(s)) {
+        return NULL;
     }
+
+    return xasprintf("%s: invalid Ethernet address", s);
 }
 
 static char *