diff options
| -rw-r--r-- | drivers/net/xen-netback/netback.c | 260 |
1 files changed, 3 insertions, 257 deletions
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 27385639b6e5..6b62c3eb8e18 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c | |||
| @@ -39,7 +39,6 @@ | |||
| 39 | #include <linux/udp.h> | 39 | #include <linux/udp.h> |
| 40 | 40 | ||
| 41 | #include <net/tcp.h> | 41 | #include <net/tcp.h> |
| 42 | #include <net/ip6_checksum.h> | ||
| 43 | 42 | ||
| 44 | #include <xen/xen.h> | 43 | #include <xen/xen.h> |
| 45 | #include <xen/events.h> | 44 | #include <xen/events.h> |
| @@ -1051,257 +1050,9 @@ static int xenvif_set_skb_gso(struct xenvif *vif, | |||
| 1051 | return 0; | 1050 | return 0; |
| 1052 | } | 1051 | } |
| 1053 | 1052 | ||
| 1054 | static inline int maybe_pull_tail(struct sk_buff *skb, unsigned int len, | ||
| 1055 | unsigned int max) | ||
| 1056 | { | ||
| 1057 | if (skb_headlen(skb) >= len) | ||
| 1058 | return 0; | ||
| 1059 | |||
| 1060 | /* If we need to pullup then pullup to the max, so we | ||
| 1061 | * won't need to do it again. | ||
| 1062 | */ | ||
| 1063 | if (max > skb->len) | ||
| 1064 | max = skb->len; | ||
| 1065 | |||
| 1066 | if (__pskb_pull_tail(skb, max - skb_headlen(skb)) == NULL) | ||
| 1067 | return -ENOMEM; | ||
| 1068 | |||
| 1069 | if (skb_headlen(skb) < len) | ||
| 1070 | return -EPROTO; | ||
| 1071 | |||
| 1072 | return 0; | ||
| 1073 | } | ||
| 1074 | |||
| 1075 | /* This value should be large enough to cover a tagged ethernet header plus | ||
| 1076 | * maximally sized IP and TCP or UDP headers. | ||
| 1077 | */ | ||
| 1078 | #define MAX_IP_HDR_LEN 128 | ||
| 1079 | |||
| 1080 | static int checksum_setup_ip(struct xenvif *vif, struct sk_buff *skb, | ||
| 1081 | int recalculate_partial_csum) | ||
| 1082 | { | ||
| 1083 | unsigned int off; | ||
| 1084 | bool fragment; | ||
| 1085 | int err; | ||
| 1086 | |||
| 1087 | fragment = false; | ||
| 1088 | |||
| 1089 | err = maybe_pull_tail(skb, | ||
| 1090 | sizeof(struct iphdr), | ||
| 1091 | MAX_IP_HDR_LEN); | ||
| 1092 | if (err < 0) | ||
| 1093 | goto out; | ||
| 1094 | |||
| 1095 | if (ip_hdr(skb)->frag_off & htons(IP_OFFSET | IP_MF)) | ||
| 1096 | fragment = true; | ||
| 1097 | |||
| 1098 | off = ip_hdrlen(skb); | ||
| 1099 | |||
| 1100 | err = -EPROTO; | ||
| 1101 | |||
| 1102 | if (fragment) | ||
| 1103 | goto out; | ||
| 1104 | |||
| 1105 | switch (ip_hdr(skb)->protocol) { | ||
| 1106 | case IPPROTO_TCP: | ||
| 1107 | err = maybe_pull_tail(skb, | ||
| 1108 | off + sizeof(struct tcphdr), | ||
| 1109 | MAX_IP_HDR_LEN); | ||
| 1110 | if (err < 0) | ||
| 1111 | goto out; | ||
| 1112 | |||
| 1113 | if (!skb_partial_csum_set(skb, off, | ||
| 1114 | offsetof(struct tcphdr, check))) { | ||
| 1115 | err = -EPROTO; | ||
| 1116 | goto out; | ||
| 1117 | } | ||
| 1118 | |||
| 1119 | if (recalculate_partial_csum) | ||
| 1120 | tcp_hdr(skb)->check = | ||
| 1121 | ~csum_tcpudp_magic(ip_hdr(skb)->saddr, | ||
| 1122 | ip_hdr(skb)->daddr, | ||
| 1123 | skb->len - off, | ||
| 1124 | IPPROTO_TCP, 0); | ||
| 1125 | break; | ||
| 1126 | case IPPROTO_UDP: | ||
| 1127 | err = maybe_pull_tail(skb, | ||
| 1128 | off + sizeof(struct udphdr), | ||
| 1129 | MAX_IP_HDR_LEN); | ||
| 1130 | if (err < 0) | ||
| 1131 | goto out; | ||
| 1132 | |||
| 1133 | if (!skb_partial_csum_set(skb, off, | ||
| 1134 | offsetof(struct udphdr, check))) { | ||
| 1135 | err = -EPROTO; | ||
| 1136 | goto out; | ||
| 1137 | } | ||
| 1138 | |||
| 1139 | if (recalculate_partial_csum) | ||
| 1140 | udp_hdr(skb)->check = | ||
| 1141 | ~csum_tcpudp_magic(ip_hdr(skb)->saddr, | ||
| 1142 | ip_hdr(skb)->daddr, | ||
| 1143 | skb->len - off, | ||
| 1144 | IPPROTO_UDP, 0); | ||
| 1145 | break; | ||
| 1146 | default: | ||
| 1147 | goto out; | ||
| 1148 | } | ||
| 1149 | |||
| 1150 | err = 0; | ||
| 1151 | |||
| 1152 | out: | ||
| 1153 | return err; | ||
| 1154 | } | ||
| 1155 | |||
| 1156 | /* This value should be large enough to cover a tagged ethernet header plus | ||
| 1157 | * an IPv6 header, all options, and a maximal TCP or UDP header. | ||
| 1158 | */ | ||
| 1159 | #define MAX_IPV6_HDR_LEN 256 | ||
| 1160 | |||
| 1161 | #define OPT_HDR(type, skb, off) \ | ||
| 1162 | (type *)(skb_network_header(skb) + (off)) | ||
| 1163 | |||
| 1164 | static int checksum_setup_ipv6(struct xenvif *vif, struct sk_buff *skb, | ||
| 1165 | int recalculate_partial_csum) | ||
| 1166 | { | ||
| 1167 | int err; | ||
| 1168 | u8 nexthdr; | ||
| 1169 | unsigned int off; | ||
| 1170 | unsigned int len; | ||
| 1171 | bool fragment; | ||
| 1172 | bool done; | ||
| 1173 | |||
| 1174 | fragment = false; | ||
| 1175 | done = false; | ||
| 1176 | |||
| 1177 | off = sizeof(struct ipv6hdr); | ||
| 1178 | |||
| 1179 | err = maybe_pull_tail(skb, off, MAX_IPV6_HDR_LEN); | ||
| 1180 | if (err < 0) | ||
| 1181 | goto out; | ||
| 1182 | |||
| 1183 | nexthdr = ipv6_hdr(skb)->nexthdr; | ||
| 1184 | |||
| 1185 | len = sizeof(struct ipv6hdr) + ntohs(ipv6_hdr(skb)->payload_len); | ||
| 1186 | while (off <= len && !done) { | ||
| 1187 | switch (nexthdr) { | ||
| 1188 | case IPPROTO_DSTOPTS: | ||
| 1189 | case IPPROTO_HOPOPTS: | ||
| 1190 | case IPPROTO_ROUTING: { | ||
| 1191 | struct ipv6_opt_hdr *hp; | ||
| 1192 | |||
| 1193 | err = maybe_pull_tail(skb, | ||
| 1194 | off + | ||
| 1195 | sizeof(struct ipv6_opt_hdr), | ||
| 1196 | MAX_IPV6_HDR_LEN); | ||
| 1197 | if (err < 0) | ||
| 1198 | goto out; | ||
| 1199 | |||
| 1200 | hp = OPT_HDR(struct ipv6_opt_hdr, skb, off); | ||
| 1201 | nexthdr = hp->nexthdr; | ||
| 1202 | off += ipv6_optlen(hp); | ||
| 1203 | break; | ||
| 1204 | } | ||
| 1205 | case IPPROTO_AH: { | ||
| 1206 | struct ip_auth_hdr *hp; | ||
| 1207 | |||
| 1208 | err = maybe_pull_tail(skb, | ||
| 1209 | off + | ||
| 1210 | sizeof(struct ip_auth_hdr), | ||
| 1211 | MAX_IPV6_HDR_LEN); | ||
| 1212 | if (err < 0) | ||
| 1213 | goto out; | ||
| 1214 | |||
| 1215 | hp = OPT_HDR(struct ip_auth_hdr, skb, off); | ||
| 1216 | nexthdr = hp->nexthdr; | ||
| 1217 | off += ipv6_authlen(hp); | ||
| 1218 | break; | ||
| 1219 | } | ||
| 1220 | case IPPROTO_FRAGMENT: { | ||
| 1221 | struct frag_hdr *hp; | ||
| 1222 | |||
| 1223 | err = maybe_pull_tail(skb, | ||
| 1224 | off + | ||
| 1225 | sizeof(struct frag_hdr), | ||
| 1226 | MAX_IPV6_HDR_LEN); | ||
| 1227 | if (err < 0) | ||
| 1228 | goto out; | ||
| 1229 | |||
| 1230 | hp = OPT_HDR(struct frag_hdr, skb, off); | ||
| 1231 | |||
| 1232 | if (hp->frag_off & htons(IP6_OFFSET | IP6_MF)) | ||
| 1233 | fragment = true; | ||
| 1234 | |||
| 1235 | nexthdr = hp->nexthdr; | ||
| 1236 | off += sizeof(struct frag_hdr); | ||
| 1237 | break; | ||
| 1238 | } | ||
| 1239 | default: | ||
| 1240 | done = true; | ||
| 1241 | break; | ||
| 1242 | } | ||
| 1243 | } | ||
| 1244 | |||
| 1245 | err = -EPROTO; | ||
| 1246 | |||
| 1247 | if (!done || fragment) | ||
| 1248 | goto out; | ||
| 1249 | |||
| 1250 | switch (nexthdr) { | ||
| 1251 | case IPPROTO_TCP: | ||
| 1252 | err = maybe_pull_tail(skb, | ||
| 1253 | off + sizeof(struct tcphdr), | ||
| 1254 | MAX_IPV6_HDR_LEN); | ||
| 1255 | if (err < 0) | ||
| 1256 | goto out; | ||
| 1257 | |||
| 1258 | if (!skb_partial_csum_set(skb, off, | ||
| 1259 | offsetof(struct tcphdr, check))) { | ||
| 1260 | err = -EPROTO; | ||
| 1261 | goto out; | ||
| 1262 | } | ||
| 1263 | |||
| 1264 | if (recalculate_partial_csum) | ||
| 1265 | tcp_hdr(skb)->check = | ||
| 1266 | ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, | ||
| 1267 | &ipv6_hdr(skb)->daddr, | ||
| 1268 | skb->len - off, | ||
| 1269 | IPPROTO_TCP, 0); | ||
| 1270 | break; | ||
| 1271 | case IPPROTO_UDP: | ||
| 1272 | err = maybe_pull_tail(skb, | ||
| 1273 | off + sizeof(struct udphdr), | ||
| 1274 | MAX_IPV6_HDR_LEN); | ||
| 1275 | if (err < 0) | ||
| 1276 | goto out; | ||
| 1277 | |||
| 1278 | if (!skb_partial_csum_set(skb, off, | ||
| 1279 | offsetof(struct udphdr, check))) { | ||
| 1280 | err = -EPROTO; | ||
| 1281 | goto out; | ||
| 1282 | } | ||
| 1283 | |||
| 1284 | if (recalculate_partial_csum) | ||
| 1285 | udp_hdr(skb)->check = | ||
| 1286 | ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, | ||
| 1287 | &ipv6_hdr(skb)->daddr, | ||
| 1288 | skb->len - off, | ||
| 1289 | IPPROTO_UDP, 0); | ||
| 1290 | break; | ||
| 1291 | default: | ||
| 1292 | goto out; | ||
| 1293 | } | ||
| 1294 | |||
| 1295 | err = 0; | ||
| 1296 | |||
| 1297 | out: | ||
| 1298 | return err; | ||
| 1299 | } | ||
| 1300 | |||
| 1301 | static int checksum_setup(struct xenvif *vif, struct sk_buff *skb) | 1053 | static int checksum_setup(struct xenvif *vif, struct sk_buff *skb) |
| 1302 | { | 1054 | { |
| 1303 | int err = -EPROTO; | 1055 | bool recalculate_partial_csum = false; |
| 1304 | int recalculate_partial_csum = 0; | ||
| 1305 | 1056 | ||
| 1306 | /* A GSO SKB must be CHECKSUM_PARTIAL. However some buggy | 1057 | /* A GSO SKB must be CHECKSUM_PARTIAL. However some buggy |
| 1307 | * peers can fail to set NETRXF_csum_blank when sending a GSO | 1058 | * peers can fail to set NETRXF_csum_blank when sending a GSO |
| @@ -1311,19 +1062,14 @@ static int checksum_setup(struct xenvif *vif, struct sk_buff *skb) | |||
| 1311 | if (skb->ip_summed != CHECKSUM_PARTIAL && skb_is_gso(skb)) { | 1062 | if (skb->ip_summed != CHECKSUM_PARTIAL && skb_is_gso(skb)) { |
| 1312 | vif->rx_gso_checksum_fixup++; | 1063 | vif->rx_gso_checksum_fixup++; |
| 1313 | skb->ip_summed = CHECKSUM_PARTIAL; | 1064 | skb->ip_summed = CHECKSUM_PARTIAL; |
| 1314 | recalculate_partial_csum = 1; | 1065 | recalculate_partial_csum = true; |
| 1315 | } | 1066 | } |
| 1316 | 1067 | ||
| 1317 | /* A non-CHECKSUM_PARTIAL SKB does not require setup. */ | 1068 | /* A non-CHECKSUM_PARTIAL SKB does not require setup. */ |
| 1318 | if (skb->ip_summed != CHECKSUM_PARTIAL) | 1069 | if (skb->ip_summed != CHECKSUM_PARTIAL) |
| 1319 | return 0; | 1070 | return 0; |
| 1320 | 1071 | ||
| 1321 | if (skb->protocol == htons(ETH_P_IP)) | 1072 | return skb_checksum_setup(skb, recalculate_partial_csum); |
| 1322 | err = checksum_setup_ip(vif, skb, recalculate_partial_csum); | ||
| 1323 | else if (skb->protocol == htons(ETH_P_IPV6)) | ||
| 1324 | err = checksum_setup_ipv6(vif, skb, recalculate_partial_csum); | ||
| 1325 | |||
| 1326 | return err; | ||
| 1327 | } | 1073 | } |
| 1328 | 1074 | ||
| 1329 | static bool tx_credit_exceeded(struct xenvif *vif, unsigned size) | 1075 | static bool tx_credit_exceeded(struct xenvif *vif, unsigned size) |
