@@ -1047,6 +1047,63 @@ static int gtp_build_skb_outer_ip4(struct sk_buff *skb, struct net_device *dev,
10471047 return - EBADMSG ;
10481048}
10491049
1050+ static int gtp_build_skb_outer_ip6 (struct net * net , struct sk_buff * skb ,
1051+ struct net_device * dev ,
1052+ struct gtp_pktinfo * pktinfo ,
1053+ struct pdp_ctx * pctx , __u8 tos )
1054+ {
1055+ struct dst_entry * dst ;
1056+ struct rt6_info * rt ;
1057+ struct flowi6 fl6 ;
1058+ int mtu ;
1059+
1060+ rt = ip6_route_output_gtp (net , & fl6 , pctx -> sk , & pctx -> peer .addr6 ,
1061+ & inet6_sk (pctx -> sk )-> saddr );
1062+ if (IS_ERR (rt )) {
1063+ netdev_dbg (dev , "no route to SSGN %pI6\n" ,
1064+ & pctx -> peer .addr6 );
1065+ dev -> stats .tx_carrier_errors ++ ;
1066+ goto err ;
1067+ }
1068+ dst = & rt -> dst ;
1069+
1070+ if (rt -> dst .dev == dev ) {
1071+ netdev_dbg (dev , "circular route to SSGN %pI6\n" ,
1072+ & pctx -> peer .addr6 );
1073+ dev -> stats .collisions ++ ;
1074+ goto err_rt ;
1075+ }
1076+
1077+ mtu = dst_mtu (& rt -> dst ) - dev -> hard_header_len -
1078+ sizeof (struct ipv6hdr ) - sizeof (struct udphdr );
1079+ switch (pctx -> gtp_version ) {
1080+ case GTP_V0 :
1081+ mtu -= sizeof (struct gtp0_header );
1082+ break ;
1083+ case GTP_V1 :
1084+ mtu -= sizeof (struct gtp1_header );
1085+ break ;
1086+ }
1087+
1088+ skb_dst_update_pmtu_no_confirm (skb , mtu );
1089+
1090+ if ((!skb_is_gso (skb ) && skb -> len > mtu ) ||
1091+ (skb_is_gso (skb ) && !skb_gso_validate_network_len (skb , mtu ))) {
1092+ netdev_dbg (dev , "packet too big, fragmentation needed\n" );
1093+ icmpv6_ndo_send (skb , ICMPV6_PKT_TOOBIG , 0 , mtu );
1094+ goto err_rt ;
1095+ }
1096+
1097+ gtp_set_pktinfo_ipv6 (pktinfo , pctx -> sk , tos , pctx , rt , & fl6 , dev );
1098+ gtp_push_header (skb , pktinfo );
1099+
1100+ return 0 ;
1101+ err_rt :
1102+ dst_release (dst );
1103+ err :
1104+ return - EBADMSG ;
1105+ }
1106+
10501107static int gtp_build_skb_ip4 (struct sk_buff * skb , struct net_device * dev ,
10511108 struct gtp_pktinfo * pktinfo )
10521109{
@@ -1087,13 +1144,10 @@ static int gtp_build_skb_ip6(struct sk_buff *skb, struct net_device *dev,
10871144{
10881145 struct gtp_dev * gtp = netdev_priv (dev );
10891146 struct net * net = gtp -> net ;
1090- struct dst_entry * dst ;
10911147 struct pdp_ctx * pctx ;
10921148 struct ipv6hdr * ip6h ;
1093- struct rt6_info * rt ;
1094- struct flowi6 fl6 ;
10951149 __u8 tos ;
1096- int mtu ;
1150+ int ret ;
10971151
10981152 /* Read the IP destination address and resolve the PDP context.
10991153 * Prepend PDP header with TEI/TID from PDP ctx.
@@ -1111,55 +1165,16 @@ static int gtp_build_skb_ip6(struct sk_buff *skb, struct net_device *dev,
11111165 }
11121166 netdev_dbg (dev , "found PDP context %p\n" , pctx );
11131167
1114- rt = ip6_route_output_gtp (net , & fl6 , pctx -> sk , & pctx -> peer .addr6 ,
1115- & inet6_sk (pctx -> sk )-> saddr );
1116- if (IS_ERR (rt )) {
1117- netdev_dbg (dev , "no route to SSGN %pI6\n" ,
1118- & pctx -> peer .addr6 );
1119- dev -> stats .tx_carrier_errors ++ ;
1120- goto err ;
1121- }
1122- dst = & rt -> dst ;
1123-
1124- if (rt -> dst .dev == dev ) {
1125- netdev_dbg (dev , "circular route to SSGN %pI6\n" ,
1126- & pctx -> peer .addr6 );
1127- dev -> stats .collisions ++ ;
1128- goto err_rt ;
1129- }
1130-
1131- mtu = dst_mtu (& rt -> dst ) - dev -> hard_header_len -
1132- sizeof (struct ipv6hdr ) - sizeof (struct udphdr );
1133- switch (pctx -> gtp_version ) {
1134- case GTP_V0 :
1135- mtu -= sizeof (struct gtp0_header );
1136- break ;
1137- case GTP_V1 :
1138- mtu -= sizeof (struct gtp1_header );
1139- break ;
1140- }
1141-
1142- skb_dst_update_pmtu_no_confirm (skb , mtu );
1143-
1144- if ((!skb_is_gso (skb ) && skb -> len > mtu ) ||
1145- (skb_is_gso (skb ) && !skb_gso_validate_network_len (skb , mtu ))) {
1146- netdev_dbg (dev , "packet too big, fragmentation needed\n" );
1147- icmpv6_ndo_send (skb , ICMPV6_PKT_TOOBIG , 0 , mtu );
1148- goto err_rt ;
1149- }
1150-
11511168 tos = ipv6_get_dsfield (ip6h );
1152- gtp_set_pktinfo_ipv6 (pktinfo , pctx -> sk , tos , pctx , rt , & fl6 , dev );
1153- gtp_push_header (skb , pktinfo );
1169+
1170+ ret = gtp_build_skb_outer_ip6 (net , skb , dev , pktinfo , pctx , tos );
1171+ if (ret < 0 )
1172+ return ret ;
11541173
11551174 netdev_dbg (dev , "gtp -> IP src: %pI6 dst: %pI6\n" ,
11561175 & ip6h -> saddr , & ip6h -> daddr );
11571176
11581177 return 0 ;
1159- err_rt :
1160- dst_release (dst );
1161- err :
1162- return - EBADMSG ;
11631178}
11641179
11651180static netdev_tx_t gtp_dev_xmit (struct sk_buff * skb , struct net_device * dev )
0 commit comments