@@ -1082,26 +1082,6 @@ static void wx_tx_ctxtdesc(struct wx_ring *tx_ring, u32 vlan_macip_lens,
1082
1082
context_desc -> mss_l4len_idx = cpu_to_le32 (mss_l4len_idx );
1083
1083
}
1084
1084
1085
- static void wx_get_ipv6_proto (struct sk_buff * skb , int offset , u8 * nexthdr )
1086
- {
1087
- struct ipv6hdr * hdr = (struct ipv6hdr * )(skb -> data + offset );
1088
-
1089
- * nexthdr = hdr -> nexthdr ;
1090
- offset += sizeof (struct ipv6hdr );
1091
- while (ipv6_ext_hdr (* nexthdr )) {
1092
- struct ipv6_opt_hdr _hdr , * hp ;
1093
-
1094
- if (* nexthdr == NEXTHDR_NONE )
1095
- return ;
1096
- hp = skb_header_pointer (skb , offset , sizeof (_hdr ), & _hdr );
1097
- if (!hp )
1098
- return ;
1099
- if (* nexthdr == NEXTHDR_FRAGMENT )
1100
- break ;
1101
- * nexthdr = hp -> nexthdr ;
1102
- }
1103
- }
1104
-
1105
1085
union network_header {
1106
1086
struct iphdr * ipv4 ;
1107
1087
struct ipv6hdr * ipv6 ;
@@ -1112,6 +1092,8 @@ static u8 wx_encode_tx_desc_ptype(const struct wx_tx_buffer *first)
1112
1092
{
1113
1093
u8 tun_prot = 0 , l4_prot = 0 , ptype = 0 ;
1114
1094
struct sk_buff * skb = first -> skb ;
1095
+ unsigned char * exthdr , * l4_hdr ;
1096
+ __be16 frag_off ;
1115
1097
1116
1098
if (skb -> encapsulation ) {
1117
1099
union network_header hdr ;
@@ -1122,14 +1104,18 @@ static u8 wx_encode_tx_desc_ptype(const struct wx_tx_buffer *first)
1122
1104
ptype = WX_PTYPE_TUN_IPV4 ;
1123
1105
break ;
1124
1106
case htons (ETH_P_IPV6 ):
1125
- wx_get_ipv6_proto (skb , skb_network_offset (skb ), & tun_prot );
1107
+ l4_hdr = skb_transport_header (skb );
1108
+ exthdr = skb_network_header (skb ) + sizeof (struct ipv6hdr );
1109
+ tun_prot = ipv6_hdr (skb )-> nexthdr ;
1110
+ if (l4_hdr != exthdr )
1111
+ ipv6_skip_exthdr (skb , exthdr - skb -> data , & tun_prot , & frag_off );
1126
1112
ptype = WX_PTYPE_TUN_IPV6 ;
1127
1113
break ;
1128
1114
default :
1129
1115
return ptype ;
1130
1116
}
1131
1117
1132
- if (tun_prot == IPPROTO_IPIP ) {
1118
+ if (tun_prot == IPPROTO_IPIP || tun_prot == IPPROTO_IPV6 ) {
1133
1119
hdr .raw = (void * )inner_ip_hdr (skb );
1134
1120
ptype |= WX_PTYPE_PKT_IPIP ;
1135
1121
} else if (tun_prot == IPPROTO_UDP ) {
@@ -1166,7 +1152,11 @@ static u8 wx_encode_tx_desc_ptype(const struct wx_tx_buffer *first)
1166
1152
l4_prot = hdr .ipv4 -> protocol ;
1167
1153
break ;
1168
1154
case 6 :
1169
- wx_get_ipv6_proto (skb , skb_inner_network_offset (skb ), & l4_prot );
1155
+ l4_hdr = skb_inner_transport_header (skb );
1156
+ exthdr = skb_inner_network_header (skb ) + sizeof (struct ipv6hdr );
1157
+ l4_prot = inner_ipv6_hdr (skb )-> nexthdr ;
1158
+ if (l4_hdr != exthdr )
1159
+ ipv6_skip_exthdr (skb , exthdr - skb -> data , & l4_prot , & frag_off );
1170
1160
ptype |= WX_PTYPE_PKT_IPV6 ;
1171
1161
break ;
1172
1162
default :
@@ -1179,7 +1169,11 @@ static u8 wx_encode_tx_desc_ptype(const struct wx_tx_buffer *first)
1179
1169
ptype = WX_PTYPE_PKT_IP ;
1180
1170
break ;
1181
1171
case htons (ETH_P_IPV6 ):
1182
- wx_get_ipv6_proto (skb , skb_network_offset (skb ), & l4_prot );
1172
+ l4_hdr = skb_transport_header (skb );
1173
+ exthdr = skb_network_header (skb ) + sizeof (struct ipv6hdr );
1174
+ l4_prot = ipv6_hdr (skb )-> nexthdr ;
1175
+ if (l4_hdr != exthdr )
1176
+ ipv6_skip_exthdr (skb , exthdr - skb -> data , & l4_prot , & frag_off );
1183
1177
ptype = WX_PTYPE_PKT_IP | WX_PTYPE_PKT_IPV6 ;
1184
1178
break ;
1185
1179
default :
@@ -1269,13 +1263,20 @@ static int wx_tso(struct wx_ring *tx_ring, struct wx_tx_buffer *first,
1269
1263
1270
1264
/* vlan_macip_lens: HEADLEN, MACLEN, VLAN tag */
1271
1265
if (enc ) {
1266
+ unsigned char * exthdr , * l4_hdr ;
1267
+ __be16 frag_off ;
1268
+
1272
1269
switch (first -> protocol ) {
1273
1270
case htons (ETH_P_IP ):
1274
1271
tun_prot = ip_hdr (skb )-> protocol ;
1275
1272
first -> tx_flags |= WX_TX_FLAGS_OUTER_IPV4 ;
1276
1273
break ;
1277
1274
case htons (ETH_P_IPV6 ):
1275
+ l4_hdr = skb_transport_header (skb );
1276
+ exthdr = skb_network_header (skb ) + sizeof (struct ipv6hdr );
1278
1277
tun_prot = ipv6_hdr (skb )-> nexthdr ;
1278
+ if (l4_hdr != exthdr )
1279
+ ipv6_skip_exthdr (skb , exthdr - skb -> data , & tun_prot , & frag_off );
1279
1280
break ;
1280
1281
default :
1281
1282
break ;
@@ -1298,6 +1299,7 @@ static int wx_tso(struct wx_ring *tx_ring, struct wx_tx_buffer *first,
1298
1299
WX_TXD_TUNNEL_LEN_SHIFT );
1299
1300
break ;
1300
1301
case IPPROTO_IPIP :
1302
+ case IPPROTO_IPV6 :
1301
1303
tunhdr_eiplen_tunlen = (((char * )inner_ip_hdr (skb ) -
1302
1304
(char * )ip_hdr (skb )) >> 2 ) <<
1303
1305
WX_TXD_OUTER_IPLEN_SHIFT ;
@@ -1341,6 +1343,8 @@ static void wx_tx_csum(struct wx_ring *tx_ring, struct wx_tx_buffer *first,
1341
1343
vlan_macip_lens = skb_network_offset (skb ) <<
1342
1344
WX_TXD_MACLEN_SHIFT ;
1343
1345
} else {
1346
+ unsigned char * exthdr , * l4_hdr ;
1347
+ __be16 frag_off ;
1344
1348
u8 l4_prot = 0 ;
1345
1349
union {
1346
1350
struct iphdr * ipv4 ;
@@ -1362,7 +1366,12 @@ static void wx_tx_csum(struct wx_ring *tx_ring, struct wx_tx_buffer *first,
1362
1366
tun_prot = ip_hdr (skb )-> protocol ;
1363
1367
break ;
1364
1368
case htons (ETH_P_IPV6 ):
1369
+ l4_hdr = skb_transport_header (skb );
1370
+ exthdr = skb_network_header (skb ) + sizeof (struct ipv6hdr );
1365
1371
tun_prot = ipv6_hdr (skb )-> nexthdr ;
1372
+ if (l4_hdr != exthdr )
1373
+ ipv6_skip_exthdr (skb , exthdr - skb -> data ,
1374
+ & tun_prot , & frag_off );
1366
1375
break ;
1367
1376
default :
1368
1377
return ;
@@ -1386,6 +1395,7 @@ static void wx_tx_csum(struct wx_ring *tx_ring, struct wx_tx_buffer *first,
1386
1395
WX_TXD_TUNNEL_LEN_SHIFT );
1387
1396
break ;
1388
1397
case IPPROTO_IPIP :
1398
+ case IPPROTO_IPV6 :
1389
1399
tunhdr_eiplen_tunlen = (((char * )inner_ip_hdr (skb ) -
1390
1400
(char * )ip_hdr (skb )) >> 2 ) <<
1391
1401
WX_TXD_OUTER_IPLEN_SHIFT ;
@@ -1408,7 +1418,10 @@ static void wx_tx_csum(struct wx_ring *tx_ring, struct wx_tx_buffer *first,
1408
1418
break ;
1409
1419
case 6 :
1410
1420
vlan_macip_lens |= (transport_hdr .raw - network_hdr .raw ) >> 1 ;
1421
+ exthdr = network_hdr .raw + sizeof (struct ipv6hdr );
1411
1422
l4_prot = network_hdr .ipv6 -> nexthdr ;
1423
+ if (transport_hdr .raw != exthdr )
1424
+ ipv6_skip_exthdr (skb , exthdr - skb -> data , & l4_prot , & frag_off );
1412
1425
break ;
1413
1426
default :
1414
1427
break ;
0 commit comments