@@ -1047,6 +1047,63 @@ static int gtp_build_skb_outer_ip4(struct sk_buff *skb, struct net_device *dev,
1047
1047
return - EBADMSG ;
1048
1048
}
1049
1049
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
+
1050
1107
static int gtp_build_skb_ip4 (struct sk_buff * skb , struct net_device * dev ,
1051
1108
struct gtp_pktinfo * pktinfo )
1052
1109
{
@@ -1087,13 +1144,10 @@ static int gtp_build_skb_ip6(struct sk_buff *skb, struct net_device *dev,
1087
1144
{
1088
1145
struct gtp_dev * gtp = netdev_priv (dev );
1089
1146
struct net * net = gtp -> net ;
1090
- struct dst_entry * dst ;
1091
1147
struct pdp_ctx * pctx ;
1092
1148
struct ipv6hdr * ip6h ;
1093
- struct rt6_info * rt ;
1094
- struct flowi6 fl6 ;
1095
1149
__u8 tos ;
1096
- int mtu ;
1150
+ int ret ;
1097
1151
1098
1152
/* Read the IP destination address and resolve the PDP context.
1099
1153
* 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,
1111
1165
}
1112
1166
netdev_dbg (dev , "found PDP context %p\n" , pctx );
1113
1167
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
-
1151
1168
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 ;
1154
1173
1155
1174
netdev_dbg (dev , "gtp -> IP src: %pI6 dst: %pI6\n" ,
1156
1175
& ip6h -> saddr , & ip6h -> daddr );
1157
1176
1158
1177
return 0 ;
1159
- err_rt :
1160
- dst_release (dst );
1161
- err :
1162
- return - EBADMSG ;
1163
1178
}
1164
1179
1165
1180
static netdev_tx_t gtp_dev_xmit (struct sk_buff * skb , struct net_device * dev )
0 commit comments