Project

General

Profile

Bug #1953 » 0003-gtp-add-IPv6-transport-outer.patch

RoadRunnR, 02/19/2017 04:45 PM

View differences:

drivers/net/gtp.c
56 56
	u16			af;
57 57

  
58 58
	struct in_addr		ms_addr_ip4;
59
	struct in_addr		sgsn_addr_ip4;
59

  
60
	union {
61
		struct in6_addr	ip6;
62
		struct in_addr	ip4;
63
	} sgsn_addr;
60 64

  
61 65
	struct sock		*sk;
62 66
	struct net_device       *dev;
......
411 415
	return ip_route_output_key(sock_net(sk), fl4);
412 416
}
413 417

  
418
static struct dst_entry *ip6_route_output_gtp(struct flowi6 *fl6,
419
					      const struct sock *sk,
420
					      struct in6_addr *daddr)
421
{
422
	memset(fl6, 0, sizeof(*fl6));
423
	fl6->flowi6_oif		= sk->sk_bound_dev_if;
424
	fl6->daddr		= *daddr;
425
	fl6->saddr		= inet6_sk(sk)->saddr;
426
	fl6->flowi6_proto	= sk->sk_protocol;
427

  
428
	return ip6_route_output(sock_net(sk), NULL, fl6);
429
}
430

  
414 431
static inline void gtp0_push_header(struct sk_buff *skb, struct pdp_ctx *pctx)
415 432
{
416 433
	int payload_len = skb->len;
......
515 532
	__u8 tos;
516 533

  
517 534
	/* Prepend PDP header with TEI/TID from PDP ctx. */
518
	rt = dst_cache_get_ip4(&pctx->dst_cache, &pctx->sgsn_addr_ip4.s_addr);
535
	rt = dst_cache_get_ip4(&pctx->dst_cache, &pctx->sgsn_addr.ip4.s_addr);
519 536
	if (!rt) {
520
		rt = ip4_route_output_gtp(&fl4, pctx->sk, pctx->sgsn_addr_ip4.s_addr);
537
		rt = ip4_route_output_gtp(&fl4, pctx->sk, pctx->sgsn_addr.ip4.s_addr);
521 538
		if (IS_ERR(rt)) {
522 539
			netdev_dbg(dev, "no route to SSGN %pI4\n",
523
				   &pctx->sgsn_addr_ip4.s_addr);
540
				   &pctx->sgsn_addr.ip4.s_addr);
524 541
			dev->stats.tx_carrier_errors++;
525 542
			goto err;
526 543
		}
527 544

  
528 545
		dst_cache_set_ip4(&pctx->dst_cache, &rt->dst,
529
				  pctx->sgsn_addr_ip4.s_addr);
546
				  pctx->sgsn_addr.ip4.s_addr);
530 547
	}
531 548

  
532 549
	if (rt->dst.dev == dev) {
533 550
		netdev_dbg(dev, "circular route to SSGN %pI4\n",
534
			   &pctx->sgsn_addr_ip4.s_addr);
551
			   &pctx->sgsn_addr.ip4.s_addr);
535 552
		dev->stats.collisions++;
536 553
		goto err_rt;
537 554
	}
......
557 574
	return -EBADMSG;
558 575
}
559 576

  
577
static int gtp_dev_xmit_ip6(struct pdp_ctx *pctx, struct sk_buff *skb,
578
			    struct net_device *dev)
