aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/ipip.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/ipip.c')
-rw-r--r--net/ipv4/ipip.c51
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
123static bool log_ecn_error = true;
124module_param(log_ecn_error, bool, 0644);
125MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN");
126
123static int ipip_net_id __read_mostly; 127static int ipip_net_id __read_mostly;
124struct ipip_net { 128struct 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;
400out: 402out:
401 rcu_read_unlock();
402 return err;
403}
404
405static 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
414static int ipip_rcv(struct sk_buff *skb) 407static 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
453drop:
454 kfree_skb(skb);
455 return 0;
455} 456}
456 457
457/* 458/*