Allow setting of fields without matching on the same fields.  Field
existence check is done on set action execution time instead, using
the extracted flow key.

Signed-off-by: Jarno Rajahalme <jrajaha...@nicira.com>
---
 datapath/actions.c      |   21 ++++++++++++++++++++-
 datapath/flow_netlink.c |   46 +++++++++++++++-------------------------------
 2 files changed, 35 insertions(+), 32 deletions(-)

diff --git a/datapath/actions.c b/datapath/actions.c
index 243b672..3b2de3f 100644
--- a/datapath/actions.c
+++ b/datapath/actions.c
@@ -470,6 +470,10 @@ static int set_ipv4(struct sk_buff *skb, const struct 
ovs_key_ipv4 *key,
        __be32 new_addr;
        int err;
 
+       /* eth.type is checked at flow install time already. */
+       if (!OVS_CB(skb)->pkt_key->ip.proto)
+               return -EINVAL;
+
        err = make_writable(skb, skb_network_offset(skb) +
                                 sizeof(struct iphdr));
        if (unlikely(err))
@@ -519,6 +523,10 @@ static int set_ipv6(struct sk_buff *skb, const struct 
ovs_key_ipv6 *key,
        struct ipv6hdr *nh;
        int err;
 
+       /* eth.type is checked at flow install time already. */
+       if (!OVS_CB(skb)->pkt_key->ip.proto)
+               return -EINVAL;
+
        err = make_writable(skb, skb_network_offset(skb) +
                            sizeof(struct ipv6hdr));
        if (unlikely(err))
@@ -593,6 +601,10 @@ static int set_udp(struct sk_buff *skb, const struct 
ovs_key_udp *key,
        __be16 src, dst;
        int err;
 
+       /* Must have extracted ports. */
+       if (!OVS_CB(skb)->pkt_key->tp.src && !OVS_CB(skb)->pkt_key->tp.dst)
+               return -EINVAL;
+
        err = make_writable(skb, skb_transport_offset(skb) +
                                 sizeof(struct udphdr));
        if (unlikely(err))
@@ -634,6 +646,10 @@ static int set_tcp(struct sk_buff *skb, const struct 
ovs_key_tcp *key,
        __be16 src, dst;
        int err;
 
+       /* Must have extracted ports. */
+       if (!OVS_CB(skb)->pkt_key->tp.src && !OVS_CB(skb)->pkt_key->tp.dst)
+               return -EINVAL;
+
        err = make_writable(skb, skb_transport_offset(skb) +
                                 sizeof(struct tcphdr));
        if (unlikely(err))
@@ -664,6 +680,10 @@ static int set_sctp(struct sk_buff *skb, const struct 
ovs_key_sctp *key,
        __le32 old_correct_csum, new_csum, old_csum;
        int err;
 
+       /* Must have extracted ports. */
+       if (!OVS_CB(skb)->pkt_key->tp.src && !OVS_CB(skb)->pkt_key->tp.dst)
+               return -EINVAL;
+
        err = make_writable(skb, sctphoff + sizeof(struct sctphdr));
        if (unlikely(err))
                return err;
@@ -821,7 +841,6 @@ static int execute_set_action(struct sk_buff *skb, const 
struct nlattr *a)
        }
 
        return -EINVAL;
-
 }
 
 /* Mask is at the midpoint of the data. */
diff --git a/datapath/flow_netlink.c b/datapath/flow_netlink.c
index ec32a00..09aaf41 100644
--- a/datapath/flow_netlink.c
+++ b/datapath/flow_netlink.c
@@ -1511,16 +1511,6 @@ static int validate_and_copy_sample(const struct nlattr 
*attr,
        return 0;
 }
 
-static int validate_tp_port(const struct sw_flow_key *flow_key,
-                           __be16 eth_type)
-{
-       if ((eth_type == htons(ETH_P_IP) || eth_type == htons(ETH_P_IPV6)) &&
-           (flow_key->tp.src || flow_key->tp.dst))
-               return 0;
-
-       return -EINVAL;
-}
-
 void ovs_match_init(struct sw_flow_match *match,
                    struct sw_flow_key *key,
                    struct sw_flow_mask *mask)
@@ -1666,9 +1656,6 @@ static int validate_set(const struct nlattr *a,
                if (eth_type != htons(ETH_P_IP))
                        return -EINVAL;
 
-               if (!flow_key->ip.proto)
-                       return -EINVAL;
-
                ipv4_key = nla_data(ovs_key);
 
                if (masked) {
@@ -1690,9 +1677,6 @@ static int validate_set(const struct nlattr *a,
                if (eth_type != htons(ETH_P_IPV6))
                        return -EINVAL;
 
-               if (!flow_key->ip.proto)
-                       return -EINVAL;
-
                ipv6_key = nla_data(ovs_key);
                if (masked) {
                        const struct ovs_key_ipv6 *mask = ipv6_key + 1;
@@ -1717,35 +1701,35 @@ static int validate_set(const struct nlattr *a,
                break;
 
        case OVS_KEY_ATTR_TCP:
-               if (flow_key->ip.proto != IPPROTO_TCP)
+               if (eth_type != htons(ETH_P_IP) &&
+                   eth_type != htons(ETH_P_IPV6))
                        return -EINVAL;
 
-               err = validate_tp_port(flow_key, eth_type);
-               if (err)
-                       return err;
+               if (flow_key->ip.proto != IPPROTO_TCP)
+                       return -EINVAL;
                break;
 
        case OVS_KEY_ATTR_UDP:
-               if (flow_key->ip.proto != IPPROTO_UDP)
+               if (eth_type != htons(ETH_P_IP) &&
+                   eth_type != htons(ETH_P_IPV6))
                        return -EINVAL;
 
-               err = validate_tp_port(flow_key, eth_type);
-               if (err)
-                       return err;
-               break;
-
-       case OVS_KEY_ATTR_MPLS:
-               if (!eth_p_mpls(eth_type))
+               if (flow_key->ip.proto != IPPROTO_UDP)
                        return -EINVAL;
                break;
 
        case OVS_KEY_ATTR_SCTP:
+               if (eth_type != htons(ETH_P_IP) &&
+                   eth_type != htons(ETH_P_IPV6))
+                       return -EINVAL;
+
                if (flow_key->ip.proto != IPPROTO_SCTP)
                        return -EINVAL;
+               break;
 
-               err = validate_tp_port(flow_key, eth_type);
-               if (err)
-                       return err;
+       case OVS_KEY_ATTR_MPLS:
+               if (!eth_p_mpls(eth_type))
+                       return -EINVAL;
                break;
 
        default:
-- 
1.7.10.4

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to