579
{
580
	const struct iphdr *iph = ip_hdr(skb);
581
	struct dst_entry *ndst;
582
	struct flowi6 fl6;
583
	__be16 gtph_port;
584

  
585
	/*
586
	 * Prepend PDP header with TEI/TID from PDP ctx.
587
	 */
588
	ndst = ip6_route_output_gtp(&fl6, pctx->sk, &pctx->sgsn_addr.ip6);
589
	if (ndst->error) {
590
		netdev_dbg(dev, "no route to SSGN %pI6\n",
591
			   &pctx->sgsn_addr.ip6.s6_addr);
592
		dev->stats.tx_carrier_errors++;
593
		goto err;
594
	}
595

  
596
	/* There is a routing loop. */
597
	if (ndst->dev == dev) {
598
		netdev_dbg(dev, "circular route to SSGN %pI6\n",
599
			   &pctx->sgsn_addr.ip6);
600
		dev->stats.collisions++;
601
		goto err_dst;
602
	}
603

  
604
	if (gtp_update_pmtu(pctx, skb, dev, ndst, iph->frag_off,
605
			    sizeof(struct ipv6hdr) + sizeof(struct udphdr), iph))
606
	    goto err_dst;
607

  
608
	skb_dst_drop(skb);
609
	gtp_push_header(skb, pctx);
610

  
611
	gtph_port = get_dst_port(pctx);
612

  
613
	udp_tunnel6_xmit_skb(ndst, pctx->sk, skb, ndst->dev, &fl6.saddr,
614
			     &fl6.daddr, 0, ip6_dst_hoplimit(ndst), 0,
615
			     gtph_port, gtph_port, false);
616

  
617
	return 0;
618

  
619
err_dst:
620
	dst_release(ndst);
621
err:
622
	return -EBADMSG;
623
}
624

  
560 625
static netdev_tx_t gtp_dev_xmit(struct sk_buff *skb, struct net_device *dev)
561 626
{
562 627
	struct pdp_ctx *pctx;
......
578 643
	case AF_INET:
579 644
		err = gtp_dev_xmit_ip4(pctx, skb, dev);
580 645
		break;
646
	case AF_INET6:
647
		err = gtp_dev_xmit_ip6(pctx, skb, dev);
648
		break;
581 649
        default:
582 650
                err = -EOPNOTSUPP;
583 651
		break;
......
871 939
{
872 940
	pctx->gtp_version = nla_get_u32(info->attrs[GTPA_VERSION]);
873 941
	pctx->af = AF_INET;
874
	pctx->sgsn_addr_ip4.s_addr =
875
		nla_get_be32(info->attrs[GTPA_SGSN_ADDRESS]);
942

  
943
	if (info->attrs[GTPA_SGSN_ADDRESS]) {
944
		pctx->sgsn_addr.ip4.s_addr =
945
			nla_get_be32(info->attrs[GTPA_SGSN_ADDRESS]);
946
	} else if (info->attrs[GTPA_SGSN_ADDRESS6]) {
947
		pctx->sgsn_addr.ip6 =
948
                        nla_get_in6_addr(info->attrs[GTPA_SGSN_ADDRESS6]);
949
	}
950

  
876 951
	pctx->ms_addr_ip4.s_addr =
877 952
		nla_get_be32(info->attrs[GTPA_MS_ADDRESS]);
878 953

  
......
911 986
	if (!gsk)
912 987
		return -ENODEV;
913 988

  
989
	switch (sk->sk_family) {
990
	case AF_INET:
991
		if (!info->attrs[GTPA_SGSN_ADDRESS])
992
			return -EINVAL;
993

  
994
		break;
995
	case AF_INET6:
996
		if (!info->attrs[GTPA_SGSN_ADDRESS6])
997
			return -EINVAL;
998

  
999
		break;
1000

  
1001
	default:
1002
		return -EINVAL;
1003
	}
1004

  
914 1005
	ms_addr = nla_get_be32(info->attrs[GTPA_MS_ADDRESS]);
915 1006
	hash_ms = ipv4_hashfn(ms_addr) % gtp->hash_size;
916 1007

  
......
976 1067
	switch (pctx->gtp_version) {
977 1068
	case GTP_V0:
978 1069
		netdev_dbg(dev, "GTPv0-U: new PDP ctx id=%llx ssgn=%pI4 ms=%pI4 (pdp=%p)\n",
979
			   pctx->u.v0.tid, &pctx->sgsn_addr_ip4,
1070
			   pctx->u.v0.tid, &pctx->sgsn_addr.ip4,
980 1071
			   &pctx->ms_addr_ip4, pctx);
981 1072
		break;
982 1073
	case GTP_V1:
983 1074
		netdev_dbg(dev, "GTPv1-U: new PDP ctx id=%x/%x ssgn=%pI4 ms=%pI4 (pdp=%p)\n",
984 1075
			   pctx->u.v1.i_tei, pctx->u.v1.o_tei,
985
			   &pctx->sgsn_addr_ip4, &pctx->ms_addr_ip4, pctx);
1076
			   &pctx->sgsn_addr.ip4, &pctx->ms_addr_ip4, pctx);
986 1077
		break;
987 1078
	}
988 1079

  
......
1013 1104
	struct gtp_dev *gtp;
1014 1105
	int err;
1015 1106

  
1107

  
1108
	if (info->attrs[GTPA_SGSN_ADDRESS] && info->attrs[GTPA_SGSN_ADDRESS6])
1109
		return -EINVAL;
1110

  
1016 1111
	if (!info->attrs[GTPA_VERSION] ||
1017 1112
	    !info->attrs[GTPA_LINK] ||
1018 1113
	    !info->attrs[GTPA_SGSN_ADDRESS] ||
......
1196 1291
		goto nlmsg_failure;
1197 1292

  
1198 1293
	if (nla_put_u32(skb, GTPA_VERSION, pctx->gtp_version) ||
1199
	    nla_put_be32(skb, GTPA_SGSN_ADDRESS, pctx->sgsn_addr_ip4.s_addr) ||
1294
	    nla_put_be32(skb, GTPA_SGSN_ADDRESS, pctx->sgsn_addr.ip4.s_addr) ||
1200 1295
	    nla_put_be32(skb, GTPA_MS_ADDRESS, pctx->ms_addr_ip4.s_addr))
1201 1296
		goto nla_put_failure;
1202 1297

  
......
1367 1462
	[GTPA_VERSION]		= { .type = NLA_U32, },
1368 1463
	[GTPA_TID]		= { .type = NLA_U64, },
1369 1464
	[GTPA_SGSN_ADDRESS]	= { .type = NLA_U32, },
1465
	[GTPA_SGSN_ADDRESS6]	= { .len = sizeof(struct in6_addr) },
1370 1466
	[GTPA_MS_ADDRESS]	= { .type = NLA_U32, },
1371 1467
	[GTPA_FLOW]		= { .type = NLA_U16, },
1372 1468
	[GTPA_NET_NS_FD]	= { .type = NLA_U32, },
include/uapi/linux/gtp.h
30 30
	GTPA_PAD,
31 31
	GTPA_PDP_HASHSIZE,
32 32
	GTPA_FD,
33
	GTPA_SGSN_ADDRESS6,
33 34
	__GTPA_MAX,
34 35
};
35 36
#define GTPA_MAX (__GTPA_MAX + 1)
(3-3/3)
Add picture from clipboard (Maximum size: 48.8 MB)