github.com/cilium/cilium@v1.16.2/bpf/lib/eth.h (about)

     1  /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
     2  /* Copyright Authors of Cilium */
     3  
     4  #pragma once
     5  
     6  #include <linux/if_ether.h>
     7  
     8  #ifndef ETH_HLEN
     9  #define ETH_HLEN __ETH_HLEN
    10  #endif
    11  
    12  #ifndef ETH_ALEN
    13  #define ETH_ALEN 6
    14  #endif
    15  
    16  union macaddr {
    17  	struct {
    18  		__u32 p1;
    19  		__u16 p2;
    20  	};
    21  	__u8 addr[6];
    22  };
    23  
    24  static __always_inline int eth_addrcmp(const union macaddr *a,
    25  				       const union macaddr *b)
    26  {
    27  	int tmp;
    28  
    29  	tmp = a->p1 - b->p1;
    30  	if (!tmp)
    31  		tmp = a->p2 - b->p2;
    32  
    33  	return tmp;
    34  }
    35  
    36  static __always_inline int eth_is_bcast(const union macaddr *a)
    37  {
    38  	union macaddr bcast;
    39  
    40  	bcast.p1 = 0xffffffff;
    41  	bcast.p2 = 0xffff;
    42  
    43  	if (!eth_addrcmp(a, &bcast))
    44  		return 1;
    45  	else
    46  		return 0;
    47  }
    48  
    49  static __always_inline bool eth_is_supported_ethertype(__be16 proto)
    50  {
    51  	/* non-Ethernet II unsupported */
    52  	return proto >= bpf_htons(ETH_P_802_3_MIN);
    53  }
    54  
    55  static __always_inline int eth_load_saddr(struct __ctx_buff *ctx, __u8 *mac,
    56  					  int off)
    57  {
    58  	return ctx_load_bytes(ctx, off + ETH_ALEN, mac, ETH_ALEN);
    59  }
    60  
    61  static __always_inline int eth_store_saddr_aligned(struct __ctx_buff *ctx,
    62  						   const __u8 *mac, int off)
    63  {
    64  	return ctx_store_bytes(ctx, off + ETH_ALEN, mac, ETH_ALEN, 0);
    65  }
    66  
    67  static __always_inline int eth_store_saddr(struct __ctx_buff *ctx,
    68  					   const __u8 *mac, int off)
    69  {
    70  #if !CTX_DIRECT_WRITE_OK
    71  	return eth_store_saddr_aligned(ctx, mac, off);
    72  #else
    73  	void *data_end = ctx_data_end(ctx);
    74  	void *data = ctx_data(ctx);
    75  
    76  	if (ctx_no_room(data + off + ETH_ALEN * 2, data_end))
    77  		return -EFAULT;
    78  	/* Need to use builtin here since mac came potentially from
    79  	 * struct bpf_fib_lookup where it's not aligned on stack. :(
    80  	 */
    81  	__bpf_memcpy_builtin(data + off + ETH_ALEN, mac, ETH_ALEN);
    82  	return 0;
    83  #endif
    84  }
    85  
    86  static __always_inline int eth_load_daddr(struct __ctx_buff *ctx, __u8 *mac,
    87  					  int off)
    88  {
    89  	return ctx_load_bytes(ctx, off, mac, ETH_ALEN);
    90  }
    91  
    92  static __always_inline int eth_store_daddr_aligned(struct __ctx_buff *ctx,
    93  						   const __u8 *mac, int off)
    94  {
    95  	return ctx_store_bytes(ctx, off, mac, ETH_ALEN, 0);
    96  }
    97  
    98  static __always_inline int eth_store_daddr(struct __ctx_buff *ctx,
    99  					   const __u8 *mac, int off)
   100  {
   101  #if !CTX_DIRECT_WRITE_OK
   102  	return eth_store_daddr_aligned(ctx, mac, off);
   103  #else
   104  	void *data_end = ctx_data_end(ctx);
   105  	void *data = ctx_data(ctx);
   106  
   107  	if (ctx_no_room(data + off + ETH_ALEN, data_end))
   108  		return -EFAULT;
   109  	/* Need to use builtin here since mac came potentially from
   110  	 * struct bpf_fib_lookup where it's not aligned on stack. :(
   111  	 */
   112  	__bpf_memcpy_builtin(data + off, mac, ETH_ALEN);
   113  	return 0;
   114  #endif
   115  }
   116  
   117  static __always_inline int eth_store_proto(struct __ctx_buff *ctx,
   118  					   const __u16 proto, int off)
   119  {
   120  	return ctx_store_bytes(ctx, off + ETH_ALEN + ETH_ALEN,
   121  			       &proto, sizeof(proto), 0);
   122  }