summary refs log tree commit diff
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2012-03-07 22:49:01 -0800
committerDavid S. Miller <davem@davemloft.net>2012-03-07 22:49:01 -0800
commit9259c483a34a4efbaf60583af3719bed28a3fe45 (patch)
tree5e3dbac4aeabd5bf83970cb8a2b642c2009a34d4 /net
parentd47775c4a7a40ecd048400cf770504ad1f2cd3df (diff)
parent81e5d41d7ed4f6c61ba3d2414f4f9ddf6d934ebb (diff)
downloadlinux-9259c483a34a4efbaf60583af3719bed28a3fe45.tar.gz
Merge branch 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jesse/openvswitch
Diffstat (limited to 'net')
-rw-r--r--net/openvswitch/actions.c44
-rw-r--r--net/openvswitch/datapath.c3
2 files changed, 35 insertions, 12 deletions
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index 2725d1bdf291..48badffaafc1 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007-2011 Nicira Networks.
+ * Copyright (c) 2007-2012 Nicira Networks.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of version 2 of the GNU General Public
@@ -145,9 +145,16 @@ static void set_ip_addr(struct sk_buff *skb, struct iphdr *nh,
 			inet_proto_csum_replace4(&tcp_hdr(skb)->check, skb,
 						 *addr, new_addr, 1);
 	} else if (nh->protocol == IPPROTO_UDP) {
-		if (likely(transport_len >= sizeof(struct udphdr)))
-			inet_proto_csum_replace4(&udp_hdr(skb)->check, skb,
-						 *addr, new_addr, 1);
+		if (likely(transport_len >= sizeof(struct udphdr))) {
+			struct udphdr *uh = udp_hdr(skb);
+
+			if (uh->check || skb->ip_summed == CHECKSUM_PARTIAL) {
+				inet_proto_csum_replace4(&uh->check, skb,
+							 *addr, new_addr, 1);
+				if (!uh->check)
+					uh->check = CSUM_MANGLED_0;
+			}
+		}
 	}
 
 	csum_replace4(&nh->check, *addr, new_addr);
@@ -197,8 +204,22 @@ static void set_tp_port(struct sk_buff *skb, __be16 *port,
 	skb->rxhash = 0;
 }
 
-static int set_udp_port(struct sk_buff *skb,
-			const struct ovs_key_udp *udp_port_key)
+static void set_udp_port(struct sk_buff *skb, __be16 *port, __be16 new_port)
+{
+	struct udphdr *uh = udp_hdr(skb);
+
+	if (uh->check && skb->ip_summed != CHECKSUM_PARTIAL) {
+		set_tp_port(skb, port, new_port, &uh->check);
+
+		if (!uh->check)
+			uh->check = CSUM_MANGLED_0;
+	} else {
+		*port = new_port;
+		skb->rxhash = 0;
+	}
+}
+
+static int set_udp(struct sk_buff *skb, const struct ovs_key_udp *udp_port_key)
 {
 	struct udphdr *uh;
 	int err;
@@ -210,16 +231,15 @@ static int set_udp_port(struct sk_buff *skb,
 
 	uh = udp_hdr(skb);
 	if (udp_port_key->udp_src != uh->source)
-		set_tp_port(skb, &uh->source, udp_port_key->udp_src, &uh->check);
+		set_udp_port(skb, &uh->source, udp_port_key->udp_src);
 
 	if (udp_port_key->udp_dst != uh->dest)
-		set_tp_port(skb, &uh->dest, udp_port_key->udp_dst, &uh->check);
+		set_udp_port(skb, &uh->dest, udp_port_key->udp_dst);
 
 	return 0;
 }
 
-static int set_tcp_port(struct sk_buff *skb,
-			const struct ovs_key_tcp *tcp_port_key)
+static int set_tcp(struct sk_buff *skb, const struct ovs_key_tcp *tcp_port_key)
 {
 	struct tcphdr *th;
 	int err;
@@ -328,11 +348,11 @@ static int execute_set_action(struct sk_buff *skb,
 		break;
 
 	case OVS_KEY_ATTR_TCP:
-		err = set_tcp_port(skb, nla_data(nested_attr));
+		err = set_tcp(skb, nla_data(nested_attr));
 		break;
 
 	case OVS_KEY_ATTR_UDP:
-		err = set_udp_port(skb, nla_data(nested_attr));
+		err = set_udp(skb, nla_data(nested_attr));
 		break;
 	}
 
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index ce64c18b8c79..2c030505b335 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -1521,6 +1521,9 @@ static struct vport *lookup_vport(struct ovs_header *ovs_header,
 		vport = ovs_vport_locate(nla_data(a[OVS_VPORT_ATTR_NAME]));
 		if (!vport)
 			return ERR_PTR(-ENODEV);
+		if (ovs_header->dp_ifindex &&
+		    ovs_header->dp_ifindex != get_dpifindex(vport->dp))
+			return ERR_PTR(-ENODEV);
 		return vport;
 	} else if (a[OVS_VPORT_ATTR_PORT_NO]) {
 		u32 port_no = nla_get_u32(a[OVS_VPORT_ATTR_PORT_NO]);