diff options
Diffstat (limited to 'net/ipv4/ipip.c')
-rw-r--r-- | net/ipv4/ipip.c | 51 |
1 files changed, 26 insertions, 25 deletions
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index 99af1f0cc658..e15b45297c09 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c | |||
@@ -120,6 +120,10 @@ | |||
120 | #define HASH_SIZE 16 | 120 | #define HASH_SIZE 16 |
121 | #define HASH(addr) (((__force u32)addr^((__force u32)addr>>4))&0xF) | 121 | #define HASH(addr) (((__force u32)addr^((__force u32)addr>>4))&0xF) |
122 | 122 | ||
123 | static bool log_ecn_error = true; | ||
124 | module_param(log_ecn_error, bool, 0644); | ||
125 | MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN"); | ||
126 | |||
123 | static int ipip_net_id __read_mostly; | 127 | static int ipip_net_id __read_mostly; |
124 | struct ipip_net { | 128 | struct ipip_net { |
125 | struct ip_tunnel __rcu *tunnels_r_l[HASH_SIZE]; | 129 | struct ip_tunnel __rcu *tunnels_r_l[HASH_SIZE]; |
@@ -365,8 +369,6 @@ static int ipip_err(struct sk_buff *skb, u32 info) | |||
365 | } | 369 | } |
366 | 370 | ||
367 | err = -ENOENT; | 371 | err = -ENOENT; |
368 | |||
369 | rcu_read_lock(); | ||
370 | t = ipip_tunnel_lookup(dev_net(skb->dev), iph->daddr, iph->saddr); | 372 | t = ipip_tunnel_lookup(dev_net(skb->dev), iph->daddr, iph->saddr); |
371 | if (t == NULL) | 373 | if (t == NULL) |
372 | goto out; | 374 | goto out; |
@@ -398,34 +400,22 @@ static int ipip_err(struct sk_buff *skb, u32 info) | |||
398 | t->err_count = 1; | 400 | t->err_count = 1; |
399 | t->err_time = jiffies; | 401 | t->err_time = jiffies; |
400 | out: | 402 | out: |
401 | rcu_read_unlock(); | ||
402 | return err; | ||
403 | } | ||
404 | |||
405 | static inline void ipip_ecn_decapsulate(const struct iphdr *outer_iph, | ||
406 | struct sk_buff *skb) | ||
407 | { | ||
408 | struct iphdr *inner_iph = ip_hdr(skb); | ||
409 | 403 | ||
410 | if (INET_ECN_is_ce(outer_iph->tos)) | 404 | return err; |
411 | IP_ECN_set_ce(inner_iph); | ||
412 | } | 405 | } |
413 | 406 | ||
414 | static int ipip_rcv(struct sk_buff *skb) | 407 | static int ipip_rcv(struct sk_buff *skb) |
415 | { | 408 | { |
416 | struct ip_tunnel *tunnel; | 409 | struct ip_tunnel *tunnel; |
417 | const struct iphdr *iph = ip_hdr(skb); | 410 | const struct iphdr *iph = ip_hdr(skb); |
411 | int err; | ||
418 | 412 | ||
419 | rcu_read_lock(); | ||
420 | tunnel = ipip_tunnel_lookup(dev_net(skb->dev), iph->saddr, iph->daddr); | 413 | tunnel = ipip_tunnel_lookup(dev_net(skb->dev), iph->saddr, iph->daddr); |
421 | if (tunnel != NULL) { | 414 | if (tunnel != NULL) { |
422 | struct pcpu_tstats *tstats; | 415 | struct pcpu_tstats *tstats; |
423 | 416 | ||
424 | if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) { | 417 | if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) |
425 | rcu_read_unlock(); | 418 | goto drop; |
426 | kfree_skb(skb); | ||
427 | return 0; | ||
428 | } | ||
429 | 419 | ||
430 | secpath_reset(skb); | 420 | secpath_reset(skb); |
431 | 421 | ||
@@ -434,24 +424,35 @@ static int ipip_rcv(struct sk_buff *skb) | |||
434 | skb->protocol = htons(ETH_P_IP); | 424 | skb->protocol = htons(ETH_P_IP); |
435 | skb->pkt_type = PACKET_HOST; | 425 | skb->pkt_type = PACKET_HOST; |
436 | 426 | ||
427 | __skb_tunnel_rx(skb, tunnel->dev); | ||
428 | |||
429 | err = IP_ECN_decapsulate(iph, skb); | ||
430 | if (unlikely(err)) { | ||
431 | if (log_ecn_error) | ||
432 | net_info_ratelimited("non-ECT from %pI4 with TOS=%#x\n", | ||
433 | &iph->saddr, iph->tos); | ||
434 | if (err > 1) { | ||
435 | ++tunnel->dev->stats.rx_frame_errors; | ||
436 | ++tunnel->dev->stats.rx_errors; | ||
437 | goto drop; | ||
438 | } | ||
439 | } | ||
440 | |||
437 | tstats = this_cpu_ptr(tunnel->dev->tstats); | 441 | tstats = this_cpu_ptr(tunnel->dev->tstats); |
438 | u64_stats_update_begin(&tstats->syncp); | 442 | u64_stats_update_begin(&tstats->syncp); |
439 | tstats->rx_packets++; | 443 | tstats->rx_packets++; |
440 | tstats->rx_bytes += skb->len; | 444 | tstats->rx_bytes += skb->len; |
441 | u64_stats_update_end(&tstats->syncp); | 445 | u64_stats_update_end(&tstats->syncp); |
442 | 446 | ||
443 | __skb_tunnel_rx(skb, tunnel->dev); | ||
444 | |||
445 | ipip_ecn_decapsulate(iph, skb); | ||
446 | |||
447 | netif_rx(skb); | 447 | netif_rx(skb); |
448 | |||
449 | rcu_read_unlock(); | ||
450 | return 0; | 448 | return 0; |
451 | } | 449 | } |
452 | rcu_read_unlock(); | ||
453 | 450 | ||
454 | return -1; | 451 | return -1; |
452 | |||
453 | drop: | ||
454 | kfree_skb(skb); | ||
455 | return 0; | ||
455 | } | 456 | } |
456 | 457 | ||
457 | /* | 458 | /* |