3636#include <linux/inetdevice.h>
3737#include <linux/netdevice.h>
3838#include <net/netevent.h>
39+ #include <net/ipv6_stubs.h>
3940
4041#include "en.h"
4142#include "eswitch.h"
@@ -259,9 +260,15 @@ static void mlx5e_ipsec_init_macs(struct mlx5e_ipsec_sa_entry *sa_entry,
259260 struct mlx5_accel_esp_xfrm_attrs * attrs )
260261{
261262 struct mlx5_core_dev * mdev = mlx5e_ipsec_sa2dev (sa_entry );
263+ struct mlx5e_ipsec_addr * addrs = & attrs -> addrs ;
262264 struct net_device * netdev = sa_entry -> dev ;
265+ struct xfrm_state * x = sa_entry -> x ;
266+ struct dst_entry * rt_dst_entry ;
267+ struct flowi4 fl4 = {};
268+ struct flowi6 fl6 = {};
263269 struct neighbour * n ;
264270 u8 addr [ETH_ALEN ];
271+ struct rtable * rt ;
265272 const void * pkey ;
266273 u8 * dst , * src ;
267274
@@ -274,18 +281,89 @@ static void mlx5e_ipsec_init_macs(struct mlx5e_ipsec_sa_entry *sa_entry,
274281 case XFRM_DEV_OFFLOAD_IN :
275282 src = attrs -> dmac ;
276283 dst = attrs -> smac ;
277- pkey = & attrs -> addrs .saddr .a4 ;
284+
285+ switch (addrs -> family ) {
286+ case AF_INET :
287+ fl4 .flowi4_proto = x -> sel .proto ;
288+ fl4 .daddr = addrs -> saddr .a4 ;
289+ fl4 .saddr = addrs -> daddr .a4 ;
290+ pkey = & addrs -> saddr .a4 ;
291+ break ;
292+ case AF_INET6 :
293+ fl6 .flowi6_proto = x -> sel .proto ;
294+ memcpy (fl6 .daddr .s6_addr32 , addrs -> saddr .a6 , 16 );
295+ memcpy (fl6 .saddr .s6_addr32 , addrs -> daddr .a6 , 16 );
296+ pkey = & addrs -> saddr .a6 ;
297+ break ;
298+ default :
299+ return ;
300+ }
278301 break ;
279302 case XFRM_DEV_OFFLOAD_OUT :
280303 src = attrs -> smac ;
281304 dst = attrs -> dmac ;
282- pkey = & attrs -> addrs .daddr .a4 ;
305+ switch (addrs -> family ) {
306+ case AF_INET :
307+ fl4 .flowi4_proto = x -> sel .proto ;
308+ fl4 .daddr = addrs -> daddr .a4 ;
309+ fl4 .saddr = addrs -> saddr .a4 ;
310+ pkey = & addrs -> daddr .a4 ;
311+ break ;
312+ case AF_INET6 :
313+ fl6 .flowi6_proto = x -> sel .proto ;
314+ memcpy (fl6 .daddr .s6_addr32 , addrs -> daddr .a6 , 16 );
315+ memcpy (fl6 .saddr .s6_addr32 , addrs -> saddr .a6 , 16 );
316+ pkey = & addrs -> daddr .a6 ;
317+ break ;
318+ default :
319+ return ;
320+ }
283321 break ;
284322 default :
285323 return ;
286324 }
287325
288326 ether_addr_copy (src , addr );
327+
328+ /* Destination can refer to a routed network, so perform FIB lookup
329+ * to resolve nexthop and get its MAC. Neighbour resolution is used as
330+ * fallback.
331+ */
332+ switch (addrs -> family ) {
333+ case AF_INET :
334+ rt = ip_route_output_key (dev_net (netdev ), & fl4 );
335+ if (IS_ERR (rt ))
336+ goto neigh ;
337+
338+ if (rt -> rt_type != RTN_UNICAST ) {
339+ ip_rt_put (rt );
340+ goto neigh ;
341+ }
342+ rt_dst_entry = & rt -> dst ;
343+ break ;
344+ case AF_INET6 :
345+ rt_dst_entry = ipv6_stub -> ipv6_dst_lookup_flow (
346+ dev_net (netdev ), NULL , & fl6 , NULL );
347+ if (IS_ERR (rt_dst_entry ))
348+ goto neigh ;
349+ break ;
350+ default :
351+ return ;
352+ }
353+
354+ n = dst_neigh_lookup (rt_dst_entry , pkey );
355+ if (!n ) {
356+ dst_release (rt_dst_entry );
357+ goto neigh ;
358+ }
359+
360+ neigh_ha_snapshot (addr , n , netdev );
361+ ether_addr_copy (dst , addr );
362+ dst_release (rt_dst_entry );
363+ neigh_release (n );
364+ return ;
365+
366+ neigh :
289367 n = neigh_lookup (& arp_tbl , pkey , netdev );
290368 if (!n ) {
291369 n = neigh_create (& arp_tbl , pkey , netdev );
0 commit comments