datapath: Validate ToS when flow is added.
authorJesse Gross <jesse@nicira.com>
Fri, 12 Mar 2010 21:05:25 +0000 (16:05 -0500)
committerJesse Gross <jesse@nicira.com>
Mon, 15 Mar 2010 19:44:41 +0000 (15:44 -0400)
Check that the ToS is valid when the flow is added, not every time
it is used.

datapath/actions.c
datapath/datapath.c
datapath/flow.c
lib/dpif-netdev.c

index b6d5488..4767862 100644 (file)
@@ -292,7 +292,7 @@ static struct sk_buff *set_nw_tos(struct sk_buff *skb,
                u8 new;
 
                /* Set the DSCP bits and preserve the ECN bits. */
-               new = (a->nw_tos & ~INET_ECN_MASK) | (nh->tos & INET_ECN_MASK);
+               new = a->nw_tos | (nh->tos & INET_ECN_MASK);
                update_csum(&nh->check, skb, htons((uint16_t)old),
                                htons((uint16_t)new), 0);
                *f = new;
index f8a2aa3..6365f94 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/rculist.h>
 #include <linux/workqueue.h>
 #include <linux/dmi.h>
+#include <net/inet_ecn.h>
 #include <net/llc.h>
 
 #include "openvswitch/datapath-protocol.h"
@@ -930,6 +931,11 @@ static int validate_actions(const struct sw_flow_actions *actions)
                                return -EINVAL;
                        break;
 
+               case ODPAT_SET_NW_TOS:
+                       if (a->nw_tos.nw_tos & INET_ECN_MASK)
+                               return -EINVAL;
+                       break;
+
                default:
                        if (a->type >= ODPAT_N_ACTIONS)
                                return -EOPNOTSUPP;
index 3b95e3b..9a94d0b 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/tcp.h>
 #include <linux/udp.h>
 #include <linux/icmp.h>
+#include <net/inet_ecn.h>
 #include <net/ip.h>
 
 #include "compat.h"
index e19cb34..365b78a 100644 (file)
@@ -720,58 +720,64 @@ static int
 dpif_netdev_validate_actions(const union odp_action *actions, int n_actions,
                              bool *mutates)
 {
-       unsigned int i;
+    unsigned int i;
 
     *mutates = false;
-       for (i = 0; i < n_actions; i++) {
-               const union odp_action *a = &actions[i];
-               switch (a->type) {
-               case ODPAT_OUTPUT:
-                       if (a->output.port >= MAX_PORTS) {
-                               return EINVAL;
+    for (i = 0; i < n_actions; i++) {
+        const union odp_action *a = &actions[i];
+        switch (a->type) {
+        case ODPAT_OUTPUT:
+            if (a->output.port >= MAX_PORTS) {
+                return EINVAL;
             }
-                       break;
+            break;
 
-               case ODPAT_OUTPUT_GROUP:
+        case ODPAT_OUTPUT_GROUP:
             *mutates = true;
-                       if (a->output_group.group >= N_GROUPS) {
-                               return EINVAL;
+            if (a->output_group.group >= N_GROUPS) {
+                return EINVAL;
             }
-                       break;
+            break;
 
         case ODPAT_CONTROLLER:
             break;
 
-               case ODPAT_SET_VLAN_VID:
+        case ODPAT_SET_VLAN_VID:
             *mutates = true;
-                       if (a->vlan_vid.vlan_vid & htons(~VLAN_VID_MASK)) {
-                               return EINVAL;
+            if (a->vlan_vid.vlan_vid & htons(~VLAN_VID_MASK)) {
+                return EINVAL;
             }
-                       break;
+            break;
 
-               case ODPAT_SET_VLAN_PCP:
+        case ODPAT_SET_VLAN_PCP:
             *mutates = true;
-                       if (a->vlan_pcp.vlan_pcp & ~(VLAN_PCP_MASK >> VLAN_PCP_SHIFT)) {
-                               return EINVAL;
+            if (a->vlan_pcp.vlan_pcp & ~(VLAN_PCP_MASK >> VLAN_PCP_SHIFT)) {
+                return EINVAL;
             }
-                       break;
+            break;
+
+        case ODPAT_SET_NW_TOS:
+            *mutates = true;
+            if (a->nw_tos.nw_tos & IP_ECN_MASK) {
+                return EINVAL;
+            }
+            break;
 
         case ODPAT_STRIP_VLAN:
         case ODPAT_SET_DL_SRC:
         case ODPAT_SET_DL_DST:
         case ODPAT_SET_NW_SRC:
         case ODPAT_SET_NW_DST:
-        case ODPAT_SET_NW_TOS:
         case ODPAT_SET_TP_SRC:
         case ODPAT_SET_TP_DST:
             *mutates = true;
             break;
 
-               default:
+        default:
             return EOPNOTSUPP;
-               }
-       }
-       return 0;
+        }
+    }
+    return 0;
 }
 
 static int
@@ -1189,7 +1195,7 @@ dp_netdev_set_nw_tos(struct ofpbuf *packet, flow_t *key,
         uint8_t *field = &nh->ip_tos;
 
         /* Set the DSCP bits and preserve the ECN bits. */
-        uint8_t new = (a->nw_tos & IP_DSCP_MASK) | (nh->ip_tos & IP_ECN_MASK);
+        uint8_t new = a->nw_tos | (nh->ip_tos & IP_ECN_MASK);
 
         nh->ip_csum = recalc_csum16(nh->ip_csum, htons((uint16_t)*field),
                 htons((uint16_t)a->nw_tos));