@@ -243,12 +243,183 @@ static void efx_release_neigh(struct efx_nic *efx,
243243 efx_free_neigh (neigh );
244244}
245245
246- static void efx_gen_encap_header (struct efx_tc_encap_action * encap )
246+ static void efx_gen_tun_header_eth (struct efx_tc_encap_action * encap , u16 proto )
247247{
248- /* stub for now */
249- encap -> n_valid = false;
250- memset (encap -> encap_hdr , 0 , sizeof (encap -> encap_hdr ));
251- encap -> encap_hdr_len = ETH_HLEN ;
248+ struct efx_neigh_binder * neigh = encap -> neigh ;
249+ struct ethhdr * eth ;
250+
251+ encap -> encap_hdr_len = sizeof (* eth );
252+ eth = (struct ethhdr * )encap -> encap_hdr ;
253+
254+ if (encap -> neigh -> n_valid )
255+ ether_addr_copy (eth -> h_dest , neigh -> ha );
256+ else
257+ eth_zero_addr (eth -> h_dest );
258+ ether_addr_copy (eth -> h_source , neigh -> egdev -> dev_addr );
259+ eth -> h_proto = htons (proto );
260+ }
261+
262+ static void efx_gen_tun_header_ipv4 (struct efx_tc_encap_action * encap , u8 ipproto , u8 len )
263+ {
264+ struct efx_neigh_binder * neigh = encap -> neigh ;
265+ struct ip_tunnel_key * key = & encap -> key ;
266+ struct iphdr * ip ;
267+
268+ ip = (struct iphdr * )(encap -> encap_hdr + encap -> encap_hdr_len );
269+ encap -> encap_hdr_len += sizeof (* ip );
270+
271+ ip -> daddr = key -> u .ipv4 .dst ;
272+ ip -> saddr = key -> u .ipv4 .src ;
273+ ip -> ttl = neigh -> ttl ;
274+ ip -> protocol = ipproto ;
275+ ip -> version = 0x4 ;
276+ ip -> ihl = 0x5 ;
277+ ip -> tot_len = cpu_to_be16 (ip -> ihl * 4 + len );
278+ ip_send_check (ip );
279+ }
280+
281+ #ifdef CONFIG_IPV6
282+ static void efx_gen_tun_header_ipv6 (struct efx_tc_encap_action * encap , u8 ipproto , u8 len )
283+ {
284+ struct efx_neigh_binder * neigh = encap -> neigh ;
285+ struct ip_tunnel_key * key = & encap -> key ;
286+ struct ipv6hdr * ip ;
287+
288+ ip = (struct ipv6hdr * )(encap -> encap_hdr + encap -> encap_hdr_len );
289+ encap -> encap_hdr_len += sizeof (* ip );
290+
291+ ip6_flow_hdr (ip , key -> tos , key -> label );
292+ ip -> daddr = key -> u .ipv6 .dst ;
293+ ip -> saddr = key -> u .ipv6 .src ;
294+ ip -> hop_limit = neigh -> ttl ;
295+ ip -> nexthdr = ipproto ;
296+ ip -> version = 0x6 ;
297+ ip -> payload_len = cpu_to_be16 (len );
298+ }
299+ #endif
300+
301+ static void efx_gen_tun_header_udp (struct efx_tc_encap_action * encap , u8 len )
302+ {
303+ struct ip_tunnel_key * key = & encap -> key ;
304+ struct udphdr * udp ;
305+
306+ udp = (struct udphdr * )(encap -> encap_hdr + encap -> encap_hdr_len );
307+ encap -> encap_hdr_len += sizeof (* udp );
308+
309+ udp -> dest = key -> tp_dst ;
310+ udp -> len = cpu_to_be16 (sizeof (* udp ) + len );
311+ }
312+
313+ static void efx_gen_tun_header_vxlan (struct efx_tc_encap_action * encap )
314+ {
315+ struct ip_tunnel_key * key = & encap -> key ;
316+ struct vxlanhdr * vxlan ;
317+
318+ vxlan = (struct vxlanhdr * )(encap -> encap_hdr + encap -> encap_hdr_len );
319+ encap -> encap_hdr_len += sizeof (* vxlan );
320+
321+ vxlan -> vx_flags = VXLAN_HF_VNI ;
322+ vxlan -> vx_vni = vxlan_vni_field (tunnel_id_to_key32 (key -> tun_id ));
323+ }
324+
325+ static void efx_gen_tun_header_geneve (struct efx_tc_encap_action * encap )
326+ {
327+ struct ip_tunnel_key * key = & encap -> key ;
328+ struct genevehdr * geneve ;
329+ u32 vni ;
330+
331+ geneve = (struct genevehdr * )(encap -> encap_hdr + encap -> encap_hdr_len );
332+ encap -> encap_hdr_len += sizeof (* geneve );
333+
334+ geneve -> proto_type = htons (ETH_P_TEB );
335+ /* convert tun_id to host-endian so we can use host arithmetic to
336+ * extract individual bytes.
337+ */
338+ vni = ntohl (tunnel_id_to_key32 (key -> tun_id ));
339+ geneve -> vni [0 ] = vni >> 16 ;
340+ geneve -> vni [1 ] = vni >> 8 ;
341+ geneve -> vni [2 ] = vni ;
342+ }
343+
344+ #define vxlan_header_l4_len (sizeof(struct udphdr) + sizeof(struct vxlanhdr))
345+ #define vxlan4_header_len (sizeof(struct ethhdr) + sizeof(struct iphdr) + vxlan_header_l4_len)
346+ static void efx_gen_vxlan_header_ipv4 (struct efx_tc_encap_action * encap )
347+ {
348+ BUILD_BUG_ON (sizeof (encap -> encap_hdr ) < vxlan4_header_len );
349+ efx_gen_tun_header_eth (encap , ETH_P_IP );
350+ efx_gen_tun_header_ipv4 (encap , IPPROTO_UDP , vxlan_header_l4_len );
351+ efx_gen_tun_header_udp (encap , sizeof (struct vxlanhdr ));
352+ efx_gen_tun_header_vxlan (encap );
353+ }
354+
355+ #define geneve_header_l4_len (sizeof(struct udphdr) + sizeof(struct genevehdr))
356+ #define geneve4_header_len (sizeof(struct ethhdr) + sizeof(struct iphdr) + geneve_header_l4_len)
357+ static void efx_gen_geneve_header_ipv4 (struct efx_tc_encap_action * encap )
358+ {
359+ BUILD_BUG_ON (sizeof (encap -> encap_hdr ) < geneve4_header_len );
360+ efx_gen_tun_header_eth (encap , ETH_P_IP );
361+ efx_gen_tun_header_ipv4 (encap , IPPROTO_UDP , geneve_header_l4_len );
362+ efx_gen_tun_header_udp (encap , sizeof (struct genevehdr ));
363+ efx_gen_tun_header_geneve (encap );
364+ }
365+
366+ #ifdef CONFIG_IPV6
367+ #define vxlan6_header_len (sizeof(struct ethhdr) + sizeof(struct ipv6hdr) + vxlan_header_l4_len)
368+ static void efx_gen_vxlan_header_ipv6 (struct efx_tc_encap_action * encap )
369+ {
370+ BUILD_BUG_ON (sizeof (encap -> encap_hdr ) < vxlan6_header_len );
371+ efx_gen_tun_header_eth (encap , ETH_P_IPV6 );
372+ efx_gen_tun_header_ipv6 (encap , IPPROTO_UDP , vxlan_header_l4_len );
373+ efx_gen_tun_header_udp (encap , sizeof (struct vxlanhdr ));
374+ efx_gen_tun_header_vxlan (encap );
375+ }
376+
377+ #define geneve6_header_len (sizeof(struct ethhdr) + sizeof(struct ipv6hdr) + geneve_header_l4_len)
378+ static void efx_gen_geneve_header_ipv6 (struct efx_tc_encap_action * encap )
379+ {
380+ BUILD_BUG_ON (sizeof (encap -> encap_hdr ) < geneve6_header_len );
381+ efx_gen_tun_header_eth (encap , ETH_P_IPV6 );
382+ efx_gen_tun_header_ipv6 (encap , IPPROTO_UDP , geneve_header_l4_len );
383+ efx_gen_tun_header_udp (encap , sizeof (struct genevehdr ));
384+ efx_gen_tun_header_geneve (encap );
385+ }
386+ #endif
387+
388+ static void efx_gen_encap_header (struct efx_nic * efx ,
389+ struct efx_tc_encap_action * encap )
390+ {
391+ encap -> n_valid = encap -> neigh -> n_valid ;
392+
393+ /* GCC stupidly thinks that only values explicitly listed in the enum
394+ * definition can _possibly_ be sensible case values, so without this
395+ * cast it complains about the IPv6 versions.
396+ */
397+ switch ((int )encap -> type ) {
398+ case EFX_ENCAP_TYPE_VXLAN :
399+ efx_gen_vxlan_header_ipv4 (encap );
400+ break ;
401+ case EFX_ENCAP_TYPE_GENEVE :
402+ efx_gen_geneve_header_ipv4 (encap );
403+ break ;
404+ #ifdef CONFIG_IPV6
405+ case EFX_ENCAP_TYPE_VXLAN | EFX_ENCAP_FLAG_IPV6 :
406+ efx_gen_vxlan_header_ipv6 (encap );
407+ break ;
408+ case EFX_ENCAP_TYPE_GENEVE | EFX_ENCAP_FLAG_IPV6 :
409+ efx_gen_geneve_header_ipv6 (encap );
410+ break ;
411+ #endif
412+ default :
413+ /* unhandled encap type, can't happen */
414+ if (net_ratelimit ())
415+ netif_err (efx , drv , efx -> net_dev ,
416+ "Bogus encap type %d, can't generate\n" ,
417+ encap -> type );
418+
419+ /* Use fallback action. */
420+ encap -> n_valid = false;
421+ break ;
422+ }
252423}
253424
254425static void efx_tc_update_encap (struct efx_nic * efx ,
@@ -282,14 +453,19 @@ static void efx_tc_update_encap(struct efx_nic *efx,
282453 }
283454 }
284455
456+ /* Make sure we don't leak arbitrary bytes on the wire;
457+ * set an all-0s ethernet header. A successful call to
458+ * efx_gen_encap_header() will overwrite this.
459+ */
460+ memset (encap -> encap_hdr , 0 , sizeof (encap -> encap_hdr ));
461+ encap -> encap_hdr_len = ETH_HLEN ;
462+
285463 if (encap -> neigh ) {
286464 read_lock_bh (& encap -> neigh -> lock );
287- efx_gen_encap_header (encap );
465+ efx_gen_encap_header (efx , encap );
288466 read_unlock_bh (& encap -> neigh -> lock );
289467 } else {
290468 encap -> n_valid = false;
291- memset (encap -> encap_hdr , 0 , sizeof (encap -> encap_hdr ));
292- encap -> encap_hdr_len = ETH_HLEN ;
293469 }
294470
295471 rc = efx_mae_update_encap_md (efx , encap );
@@ -486,7 +662,7 @@ struct efx_tc_encap_action *efx_tc_flower_create_encap_md(
486662 }
487663 encap -> dest_mport = rc ;
488664 read_lock_bh (& encap -> neigh -> lock );
489- efx_gen_encap_header (encap );
665+ efx_gen_encap_header (efx , encap );
490666 read_unlock_bh (& encap -> neigh -> lock );
491667
492668 rc = efx_mae_allocate_encap_md (efx , encap );
0 commit comments