LCOV - code coverage report
Current view: top level - include/net - dst_metadata.h (source / functions) Hit Total Coverage
Test: gcov_data_raspi2_qemu_modules_combined.info Lines: 5 26 19.2 %
Date: 2020-09-30 20:25:01 Functions: 1 3 33.3 %
Branches: 9 41 22.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: GPL-2.0 */
       2                 :            : #ifndef __NET_DST_METADATA_H
       3                 :            : #define __NET_DST_METADATA_H 1
       4                 :            : 
       5                 :            : #include <linux/skbuff.h>
       6                 :            : #include <net/ip_tunnels.h>
       7                 :            : #include <net/dst.h>
       8                 :            : 
       9                 :            : enum metadata_type {
      10                 :            :         METADATA_IP_TUNNEL,
      11                 :            :         METADATA_HW_PORT_MUX,
      12                 :            : };
      13                 :            : 
      14                 :            : struct hw_port_info {
      15                 :            :         struct net_device *lower_dev;
      16                 :            :         u32 port_id;
      17                 :            : };
      18                 :            : 
      19                 :            : struct metadata_dst {
      20                 :            :         struct dst_entry                dst;
      21                 :            :         enum metadata_type              type;
      22                 :            :         union {
      23                 :            :                 struct ip_tunnel_info   tun_info;
      24                 :            :                 struct hw_port_info     port_info;
      25                 :            :         } u;
      26                 :            : };
      27                 :            : 
      28                 :            : static inline struct metadata_dst *skb_metadata_dst(const struct sk_buff *skb)
      29                 :            : {
      30                 :            :         struct metadata_dst *md_dst = (struct metadata_dst *) skb_dst(skb);
      31                 :            : 
      32   [ -  +  #  #  :       2638 :         if (md_dst && md_dst->dst.flags & DST_METADATA)
             #  #  #  # ]
      33                 :            :                 return md_dst;
      34                 :            : 
      35                 :            :         return NULL;
      36                 :            : }
      37                 :            : 
      38                 :            : static inline struct ip_tunnel_info *
      39                 :       2638 : skb_tunnel_info(const struct sk_buff *skb)
      40                 :            : {
      41                 :            :         struct metadata_dst *md_dst = skb_metadata_dst(skb);
      42                 :            :         struct dst_entry *dst;
      43                 :            : 
      44   [ -  +  #  # ]:       2638 :         if (md_dst && md_dst->type == METADATA_IP_TUNNEL)
      45                 :          0 :                 return &md_dst->u.tun_info;
      46                 :            : 
      47                 :            :         dst = skb_dst(skb);
      48   [ -  +  #  # ]:       2638 :         if (dst && dst->lwtstate)
      49                 :          0 :                 return lwt_tun_info(dst->lwtstate);
      50                 :            : 
      51                 :            :         return NULL;
      52                 :            : }
      53                 :            : 
      54                 :            : static inline bool skb_valid_dst(const struct sk_buff *skb)
      55                 :            : {
      56                 :            :         struct dst_entry *dst = skb_dst(skb);
      57                 :            : 
      58   [ +  +  -  +  :      17914 :         return dst && !(dst->flags & DST_METADATA);
             +  +  -  + ]
      59                 :            : }
      60                 :            : 
      61                 :          0 : static inline int skb_metadata_dst_cmp(const struct sk_buff *skb_a,
      62                 :            :                                        const struct sk_buff *skb_b)
      63                 :            : {
      64                 :            :         const struct metadata_dst *a, *b;
      65                 :            : 
      66         [ #  # ]:          0 :         if (!(skb_a->_skb_refdst | skb_b->_skb_refdst))
      67                 :            :                 return 0;
      68                 :            : 
      69                 :            :         a = (const struct metadata_dst *) skb_dst(skb_a);
      70                 :            :         b = (const struct metadata_dst *) skb_dst(skb_b);
      71                 :            : 
      72   [ #  #  #  # ]:          0 :         if (!a != !b || a->type != b->type)
      73                 :            :                 return 1;
      74                 :            : 
      75      [ #  #  # ]:          0 :         switch (a->type) {
      76                 :            :         case METADATA_HW_PORT_MUX:
      77                 :          0 :                 return memcmp(&a->u.port_info, &b->u.port_info,
      78                 :            :                               sizeof(a->u.port_info));
      79                 :            :         case METADATA_IP_TUNNEL:
      80                 :          0 :                 return memcmp(&a->u.tun_info, &b->u.tun_info,
      81                 :            :                               sizeof(a->u.tun_info) +
      82                 :          0 :                                          a->u.tun_info.options_len);
      83                 :            :         default:
      84                 :            :                 return 1;
      85                 :            :         }
      86                 :            : }
      87                 :            : 
      88                 :            : void metadata_dst_free(struct metadata_dst *);
      89                 :            : struct metadata_dst *metadata_dst_alloc(u8 optslen, enum metadata_type type,
      90                 :            :                                         gfp_t flags);
      91                 :            : void metadata_dst_free_percpu(struct metadata_dst __percpu *md_dst);
      92                 :            : struct metadata_dst __percpu *
      93                 :            : metadata_dst_alloc_percpu(u8 optslen, enum metadata_type type, gfp_t flags);
      94                 :            : 
      95                 :            : static inline struct metadata_dst *tun_rx_dst(int md_size)
      96                 :            : {
      97                 :            :         struct metadata_dst *tun_dst;
      98                 :            : 
      99                 :            :         tun_dst = metadata_dst_alloc(md_size, METADATA_IP_TUNNEL, GFP_ATOMIC);
     100                 :            :         if (!tun_dst)
     101                 :            :                 return NULL;
     102                 :            : 
     103                 :            :         tun_dst->u.tun_info.options_len = 0;
     104                 :            :         tun_dst->u.tun_info.mode = 0;
     105                 :            :         return tun_dst;
     106                 :            : }
     107                 :            : 
     108                 :          0 : static inline struct metadata_dst *tun_dst_unclone(struct sk_buff *skb)
     109                 :            : {
     110                 :            :         struct metadata_dst *md_dst = skb_metadata_dst(skb);
     111                 :            :         int md_size;
     112                 :            :         struct metadata_dst *new_md;
     113                 :            : 
     114   [ #  #  #  # ]:          0 :         if (!md_dst || md_dst->type != METADATA_IP_TUNNEL)
     115                 :            :                 return ERR_PTR(-EINVAL);
     116                 :            : 
     117                 :          0 :         md_size = md_dst->u.tun_info.options_len;
     118                 :          0 :         new_md = metadata_dst_alloc(md_size, METADATA_IP_TUNNEL, GFP_ATOMIC);
     119         [ #  # ]:          0 :         if (!new_md)
     120                 :            :                 return ERR_PTR(-ENOMEM);
     121                 :            : 
     122                 :          0 :         memcpy(&new_md->u.tun_info, &md_dst->u.tun_info,
     123                 :            :                sizeof(struct ip_tunnel_info) + md_size);
     124                 :          0 :         skb_dst_drop(skb);
     125                 :          0 :         dst_hold(&new_md->dst);
     126                 :            :         skb_dst_set(skb, &new_md->dst);
     127                 :          0 :         return new_md;
     128                 :            : }
     129                 :            : 
     130                 :            : static inline struct ip_tunnel_info *skb_tunnel_info_unclone(struct sk_buff *skb)
     131                 :            : {
     132                 :            :         struct metadata_dst *dst;
     133                 :            : 
     134                 :          0 :         dst = tun_dst_unclone(skb);
     135         [ #  # ]:          0 :         if (IS_ERR(dst))
     136                 :            :                 return NULL;
     137                 :            : 
     138                 :          0 :         return &dst->u.tun_info;
     139                 :            : }
     140                 :            : 
     141                 :            : static inline struct metadata_dst *__ip_tun_set_dst(__be32 saddr,
     142                 :            :                                                     __be32 daddr,
     143                 :            :                                                     __u8 tos, __u8 ttl,
     144                 :            :                                                     __be16 tp_dst,
     145                 :            :                                                     __be16 flags,
     146                 :            :                                                     __be64 tunnel_id,
     147                 :            :                                                     int md_size)
     148                 :            : {
     149                 :            :         struct metadata_dst *tun_dst;
     150                 :            : 
     151                 :            :         tun_dst = tun_rx_dst(md_size);
     152                 :            :         if (!tun_dst)
     153                 :            :                 return NULL;
     154                 :            : 
     155                 :            :         ip_tunnel_key_init(&tun_dst->u.tun_info.key,
     156                 :            :                            saddr, daddr, tos, ttl,
     157                 :            :                            0, 0, tp_dst, tunnel_id, flags);
     158                 :            :         return tun_dst;
     159                 :            : }
     160                 :            : 
     161                 :            : static inline struct metadata_dst *ip_tun_rx_dst(struct sk_buff *skb,
     162                 :            :                                                  __be16 flags,
     163                 :            :                                                  __be64 tunnel_id,
     164                 :            :                                                  int md_size)
     165                 :            : {
     166                 :            :         const struct iphdr *iph = ip_hdr(skb);
     167                 :            : 
     168                 :            :         return __ip_tun_set_dst(iph->saddr, iph->daddr, iph->tos, iph->ttl,
     169                 :            :                                 0, flags, tunnel_id, md_size);
     170                 :            : }
     171                 :            : 
     172                 :            : static inline struct metadata_dst *__ipv6_tun_set_dst(const struct in6_addr *saddr,
     173                 :            :                                                       const struct in6_addr *daddr,
     174                 :            :                                                       __u8 tos, __u8 ttl,
     175                 :            :                                                       __be16 tp_dst,
     176                 :            :                                                       __be32 label,
     177                 :            :                                                       __be16 flags,
     178                 :            :                                                       __be64 tunnel_id,
     179                 :            :                                                       int md_size)
     180                 :            : {
     181                 :            :         struct metadata_dst *tun_dst;
     182                 :            :         struct ip_tunnel_info *info;
     183                 :            : 
     184                 :            :         tun_dst = tun_rx_dst(md_size);
     185                 :            :         if (!tun_dst)
     186                 :            :                 return NULL;
     187                 :            : 
     188                 :            :         info = &tun_dst->u.tun_info;
     189                 :            :         info->mode = IP_TUNNEL_INFO_IPV6;
     190                 :            :         info->key.tun_flags = flags;
     191                 :            :         info->key.tun_id = tunnel_id;
     192                 :            :         info->key.tp_src = 0;
     193                 :            :         info->key.tp_dst = tp_dst;
     194                 :            : 
     195                 :            :         info->key.u.ipv6.src = *saddr;
     196                 :            :         info->key.u.ipv6.dst = *daddr;
     197                 :            : 
     198                 :            :         info->key.tos = tos;
     199                 :            :         info->key.ttl = ttl;
     200                 :            :         info->key.label = label;
     201                 :            : 
     202                 :            :         return tun_dst;
     203                 :            : }
     204                 :            : 
     205                 :            : static inline struct metadata_dst *ipv6_tun_rx_dst(struct sk_buff *skb,
     206                 :            :                                                    __be16 flags,
     207                 :            :                                                    __be64 tunnel_id,
     208                 :            :                                                    int md_size)
     209                 :            : {
     210                 :            :         const struct ipv6hdr *ip6h = ipv6_hdr(skb);
     211                 :            : 
     212                 :            :         return __ipv6_tun_set_dst(&ip6h->saddr, &ip6h->daddr,
     213                 :            :                                   ipv6_get_dsfield(ip6h), ip6h->hop_limit,
     214                 :            :                                   0, ip6_flowlabel(ip6h), flags, tunnel_id,
     215                 :            :                                   md_size);
     216                 :            : }
     217                 :            : #endif /* __NET_DST_METADATA_H */

Generated by: LCOV version 1.14