LCOV - code coverage report
Current view: top level - include/net - dst_metadata.h (source / functions) Hit Total Coverage
Test: landlock.info Lines: 15 47 31.9 %
Date: 2021-04-22 12:43:58 Functions: 4 5 80.0 %

          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          24 : static inline struct metadata_dst *skb_metadata_dst(const struct sk_buff *skb)
      29             : {
      30          24 :         struct metadata_dst *md_dst = (struct metadata_dst *) skb_dst(skb);
      31             : 
      32          24 :         if (md_dst && md_dst->dst.flags & DST_METADATA)
      33           0 :                 return md_dst;
      34             : 
      35             :         return NULL;
      36             : }
      37             : 
      38             : static inline struct ip_tunnel_info *
      39          24 : skb_tunnel_info(const struct sk_buff *skb)
      40             : {
      41          24 :         struct metadata_dst *md_dst = skb_metadata_dst(skb);
      42          24 :         struct dst_entry *dst;
      43             : 
      44          24 :         if (md_dst && md_dst->type == METADATA_IP_TUNNEL)
      45           0 :                 return &md_dst->u.tun_info;
      46             : 
      47          24 :         dst = skb_dst(skb);
      48          24 :         if (dst && dst->lwtstate)
      49           0 :                 return lwt_tun_info(dst->lwtstate);
      50             : 
      51             :         return NULL;
      52             : }
      53             : 
      54         454 : static inline bool skb_valid_dst(const struct sk_buff *skb)
      55             : {
      56         454 :         struct dst_entry *dst = skb_dst(skb);
      57             : 
      58         454 :         return dst && !(dst->flags & DST_METADATA);
      59             : }
      60             : 
      61         269 : static inline int skb_metadata_dst_cmp(const struct sk_buff *skb_a,
      62             :                                        const struct sk_buff *skb_b)
      63             : {
      64         269 :         const struct metadata_dst *a, *b;
      65             : 
      66         269 :         if (!(skb_a->_skb_refdst | skb_b->_skb_refdst))
      67             :                 return 0;
      68             : 
      69           0 :         a = (const struct metadata_dst *) skb_dst(skb_a);
      70           0 :         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           0 :         case METADATA_HW_PORT_MUX:
      77           0 :                 return memcmp(&a->u.port_info, &b->u.port_info,
      78             :                               sizeof(a->u.port_info));
      79           0 :         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           0 :         struct metadata_dst *md_dst = skb_metadata_dst(skb);
     111           0 :         int md_size;
     112           0 :         struct metadata_dst *new_md;
     113             : 
     114           0 :         if (!md_dst || md_dst->type != METADATA_IP_TUNNEL)
     115           0 :                 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           0 :                 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           0 :         skb_dst_set(skb, &new_md->dst);
     127           0 :         return new_md;
     128             : }
     129             : 
     130           0 : static inline struct ip_tunnel_info *skb_tunnel_info_unclone(struct sk_buff *skb)
     131             : {
     132           0 :         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