@@ -983,33 +983,16 @@ static void gtp_set_pktinfo_ipv6(struct gtp_pktinfo *pktinfo,
983983 pktinfo -> dev = dev ;
984984}
985985
986- static int gtp_build_skb_ip4 (struct sk_buff * skb , struct net_device * dev ,
987- struct gtp_pktinfo * pktinfo )
986+ static int gtp_build_skb_outer_ip4 (struct sk_buff * skb , struct net_device * dev ,
987+ struct gtp_pktinfo * pktinfo ,
988+ struct pdp_ctx * pctx , __u8 tos ,
989+ __be16 frag_off )
988990{
989- struct gtp_dev * gtp = netdev_priv (dev );
990- struct pdp_ctx * pctx ;
991991 struct rtable * rt ;
992992 struct flowi4 fl4 ;
993- struct iphdr * iph ;
994993 __be16 df ;
995994 int mtu ;
996995
997- /* Read the IP destination address and resolve the PDP context.
998- * Prepend PDP header with TEI/TID from PDP ctx.
999- */
1000- iph = ip_hdr (skb );
1001- if (gtp -> role == GTP_ROLE_SGSN )
1002- pctx = ipv4_pdp_find (gtp , iph -> saddr );
1003- else
1004- pctx = ipv4_pdp_find (gtp , iph -> daddr );
1005-
1006- if (!pctx ) {
1007- netdev_dbg (dev , "no PDP ctx found for %pI4, skip\n" ,
1008- & iph -> daddr );
1009- return - ENOENT ;
1010- }
1011- netdev_dbg (dev , "found PDP context %p\n" , pctx );
1012-
1013996 rt = ip4_route_output_gtp (& fl4 , pctx -> sk , pctx -> peer .addr .s_addr ,
1014997 inet_sk (pctx -> sk )-> inet_saddr );
1015998 if (IS_ERR (rt )) {
@@ -1027,7 +1010,7 @@ static int gtp_build_skb_ip4(struct sk_buff *skb, struct net_device *dev,
10271010 }
10281011
10291012 /* This is similar to tnl_update_pmtu(). */
1030- df = iph -> frag_off ;
1013+ df = frag_off ;
10311014 if (df ) {
10321015 mtu = dst_mtu (& rt -> dst ) - dev -> hard_header_len -
10331016 sizeof (struct iphdr ) - sizeof (struct udphdr );
@@ -1045,7 +1028,7 @@ static int gtp_build_skb_ip4(struct sk_buff *skb, struct net_device *dev,
10451028
10461029 skb_dst_update_pmtu_no_confirm (skb , mtu );
10471030
1048- if (iph -> frag_off & htons (IP_DF ) &&
1031+ if (frag_off & htons (IP_DF ) &&
10491032 ((!skb_is_gso (skb ) && skb -> len > mtu ) ||
10501033 (skb_is_gso (skb ) && !skb_gso_validate_network_len (skb , mtu )))) {
10511034 netdev_dbg (dev , "packet too big, fragmentation needed\n" );
@@ -1054,19 +1037,51 @@ static int gtp_build_skb_ip4(struct sk_buff *skb, struct net_device *dev,
10541037 goto err_rt ;
10551038 }
10561039
1057- gtp_set_pktinfo_ipv4 (pktinfo , pctx -> sk , iph -> tos , pctx , rt , & fl4 , dev );
1040+ gtp_set_pktinfo_ipv4 (pktinfo , pctx -> sk , tos , pctx , rt , & fl4 , dev );
10581041 gtp_push_header (skb , pktinfo );
10591042
1060- netdev_dbg (dev , "gtp -> IP src: %pI4 dst: %pI4\n" ,
1061- & iph -> saddr , & iph -> daddr );
1062-
10631043 return 0 ;
10641044err_rt :
10651045 ip_rt_put (rt );
10661046err :
10671047 return - EBADMSG ;
10681048}
10691049
1050+ static int gtp_build_skb_ip4 (struct sk_buff * skb , struct net_device * dev ,
1051+ struct gtp_pktinfo * pktinfo )
1052+ {
1053+ struct gtp_dev * gtp = netdev_priv (dev );
1054+ struct pdp_ctx * pctx ;
1055+ struct iphdr * iph ;
1056+ int ret ;
1057+
1058+ /* Read the IP destination address and resolve the PDP context.
1059+ * Prepend PDP header with TEI/TID from PDP ctx.
1060+ */
1061+ iph = ip_hdr (skb );
1062+ if (gtp -> role == GTP_ROLE_SGSN )
1063+ pctx = ipv4_pdp_find (gtp , iph -> saddr );
1064+ else
1065+ pctx = ipv4_pdp_find (gtp , iph -> daddr );
1066+
1067+ if (!pctx ) {
1068+ netdev_dbg (dev , "no PDP ctx found for %pI4, skip\n" ,
1069+ & iph -> daddr );
1070+ return - ENOENT ;
1071+ }
1072+ netdev_dbg (dev , "found PDP context %p\n" , pctx );
1073+
1074+ ret = gtp_build_skb_outer_ip4 (skb , dev , pktinfo , pctx ,
1075+ iph -> tos , iph -> frag_off );
1076+ if (ret < 0 )
1077+ return ret ;
1078+
1079+ netdev_dbg (dev , "gtp -> IP src: %pI4 dst: %pI4\n" ,
1080+ & iph -> saddr , & iph -> daddr );
1081+
1082+ return 0 ;
1083+ }
1084+
10701085static int gtp_build_skb_ip6 (struct sk_buff * skb , struct net_device * dev ,
10711086 struct gtp_pktinfo * pktinfo )
10721087{
0 commit comments