aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2014-11-16 14:59:01 -0500
committerDavid S. Miller <davem@davemloft.net>2014-11-16 14:59:01 -0500
commitc6ab766e812570c506a4dc2215dc0da3229cfd67 (patch)
tree0951f32cc28172e0b0ea7ec10f136092ae609779
parent52cff74eef5dd7bdab759300e7d1ca36eba18254 (diff)
parentfecaef85f7188ad1822210e2c7a7625c9a32a8e4 (diff)
Merge branch 'net_ovs' of git://git.kernel.org/pub/scm/linux/kernel/git/pshelar/openvswitch
Pravin B Shelar says: ==================== Open vSwitch Following fixes are accumulated in ovs-repo. Three of them are related to protocol processing, one is related to memory leak in case of error and one is to fix race. Patch "Validate IPv6 flow key and mask values" has conflicts with net-next, Let me know if you want me to send the patch for net-next. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/openvswitch/actions.c10
-rw-r--r--net/openvswitch/datapath.c14
-rw-r--r--net/openvswitch/flow_netlink.c9
3 files changed, 21 insertions, 12 deletions
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index 006886dbee36..8c4229b11c34 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -246,11 +246,11 @@ static void update_ipv6_checksum(struct sk_buff *skb, u8 l4_proto,
246{ 246{
247 int transport_len = skb->len - skb_transport_offset(skb); 247 int transport_len = skb->len - skb_transport_offset(skb);
248 248
249 if (l4_proto == IPPROTO_TCP) { 249 if (l4_proto == NEXTHDR_TCP) {
250 if (likely(transport_len >= sizeof(struct tcphdr))) 250 if (likely(transport_len >= sizeof(struct tcphdr)))
251 inet_proto_csum_replace16(&tcp_hdr(skb)->check, skb, 251 inet_proto_csum_replace16(&tcp_hdr(skb)->check, skb,
252 addr, new_addr, 1); 252 addr, new_addr, 1);
253 } else if (l4_proto == IPPROTO_UDP) { 253 } else if (l4_proto == NEXTHDR_UDP) {
254 if (likely(transport_len >= sizeof(struct udphdr))) { 254 if (likely(transport_len >= sizeof(struct udphdr))) {
255 struct udphdr *uh = udp_hdr(skb); 255 struct udphdr *uh = udp_hdr(skb);
256 256
@@ -261,6 +261,10 @@ static void update_ipv6_checksum(struct sk_buff *skb, u8 l4_proto,
261 uh->check = CSUM_MANGLED_0; 261 uh->check = CSUM_MANGLED_0;
262 } 262 }
263 } 263 }
264 } else if (l4_proto == NEXTHDR_ICMP) {
265 if (likely(transport_len >= sizeof(struct icmp6hdr)))
266 inet_proto_csum_replace16(&icmp6_hdr(skb)->icmp6_cksum,
267 skb, addr, new_addr, 1);
264 } 268 }
265} 269}
266 270
@@ -722,8 +726,6 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
722 726
723 case OVS_ACTION_ATTR_SAMPLE: 727 case OVS_ACTION_ATTR_SAMPLE:
724 err = sample(dp, skb, key, a); 728 err = sample(dp, skb, key, a);
725 if (unlikely(err)) /* skb already freed. */
726 return err;
727 break; 729 break;
728 } 730 }
729 731
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index e6d7255183eb..f9e556b56086 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -1265,7 +1265,7 @@ static size_t ovs_dp_cmd_msg_size(void)
1265 return msgsize; 1265 return msgsize;
1266} 1266}
1267 1267
1268/* Called with ovs_mutex or RCU read lock. */ 1268/* Called with ovs_mutex. */
1269static int ovs_dp_cmd_fill_info(struct datapath *dp, struct sk_buff *skb, 1269static int ovs_dp_cmd_fill_info(struct datapath *dp, struct sk_buff *skb,
1270 u32 portid, u32 seq, u32 flags, u8 cmd) 1270 u32 portid, u32 seq, u32 flags, u8 cmd)
1271{ 1271{
@@ -1555,7 +1555,7 @@ static int ovs_dp_cmd_get(struct sk_buff *skb, struct genl_info *info)
1555 if (!reply) 1555 if (!reply)
1556 return -ENOMEM; 1556 return -ENOMEM;
1557 1557
1558 rcu_read_lock(); 1558 ovs_lock();
1559 dp = lookup_datapath(sock_net(skb->sk), info->userhdr, info->attrs); 1559 dp = lookup_datapath(sock_net(skb->sk), info->userhdr, info->attrs);
1560 if (IS_ERR(dp)) { 1560 if (IS_ERR(dp)) {
1561 err = PTR_ERR(dp); 1561 err = PTR_ERR(dp);
@@ -1564,12 +1564,12 @@ static int ovs_dp_cmd_get(struct sk_buff *skb, struct genl_info *info)
1564 err = ovs_dp_cmd_fill_info(dp, reply, info->snd_portid, 1564 err = ovs_dp_cmd_fill_info(dp, reply, info->snd_portid,
1565 info->snd_seq, 0, OVS_DP_CMD_NEW); 1565 info->snd_seq, 0, OVS_DP_CMD_NEW);
1566 BUG_ON(err < 0); 1566 BUG_ON(err < 0);
1567 rcu_read_unlock(); 1567 ovs_unlock();
1568 1568
1569 return genlmsg_reply(reply, info); 1569 return genlmsg_reply(reply, info);
1570 1570
1571err_unlock_free: 1571err_unlock_free:
1572 rcu_read_unlock(); 1572 ovs_unlock();
1573 kfree_skb(reply); 1573 kfree_skb(reply);
1574 return err; 1574 return err;
1575} 1575}
@@ -1581,8 +1581,8 @@ static int ovs_dp_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
1581 int skip = cb->args[0]; 1581 int skip = cb->args[0];
1582 int i = 0; 1582 int i = 0;
1583 1583
1584 rcu_read_lock(); 1584 ovs_lock();
1585 list_for_each_entry_rcu(dp, &ovs_net->dps, list_node) { 1585 list_for_each_entry(dp, &ovs_net->dps, list_node) {
1586 if (i >= skip && 1586 if (i >= skip &&
1587 ovs_dp_cmd_fill_info(dp, skb, NETLINK_CB(cb->skb).portid, 1587 ovs_dp_cmd_fill_info(dp, skb, NETLINK_CB(cb->skb).portid,
1588 cb->nlh->nlmsg_seq, NLM_F_MULTI, 1588 cb->nlh->nlmsg_seq, NLM_F_MULTI,
@@ -1590,7 +1590,7 @@ static int ovs_dp_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
1590 break; 1590 break;
1591 i++; 1591 i++;
1592 } 1592 }
1593 rcu_read_unlock(); 1593 ovs_unlock();
1594 1594
1595 cb->args[0] = i; 1595 cb->args[0] = i;
1596 1596
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
index 939bcb32100f..fa4ec2e4a78b 100644
--- a/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -145,7 +145,7 @@ static bool match_validate(const struct sw_flow_match *match,
145 if (match->key->eth.type == htons(ETH_P_ARP) 145 if (match->key->eth.type == htons(ETH_P_ARP)
146 || match->key->eth.type == htons(ETH_P_RARP)) { 146 || match->key->eth.type == htons(ETH_P_RARP)) {
147 key_expected |= 1 << OVS_KEY_ATTR_ARP; 147 key_expected |= 1 << OVS_KEY_ATTR_ARP;
148 if (match->mask && (match->mask->key.eth.type == htons(0xffff))) 148 if (match->mask && (match->mask->key.tp.src == htons(0xff)))
149 mask_allowed |= 1 << OVS_KEY_ATTR_ARP; 149 mask_allowed |= 1 << OVS_KEY_ATTR_ARP;
150 } 150 }
151 151
@@ -689,6 +689,13 @@ static int ovs_key_from_nlattrs(struct sw_flow_match *match, u64 attrs,
689 ipv6_key->ipv6_frag, OVS_FRAG_TYPE_MAX); 689 ipv6_key->ipv6_frag, OVS_FRAG_TYPE_MAX);
690 return -EINVAL; 690 return -EINVAL;
691 } 691 }
692
693 if (ipv6_key->ipv6_label & htonl(0xFFF00000)) {
694 OVS_NLERR("IPv6 flow label %x is out of range (max=%x).\n",
695 ntohl(ipv6_key->ipv6_label), (1 << 20) - 1);
696 return -EINVAL;
697 }
698
692 SW_FLOW_KEY_PUT(match, ipv6.label, 699 SW_FLOW_KEY_PUT(match, ipv6.label,
693 ipv6_key->ipv6_label, is_mask); 700 ipv6_key->ipv6_label, is_mask);
694 SW_FLOW_KEY_PUT(match, ip.proto, 701 SW_FLOW_KEY_PUT(match, ip.proto,