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