@@ -1082,26 +1082,6 @@ static void wx_tx_ctxtdesc(struct wx_ring *tx_ring, u32 vlan_macip_lens,
10821082 context_desc -> mss_l4len_idx = cpu_to_le32 (mss_l4len_idx );
10831083}
10841084
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-
11051085union network_header {
11061086 struct iphdr * ipv4 ;
11071087 struct ipv6hdr * ipv6 ;
@@ -1112,6 +1092,8 @@ static u8 wx_encode_tx_desc_ptype(const struct wx_tx_buffer *first)
11121092{
11131093 u8 tun_prot = 0 , l4_prot = 0 , ptype = 0 ;
11141094 struct sk_buff * skb = first -> skb ;
1095+ unsigned char * exthdr , * l4_hdr ;
1096+ __be16 frag_off ;
11151097
11161098 if (skb -> encapsulation ) {
11171099 union network_header hdr ;
@@ -1122,14 +1104,18 @@ static u8 wx_encode_tx_desc_ptype(const struct wx_tx_buffer *first)
11221104 ptype = WX_PTYPE_TUN_IPV4 ;
11231105 break ;
11241106 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 );
11261112 ptype = WX_PTYPE_TUN_IPV6 ;
11271113 break ;
11281114 default :
11291115 return ptype ;
11301116 }
11311117
1132- if (tun_prot == IPPROTO_IPIP ) {
1118+ if (tun_prot == IPPROTO_IPIP || tun_prot == IPPROTO_IPV6 ) {
11331119 hdr .raw = (void * )inner_ip_hdr (skb );
11341120 ptype |= WX_PTYPE_PKT_IPIP ;
11351121 } else if (tun_prot == IPPROTO_UDP ) {
@@ -1166,7 +1152,11 @@ static u8 wx_encode_tx_desc_ptype(const struct wx_tx_buffer *first)
11661152 l4_prot = hdr .ipv4 -> protocol ;
11671153 break ;
11681154 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 );
11701160 ptype |= WX_PTYPE_PKT_IPV6 ;
11711161 break ;
11721162 default :
@@ -1179,7 +1169,11 @@ static u8 wx_encode_tx_desc_ptype(const struct wx_tx_buffer *first)
11791169 ptype = WX_PTYPE_PKT_IP ;
11801170 break ;
11811171 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 );
11831177 ptype = WX_PTYPE_PKT_IP | WX_PTYPE_PKT_IPV6 ;
11841178 break ;
11851179 default :
@@ -1269,13 +1263,20 @@ static int wx_tso(struct wx_ring *tx_ring, struct wx_tx_buffer *first,
12691263
12701264 /* vlan_macip_lens: HEADLEN, MACLEN, VLAN tag */
12711265 if (enc ) {
1266+ unsigned char * exthdr , * l4_hdr ;
1267+ __be16 frag_off ;
1268+
12721269 switch (first -> protocol ) {
12731270 case htons (ETH_P_IP ):
12741271 tun_prot = ip_hdr (skb )-> protocol ;
12751272 first -> tx_flags |= WX_TX_FLAGS_OUTER_IPV4 ;
12761273 break ;
12771274 case htons (ETH_P_IPV6 ):
1275+ l4_hdr = skb_transport_header (skb );
1276+ exthdr = skb_network_header (skb ) + sizeof (struct ipv6hdr );
12781277 tun_prot = ipv6_hdr (skb )-> nexthdr ;
1278+ if (l4_hdr != exthdr )
1279+ ipv6_skip_exthdr (skb , exthdr - skb -> data , & tun_prot , & frag_off );
12791280 break ;
12801281 default :
12811282 break ;
@@ -1298,6 +1299,7 @@ static int wx_tso(struct wx_ring *tx_ring, struct wx_tx_buffer *first,
12981299 WX_TXD_TUNNEL_LEN_SHIFT );
12991300 break ;
13001301 case IPPROTO_IPIP :
1302+ case IPPROTO_IPV6 :
13011303 tunhdr_eiplen_tunlen = (((char * )inner_ip_hdr (skb ) -
13021304 (char * )ip_hdr (skb )) >> 2 ) <<
13031305 WX_TXD_OUTER_IPLEN_SHIFT ;
@@ -1341,6 +1343,8 @@ static void wx_tx_csum(struct wx_ring *tx_ring, struct wx_tx_buffer *first,
13411343 vlan_macip_lens = skb_network_offset (skb ) <<
13421344 WX_TXD_MACLEN_SHIFT ;
13431345 } else {
1346+ unsigned char * exthdr , * l4_hdr ;
1347+ __be16 frag_off ;
13441348 u8 l4_prot = 0 ;
13451349 union {
13461350 struct iphdr * ipv4 ;
@@ -1362,7 +1366,12 @@ static void wx_tx_csum(struct wx_ring *tx_ring, struct wx_tx_buffer *first,
13621366 tun_prot = ip_hdr (skb )-> protocol ;
13631367 break ;
13641368 case htons (ETH_P_IPV6 ):
1369+ l4_hdr = skb_transport_header (skb );
1370+ exthdr = skb_network_header (skb ) + sizeof (struct ipv6hdr );
13651371 tun_prot = ipv6_hdr (skb )-> nexthdr ;
1372+ if (l4_hdr != exthdr )
1373+ ipv6_skip_exthdr (skb , exthdr - skb -> data ,
1374+ & tun_prot , & frag_off );
13661375 break ;
13671376 default :
13681377 return ;
@@ -1386,6 +1395,7 @@ static void wx_tx_csum(struct wx_ring *tx_ring, struct wx_tx_buffer *first,
13861395 WX_TXD_TUNNEL_LEN_SHIFT );
13871396 break ;
13881397 case IPPROTO_IPIP :
1398+ case IPPROTO_IPV6 :
13891399 tunhdr_eiplen_tunlen = (((char * )inner_ip_hdr (skb ) -
13901400 (char * )ip_hdr (skb )) >> 2 ) <<
13911401 WX_TXD_OUTER_IPLEN_SHIFT ;
@@ -1408,7 +1418,10 @@ static void wx_tx_csum(struct wx_ring *tx_ring, struct wx_tx_buffer *first,
14081418 break ;
14091419 case 6 :
14101420 vlan_macip_lens |= (transport_hdr .raw - network_hdr .raw ) >> 1 ;
1421+ exthdr = network_hdr .raw + sizeof (struct ipv6hdr );
14111422 l4_prot = network_hdr .ipv6 -> nexthdr ;
1423+ if (transport_hdr .raw != exthdr )
1424+ ipv6_skip_exthdr (skb , exthdr - skb -> data , & l4_prot , & frag_off );
14121425 break ;
14131426 default :
14141427 break ;
0 commit comments