diff options
Diffstat (limited to 'net/openvswitch')
-rw-r--r-- | net/openvswitch/datapath.c | 2 | ||||
-rw-r--r-- | net/openvswitch/flow.c | 15 | ||||
-rw-r--r-- | net/openvswitch/flow_netlink.c | 16 |
3 files changed, 21 insertions, 12 deletions
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index 99cfafc2a139..ef38e5aecd28 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c | |||
@@ -308,7 +308,7 @@ static int queue_gso_packets(struct datapath *dp, struct sk_buff *skb, | |||
308 | const struct dp_upcall_info *upcall_info, | 308 | const struct dp_upcall_info *upcall_info, |
309 | uint32_t cutlen) | 309 | uint32_t cutlen) |
310 | { | 310 | { |
311 | unsigned short gso_type = skb_shinfo(skb)->gso_type; | 311 | unsigned int gso_type = skb_shinfo(skb)->gso_type; |
312 | struct sw_flow_key later_key; | 312 | struct sw_flow_key later_key; |
313 | struct sk_buff *segs, *nskb; | 313 | struct sk_buff *segs, *nskb; |
314 | int err; | 314 | int err; |
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c index dbe2379329c5..f039064ce922 100644 --- a/net/openvswitch/flow.c +++ b/net/openvswitch/flow.c | |||
@@ -579,6 +579,7 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key) | |||
579 | return -EINVAL; | 579 | return -EINVAL; |
580 | 580 | ||
581 | skb_reset_network_header(skb); | 581 | skb_reset_network_header(skb); |
582 | key->eth.type = skb->protocol; | ||
582 | } else { | 583 | } else { |
583 | eth = eth_hdr(skb); | 584 | eth = eth_hdr(skb); |
584 | ether_addr_copy(key->eth.src, eth->h_source); | 585 | ether_addr_copy(key->eth.src, eth->h_source); |
@@ -592,15 +593,23 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key) | |||
592 | if (unlikely(parse_vlan(skb, key))) | 593 | if (unlikely(parse_vlan(skb, key))) |
593 | return -ENOMEM; | 594 | return -ENOMEM; |
594 | 595 | ||
595 | skb->protocol = parse_ethertype(skb); | 596 | key->eth.type = parse_ethertype(skb); |
596 | if (unlikely(skb->protocol == htons(0))) | 597 | if (unlikely(key->eth.type == htons(0))) |
597 | return -ENOMEM; | 598 | return -ENOMEM; |
598 | 599 | ||
600 | /* Multiple tagged packets need to retain TPID to satisfy | ||
601 | * skb_vlan_pop(), which will later shift the ethertype into | ||
602 | * skb->protocol. | ||
603 | */ | ||
604 | if (key->eth.cvlan.tci & htons(VLAN_TAG_PRESENT)) | ||
605 | skb->protocol = key->eth.cvlan.tpid; | ||
606 | else | ||
607 | skb->protocol = key->eth.type; | ||
608 | |||
599 | skb_reset_network_header(skb); | 609 | skb_reset_network_header(skb); |
600 | __skb_push(skb, skb->data - skb_mac_header(skb)); | 610 | __skb_push(skb, skb->data - skb_mac_header(skb)); |
601 | } | 611 | } |
602 | skb_reset_mac_len(skb); | 612 | skb_reset_mac_len(skb); |
603 | key->eth.type = skb->protocol; | ||
604 | 613 | ||
605 | /* Network layer. */ | 614 | /* Network layer. */ |
606 | if (key->eth.type == htons(ETH_P_IP)) { | 615 | if (key->eth.type == htons(ETH_P_IP)) { |
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c index dc424798ba6f..624ea74353dd 100644 --- a/net/openvswitch/flow_netlink.c +++ b/net/openvswitch/flow_netlink.c | |||
@@ -2241,14 +2241,11 @@ int ovs_nla_put_mask(const struct sw_flow *flow, struct sk_buff *skb) | |||
2241 | 2241 | ||
2242 | #define MAX_ACTIONS_BUFSIZE (32 * 1024) | 2242 | #define MAX_ACTIONS_BUFSIZE (32 * 1024) |
2243 | 2243 | ||
2244 | static struct sw_flow_actions *nla_alloc_flow_actions(int size, bool log) | 2244 | static struct sw_flow_actions *nla_alloc_flow_actions(int size) |
2245 | { | 2245 | { |
2246 | struct sw_flow_actions *sfa; | 2246 | struct sw_flow_actions *sfa; |
2247 | 2247 | ||
2248 | if (size > MAX_ACTIONS_BUFSIZE) { | 2248 | WARN_ON_ONCE(size > MAX_ACTIONS_BUFSIZE); |
2249 | OVS_NLERR(log, "Flow action size %u bytes exceeds max", size); | ||
2250 | return ERR_PTR(-EINVAL); | ||
2251 | } | ||
2252 | 2249 | ||
2253 | sfa = kmalloc(sizeof(*sfa) + size, GFP_KERNEL); | 2250 | sfa = kmalloc(sizeof(*sfa) + size, GFP_KERNEL); |
2254 | if (!sfa) | 2251 | if (!sfa) |
@@ -2321,12 +2318,15 @@ static struct nlattr *reserve_sfa_size(struct sw_flow_actions **sfa, | |||
2321 | new_acts_size = ksize(*sfa) * 2; | 2318 | new_acts_size = ksize(*sfa) * 2; |
2322 | 2319 | ||
2323 | if (new_acts_size > MAX_ACTIONS_BUFSIZE) { | 2320 | if (new_acts_size > MAX_ACTIONS_BUFSIZE) { |
2324 | if ((MAX_ACTIONS_BUFSIZE - next_offset) < req_size) | 2321 | if ((MAX_ACTIONS_BUFSIZE - next_offset) < req_size) { |
2322 | OVS_NLERR(log, "Flow action size exceeds max %u", | ||
2323 | MAX_ACTIONS_BUFSIZE); | ||
2325 | return ERR_PTR(-EMSGSIZE); | 2324 | return ERR_PTR(-EMSGSIZE); |
2325 | } | ||
2326 | new_acts_size = MAX_ACTIONS_BUFSIZE; | 2326 | new_acts_size = MAX_ACTIONS_BUFSIZE; |
2327 | } | 2327 | } |
2328 | 2328 | ||
2329 | acts = nla_alloc_flow_actions(new_acts_size, log); | 2329 | acts = nla_alloc_flow_actions(new_acts_size); |
2330 | if (IS_ERR(acts)) | 2330 | if (IS_ERR(acts)) |
2331 | return (void *)acts; | 2331 | return (void *)acts; |
2332 | 2332 | ||
@@ -3059,7 +3059,7 @@ int ovs_nla_copy_actions(struct net *net, const struct nlattr *attr, | |||
3059 | { | 3059 | { |
3060 | int err; | 3060 | int err; |
3061 | 3061 | ||
3062 | *sfa = nla_alloc_flow_actions(nla_len(attr), log); | 3062 | *sfa = nla_alloc_flow_actions(min(nla_len(attr), MAX_ACTIONS_BUFSIZE)); |
3063 | if (IS_ERR(*sfa)) | 3063 | if (IS_ERR(*sfa)) |
3064 | return PTR_ERR(*sfa); | 3064 | return PTR_ERR(*sfa); |
3065 | 3065 | ||