datapath: Simplify ODPAT_SET_DL_TCI action.
authorBen Pfaff <blp@nicira.com>
Mon, 18 Oct 2010 18:18:10 +0000 (11:18 -0700)
committerBen Pfaff <blp@nicira.com>
Mon, 18 Oct 2010 18:18:23 +0000 (11:18 -0700)
There's no need to have a mask in this action, because both parts of the
TCI are part of the flow structure.

Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jesse Gross <jesse@nicira.com>
datapath/actions.c
datapath/datapath.c
include/openvswitch/datapath-protocol.h
lib/dpif-netdev.c
lib/odp-util.c
lib/ofp-util.c
ofproto/ofproto-sflow.c
ofproto/ofproto.c
vswitchd/bridge.c

index 5365278ab8266cf4b49a383a887745b9e8a2f0a1..5904c8312d4116464bb3c528f4d28c154e1acdf0 100644 (file)
@@ -74,7 +74,6 @@ static struct sk_buff *modify_vlan_tci(struct datapath *dp, struct sk_buff *skb,
                                       const struct odp_flow_key *key,
                                       const union odp_action *a, int n_actions)
 {
-       __be16 mask = a->dl_tci.mask;
        __be16 tci = a->dl_tci.tci;
 
        skb = make_writable(skb, VLAN_HLEN);
@@ -92,7 +91,7 @@ static struct sk_buff *modify_vlan_tci(struct datapath *dp, struct sk_buff *skb,
                vh = vlan_eth_hdr(skb);
                old_tci = vh->h_vlan_TCI;
 
-               vh->h_vlan_TCI = (vh->h_vlan_TCI & ~mask) | tci;
+               vh->h_vlan_TCI = tci;
 
                if (OVS_CB(skb)->ip_summed == OVS_CSUM_COMPLETE) {
                        __be16 diff[] = { ~old_tci, vh->h_vlan_TCI };
index 9eeb28cd1d12c04be4253c94e1f575ea6f52535e..b41110dbcb3fd978db959f3104a48a7cc972869e 100644 (file)
@@ -904,7 +904,6 @@ static int validate_actions(const struct sw_flow_actions *actions)
 
        for (i = 0; i < actions->n_actions; i++) {
                const union odp_action *a = &actions->actions[i];
-               __be16 mask;
 
                switch (a->type) {
                case ODPAT_CONTROLLER:
@@ -928,12 +927,7 @@ static int validate_actions(const struct sw_flow_actions *actions)
                        break;
 
                case ODPAT_SET_DL_TCI:
-                       mask = a->dl_tci.mask;
-                       if (mask != htons(VLAN_VID_MASK) &&
-                           mask != htons(VLAN_PCP_MASK) &&
-                           mask != htons(VLAN_VID_MASK | VLAN_PCP_MASK))
-                               return -EINVAL;
-                       if (a->dl_tci.tci & ~mask)
+                       if (a->dl_tci.tci & htons(VLAN_CFI_MASK))
                                return -EINVAL;
                        break;
 
index 1aa8066cade4487a054abd885bf25540d31e8182..b0e9dfbb3cf44988291f96435a2251c6918f1714 100644 (file)
@@ -258,7 +258,7 @@ struct odp_flowvec {
 /* Action types. */
 #define ODPAT_OUTPUT            0    /* Output to switch port. */
 #define ODPAT_CONTROLLER        2    /* Send copy to controller. */
-#define ODPAT_SET_DL_TCI        3    /* Set the 802.1q VLAN VID and/or PCP. */
+#define ODPAT_SET_DL_TCI        3    /* Set the 802.1q TCI value. */
 #define ODPAT_STRIP_VLAN        5    /* Strip the 802.1q header. */
 #define ODPAT_SET_DL_SRC        6    /* Ethernet source address. */
 #define ODPAT_SET_DL_DST        7    /* Ethernet destination address. */
@@ -295,10 +295,8 @@ struct odp_action_tunnel {
 /* Action structure for ODPAT_SET_DL_TCI. */
 struct odp_action_dl_tci {
     uint16_t type;              /* ODPAT_SET_DL_TCI. */
-    ovs_be16 tci;               /* New TCI.  Bits not in mask must be zero. */
-    ovs_be16 mask;              /* 0x0fff to set VID, 0xe000 to set PCP,
-                                 * or 0xefff to set both. */
-    uint16_t reserved;
+    ovs_be16 tci;               /* New TCI.  CFI bit must be zero. */
+    uint32_t reserved;
 };
 
 /* Action structure for ODPAT_SET_DL_SRC/DST. */
index aa4fdf830bf8cc7c14a3cf52c793c5553d26a4f6..3df6598d25ae3fbba0015fd3e1bb5ebf004d3daf 100644 (file)
@@ -667,12 +667,7 @@ dpif_netdev_validate_actions(const union odp_action *actions, int n_actions,
 
         case ODPAT_SET_DL_TCI:
             *mutates = true;
-            if (a->dl_tci.mask != htons(VLAN_VID_MASK)
-                && a->dl_tci.mask != htons(VLAN_PCP_MASK)
-                && a->dl_tci.mask != htons(VLAN_VID_MASK | VLAN_PCP_MASK)) {
-                return EINVAL;
-            }
-            if (a->dl_tci.tci & ~a->dl_tci.mask){
+            if (a->dl_tci.tci & htons(VLAN_CFI)) {
                 return EINVAL;
             }
             break;
@@ -1011,16 +1006,12 @@ dp_netdev_wait(void)
 }
 
 
-/* Modify the TCI field of 'packet'.  If a VLAN tag is not present, one is
- * added with the TCI field set to 'a->tci'.  If a VLAN tag is present, then
- * 'a->mask' bits are cleared before 'a->tci' is logically OR'd into the TCI
- * field.
- *
- * Note that the function does not ensure that 'a->tci' does not affect bits
- * outside of 'a->mask'.
+/* Modify the TCI field of 'packet'.  If a VLAN tag is present, its TCI field
+ * is replaced by 'tci'.  If a VLAN tag is not present, one is added with the
+ * TCI field set to 'tci'.
  */
 static void
-dp_netdev_set_dl_tci(struct ofpbuf *packet, const struct odp_action_dl_tci *a)
+dp_netdev_set_dl_tci(struct ofpbuf *packet, uint16_t tci)
 {
     struct vlan_eth_header *veh;
     struct eth_header *eh;
@@ -1028,16 +1019,15 @@ dp_netdev_set_dl_tci(struct ofpbuf *packet, const struct odp_action_dl_tci *a)
     eh = packet->l2;
     if (packet->size >= sizeof(struct vlan_eth_header)
         && eh->eth_type == htons(ETH_TYPE_VLAN)) {
-        /* Clear 'mask' bits, but maintain other TCI bits. */
         veh = packet->l2;
-        veh->veth_tci = (veh->veth_tci & ~a->mask) | a->tci;
+        veh->veth_tci = tci;
     } else {
         /* Insert new 802.1Q header. */
         struct vlan_eth_header tmp;
         memcpy(tmp.veth_dst, eh->eth_dst, ETH_ADDR_LEN);
         memcpy(tmp.veth_src, eh->eth_src, ETH_ADDR_LEN);
         tmp.veth_type = htons(ETH_TYPE_VLAN);
-        tmp.veth_tci = htons(a->tci);
+        tmp.veth_tci = tci;
         tmp.veth_next_type = eh->eth_type;
 
         veh = ofpbuf_push_uninit(packet, VLAN_HEADER_LEN);
@@ -1235,7 +1225,7 @@ dp_netdev_execute_actions(struct dp_netdev *dp,
             break;
 
         case ODPAT_SET_DL_TCI:
-            dp_netdev_set_dl_tci(packet, &a->dl_tci);
+            dp_netdev_set_dl_tci(packet, a->dl_tci.tci);
             break;
 
         case ODPAT_STRIP_VLAN:
index 130d55de77f2d99930cb76afd1d3cf5d544878d2..511ec3a99f8b403273d0b7a25cebb4817f862c1b 100644 (file)
@@ -71,26 +71,10 @@ format_odp_action(struct ds *ds, const union odp_action *a)
     case ODPAT_SET_TUNNEL:
         ds_put_format(ds, "set_tunnel(0x%08"PRIx32")", ntohl(a->tunnel.tun_id));
         break;
-    case ODPAT_SET_DL_TCI: {
-        int vid = vlan_tci_to_vid(a->dl_tci.tci);
-        int pcp = vlan_tci_to_pcp(a->dl_tci.tci);
-
-        switch (ntohs(a->dl_tci.mask)) {
-        case VLAN_VID_MASK:
-            ds_put_format(ds, "set_tci(vlan=%d)", vid);
-            break;
-        case VLAN_PCP_MASK:
-            ds_put_format(ds, "set_tci(pcp=%d)", pcp);
-            break;
-        case VLAN_VID_MASK | VLAN_PCP_MASK:
-            ds_put_format(ds, "set_tci(vlan=%d,pcp=%d)", vid, pcp);
-            break;
-        default:
-            ds_put_format(ds, "set_tci(tci=%04"PRIx16",mask=%04"PRIx16")",
-                          ntohs(a->dl_tci.tci), ntohs(a->dl_tci.mask));
-            break;
-        }
-    }
+    case ODPAT_SET_DL_TCI:
+        ds_put_format(ds, "set_tci(vid=%"PRIu16",pcp=%d)",
+                      vlan_tci_to_vid(a->dl_tci.tci),
+                      vlan_tci_to_pcp(a->dl_tci.tci));
         break;
     case ODPAT_STRIP_VLAN:
         ds_put_format(ds, "strip_vlan");
index d8d3ced58cebd15ab632e4ee58dd482284c63cb6..99e5943c562e8ee67b0bf649eec41acad4a2c48d 100644 (file)
@@ -587,7 +587,25 @@ check_action(const union ofp_action *a, unsigned int len, int max_ports)
         return check_output_port(ntohs(a->output.port), max_ports);
 
     case OFPAT_SET_VLAN_VID:
+        error = check_action_exact_len(a, len, 8);
+        if (error) {
+            return error;
+        }
+        if (a->vlan_vid.vlan_vid & ~htons(0xfff)) {
+            return ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT);
+        }
+        return 0;
+
     case OFPAT_SET_VLAN_PCP:
+        error = check_action_exact_len(a, len, 8);
+        if (error) {
+            return error;
+        }
+        if (a->vlan_vid.vlan_vid & ~7) {
+            return ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT);
+        }
+        return 0;
+
     case OFPAT_STRIP_VLAN:
     case OFPAT_SET_NW_SRC:
     case OFPAT_SET_NW_DST:
index de9bf8987af2e3307f057d38aebd7bedc5e3054f..784e5528f85472abea96585eeba427c08ff3553f 100644 (file)
@@ -567,6 +567,7 @@ ofproto_sflow_received(struct ofproto_sflow *os, struct odp_msg *msg)
     n_outputs = 0;
     for (i = 0; i < n_actions; i++) {
         const union odp_action *a = &actions[i];
+        uint16_t tci;
 
         switch (a->type) {
         case ODPAT_OUTPUT:
@@ -575,12 +576,9 @@ ofproto_sflow_received(struct ofproto_sflow *os, struct odp_msg *msg)
             break;
 
         case ODPAT_SET_DL_TCI:
-            if (a->dl_tci.mask & htons(VLAN_VID_MASK)) {
-                switchElem.flowType.sw.dst_vlan = vlan_tci_to_vid(a->dl_tci.tci);
-            }
-            if (a->dl_tci.mask & htons(VLAN_PCP_MASK)) {
-                switchElem.flowType.sw.dst_priority = vlan_tci_to_pcp(a->dl_tci.tci);
-            }
+            tci = a->dl_tci.tci;
+            switchElem.flowType.sw.dst_vlan = vlan_tci_to_vid(tci);
+            switchElem.flowType.sw.dst_priority = vlan_tci_to_pcp(tci);
             break;
 
         default:
index bb2bf5a4ae2873c3447d5b949c4334f28336af14..ab5d476b6cd0a99562053ea37a18dc527f297e6c 100644 (file)
@@ -2768,16 +2768,15 @@ do_xlate_actions(const union ofp_action *in, size_t n_in,
 
         case OFPAT_SET_VLAN_VID:
             oa = odp_actions_add(ctx->out, ODPAT_SET_DL_TCI);
-            oa->dl_tci.tci = ia->vlan_vid.vlan_vid & htons(VLAN_VID_MASK);
-            oa->dl_tci.mask = htons(VLAN_VID_MASK);
+            oa->dl_tci.tci = ia->vlan_vid.vlan_vid;
+            oa->dl_tci.tci |= htons(ctx->flow.dl_vlan_pcp << VLAN_PCP_SHIFT);
             ctx->flow.dl_vlan = ia->vlan_vid.vlan_vid;
             break;
 
         case OFPAT_SET_VLAN_PCP:
             oa = odp_actions_add(ctx->out, ODPAT_SET_DL_TCI);
-            oa->dl_tci.tci = htons((ia->vlan_pcp.vlan_pcp << VLAN_PCP_SHIFT)
-                                   & VLAN_PCP_MASK);
-            oa->dl_tci.mask = htons(VLAN_PCP_MASK);
+            oa->dl_tci.tci = htons(ia->vlan_pcp.vlan_pcp << VLAN_PCP_SHIFT);
+            oa->dl_tci.tci |= ctx->flow.dl_vlan;
             ctx->flow.dl_vlan_pcp = ia->vlan_pcp.vlan_pcp;
             break;
 
index 4a7f90bfa6b9aa3b12ac5ffcbb30a7e56f13f72b..75cce3c8da315f1889e4bf641d6222b5051500a1 100644 (file)
@@ -2330,7 +2330,7 @@ compose_actions(struct bridge *br, const struct flow *flow, uint16_t vlan,
             } else {
                 a = odp_actions_add(actions, ODPAT_SET_DL_TCI);
                 a->dl_tci.tci = htons(p->vlan & VLAN_VID_MASK);
-                a->dl_tci.mask = htons(VLAN_VID_MASK);
+                a->dl_tci.tci |= htons(flow->dl_vlan_pcp << VLAN_PCP_SHIFT);
             }
             cur_vlan = p->vlan;
         }