Project

General

Profile

Bug #1953 » 0001-gtp-move-path-mtu-calculation-and-error-handling-int.patch

RoadRunnR, 02/19/2017 04:45 PM

View differences:

drivers/net/gtp.c
458 458
	}
459 459
}
460 460

  
461
static int gtp_update_pmtu(struct pdp_ctx *pctx, struct sk_buff *skb,
462
			  struct net_device *dev, struct dst_entry *ndst,
463
			  __be16 df, int tnl_header_len,
464
			  const struct iphdr *inner_iph)
465
{
466
	int mtu;
467

  
468
	if (df) {
469
		mtu = dst_mtu(ndst) - dev->hard_header_len - tnl_header_len;
470
		switch (pctx->gtp_version) {
471
		case GTP_V0:
472
			mtu -= sizeof(struct gtp0_header);
473
			break;
474
		case GTP_V1:
475
			mtu -= sizeof(struct gtp1_header);
476
			break;
477
		}
478
	} else
479
		mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu;
480

  
481
	if (skb_dst(skb))
482
		skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu);
483

  
484
	if (!skb_is_gso(skb) && (inner_iph->frag_off & htons(IP_DF)) &&
485
	    mtu < ntohs(inner_iph->tot_len)) {
486
		netdev_dbg(dev, "packet too big, fragmentation needed\n");
487
		memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
488
		icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
489
		return -E2BIG;
490
	}
491

  
492
	return 0;
493
 }
494

  
461 495
static inline void gtp_set_pktinfo_ipv4(struct gtp_pktinfo *pktinfo,
462 496
					struct sock *sk, struct iphdr *iph,
463 497
					struct pdp_ctx *pctx, struct rtable *rt,
......
480 514
	struct rtable *rt;
481 515
	struct flowi4 fl4;
482 516
	struct iphdr *iph;
483
	__be16 df;
484
	int mtu;
485 517

  
486 518
	/* Read the IP destination address and resolve the PDP context.
487 519
	 * Prepend PDP header with TEI/TID from PDP ctx.
......
516 548
		goto err_rt;
517 549
	}
518 550

  
551
	if (gtp_update_pmtu(pctx, skb, dev, &rt->dst, iph->frag_off,
552
			    sizeof(struct iphdr) + sizeof(struct udphdr), iph))
553
		goto err_rt;
554

  
519 555
	skb_dst_drop(skb);
520 556

  
521
	/* This is similar to tnl_update_pmtu(). */
522
	df = iph->frag_off;
523
	if (df) {
524
		mtu = dst_mtu(&rt->dst) - dev->hard_header_len -
525
			sizeof(struct iphdr) - sizeof(struct udphdr);
526
		switch (pctx->gtp_version) {
527
		case GTP_V0:
528
			mtu -= sizeof(struct gtp0_header);
529
			break;
530
		case GTP_V1:
531
			mtu -= sizeof(struct gtp1_header);
532
			break;
533
		}
534
	} else {
535
		mtu = dst_mtu(&rt->dst);
536
	}
537

  
538
	rt->dst.ops->update_pmtu(&rt->dst, NULL, skb, mtu);
539

  
540
	if (!skb_is_gso(skb) && (iph->frag_off & htons(IP_DF)) &&
541
	    mtu < ntohs(iph->tot_len)) {
542
		netdev_dbg(dev, "packet too big, fragmentation needed\n");
543
		memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
544
		icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
545
			  htonl(mtu));
546
		goto err_rt;
547
	}
548

  
549 557
	gtp_set_pktinfo_ipv4(pktinfo, pctx->sk, iph, pctx, rt, &fl4, dev);
550 558
	gtp_push_header(skb, pktinfo);
551 559

  
(1-1/3)
Add picture from clipboard (Maximum size: 48.8 MB)