LCOV - code coverage report
Current view: top level - include/linux - virtio_net.h (source / functions) Hit Total Coverage
Test: gcov_data_raspi2_qemu_modules_combined.info Lines: 0 55 0.0 %
Date: 2020-09-30 20:25:01 Functions: 0 2 0.0 %
Branches: 0 63 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: GPL-2.0 */
       2                 :            : #ifndef _LINUX_VIRTIO_NET_H
       3                 :            : #define _LINUX_VIRTIO_NET_H
       4                 :            : 
       5                 :            : #include <linux/if_vlan.h>
       6                 :            : #include <uapi/linux/tcp.h>
       7                 :            : #include <uapi/linux/udp.h>
       8                 :            : #include <uapi/linux/virtio_net.h>
       9                 :            : 
      10                 :            : static inline int virtio_net_hdr_set_proto(struct sk_buff *skb,
      11                 :            :                                            const struct virtio_net_hdr *hdr)
      12                 :            : {
      13   [ #  #  #  #  :          0 :         switch (hdr->gso_type & ~VIRTIO_NET_HDR_GSO_ECN) {
             #  #  #  #  
                      # ]
      14                 :            :         case VIRTIO_NET_HDR_GSO_TCPV4:
      15                 :            :         case VIRTIO_NET_HDR_GSO_UDP:
      16                 :          0 :                 skb->protocol = cpu_to_be16(ETH_P_IP);
      17                 :            :                 break;
      18                 :            :         case VIRTIO_NET_HDR_GSO_TCPV6:
      19                 :          0 :                 skb->protocol = cpu_to_be16(ETH_P_IPV6);
      20                 :            :                 break;
      21                 :            :         default:
      22                 :            :                 return -EINVAL;
      23                 :            :         }
      24                 :            : 
      25                 :            :         return 0;
      26                 :            : }
      27                 :            : 
      28                 :          0 : static inline int virtio_net_hdr_to_skb(struct sk_buff *skb,
      29                 :            :                                         const struct virtio_net_hdr *hdr,
      30                 :            :                                         bool little_endian)
      31                 :            : {
      32                 :            :         unsigned int gso_type = 0;
      33                 :            :         unsigned int thlen = 0;
      34                 :            :         unsigned int p_off = 0;
      35                 :            :         unsigned int ip_proto;
      36                 :            : 
      37         [ #  # ]:          0 :         if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) {
      38   [ #  #  #  # ]:          0 :                 switch (hdr->gso_type & ~VIRTIO_NET_HDR_GSO_ECN) {
      39                 :            :                 case VIRTIO_NET_HDR_GSO_TCPV4:
      40                 :            :                         gso_type = SKB_GSO_TCPV4;
      41                 :            :                         ip_proto = IPPROTO_TCP;
      42                 :            :                         thlen = sizeof(struct tcphdr);
      43                 :            :                         break;
      44                 :            :                 case VIRTIO_NET_HDR_GSO_TCPV6:
      45                 :            :                         gso_type = SKB_GSO_TCPV6;
      46                 :            :                         ip_proto = IPPROTO_TCP;
      47                 :            :                         thlen = sizeof(struct tcphdr);
      48                 :          0 :                         break;
      49                 :            :                 case VIRTIO_NET_HDR_GSO_UDP:
      50                 :            :                         gso_type = SKB_GSO_UDP;
      51                 :            :                         ip_proto = IPPROTO_UDP;
      52                 :            :                         thlen = sizeof(struct udphdr);
      53                 :          0 :                         break;
      54                 :            :                 default:
      55                 :            :                         return -EINVAL;
      56                 :            :                 }
      57                 :            : 
      58         [ #  # ]:          0 :                 if (hdr->gso_type & VIRTIO_NET_HDR_GSO_ECN)
      59                 :          0 :                         gso_type |= SKB_GSO_TCP_ECN;
      60                 :            : 
      61         [ #  # ]:          0 :                 if (hdr->gso_size == 0)
      62                 :            :                         return -EINVAL;
      63                 :            :         }
      64                 :            : 
      65         [ #  # ]:          0 :         if (hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) {
      66                 :          0 :                 u16 start = __virtio16_to_cpu(little_endian, hdr->csum_start);
      67                 :          0 :                 u16 off = __virtio16_to_cpu(little_endian, hdr->csum_offset);
      68                 :            : 
      69         [ #  # ]:          0 :                 if (!skb_partial_csum_set(skb, start, off))
      70                 :            :                         return -EINVAL;
      71                 :            : 
      72                 :          0 :                 p_off = skb_transport_offset(skb) + thlen;
      73         [ #  # ]:          0 :                 if (p_off > skb_headlen(skb))
      74                 :            :                         return -EINVAL;
      75                 :            :         } else {
      76                 :            :                 /* gso packets without NEEDS_CSUM do not set transport_offset.
      77                 :            :                  * probe and drop if does not match one of the above types.
      78                 :            :                  */
      79   [ #  #  #  # ]:          0 :                 if (gso_type && skb->network_header) {
      80                 :            :                         struct flow_keys_basic keys;
      81                 :            : 
      82         [ #  # ]:          0 :                         if (!skb->protocol)
      83                 :            :                                 virtio_net_hdr_set_proto(skb, hdr);
      84                 :            : retry:
      85         [ #  # ]:          0 :                         if (!skb_flow_dissect_flow_keys_basic(NULL, skb, &keys,
      86                 :            :                                                               NULL, 0, 0, 0,
      87                 :            :                                                               0)) {
      88                 :            :                                 /* UFO does not specify ipv4 or 6: try both */
      89   [ #  #  #  # ]:          0 :                                 if (gso_type & SKB_GSO_UDP &&
      90                 :          0 :                                     skb->protocol == htons(ETH_P_IP)) {
      91                 :          0 :                                         skb->protocol = htons(ETH_P_IPV6);
      92                 :          0 :                                         goto retry;
      93                 :            :                                 }
      94                 :          0 :                                 return -EINVAL;
      95                 :            :                         }
      96                 :            : 
      97                 :          0 :                         p_off = keys.control.thoff + thlen;
      98   [ #  #  #  # ]:          0 :                         if (p_off > skb_headlen(skb) ||
      99                 :          0 :                             keys.basic.ip_proto != ip_proto)
     100                 :            :                                 return -EINVAL;
     101                 :            : 
     102                 :            :                         skb_set_transport_header(skb, keys.control.thoff);
     103         [ #  # ]:          0 :                 } else if (gso_type) {
     104                 :            :                         p_off = thlen;
     105         [ #  # ]:          0 :                         if (p_off > skb_headlen(skb))
     106                 :            :                                 return -EINVAL;
     107                 :            :                 }
     108                 :            :         }
     109                 :            : 
     110         [ #  # ]:          0 :         if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) {
     111                 :          0 :                 u16 gso_size = __virtio16_to_cpu(little_endian, hdr->gso_size);
     112                 :            :                 struct skb_shared_info *shinfo = skb_shinfo(skb);
     113                 :            : 
     114                 :            :                 /* Too small packets are not really GSO ones. */
     115         [ #  # ]:          0 :                 if (skb->len - p_off > gso_size) {
     116                 :          0 :                         shinfo->gso_size = gso_size;
     117                 :          0 :                         shinfo->gso_type = gso_type;
     118                 :            : 
     119                 :            :                         /* Header must be checked, and gso_segs computed. */
     120                 :          0 :                         shinfo->gso_type |= SKB_GSO_DODGY;
     121                 :          0 :                         shinfo->gso_segs = 0;
     122                 :            :                 }
     123                 :            :         }
     124                 :            : 
     125                 :            :         return 0;
     126                 :            : }
     127                 :            : 
     128                 :          0 : static inline int virtio_net_hdr_from_skb(const struct sk_buff *skb,
     129                 :            :                                           struct virtio_net_hdr *hdr,
     130                 :            :                                           bool little_endian,
     131                 :            :                                           bool has_data_valid,
     132                 :            :                                           int vlan_hlen)
     133                 :            : {
     134                 :          0 :         memset(hdr, 0, sizeof(*hdr));   /* no info leak */
     135                 :            : 
     136         [ #  # ]:          0 :         if (skb_is_gso(skb)) {
     137                 :            :                 struct skb_shared_info *sinfo = skb_shinfo(skb);
     138                 :            : 
     139                 :            :                 /* This is a hint as to how much should be linear. */
     140                 :          0 :                 hdr->hdr_len = __cpu_to_virtio16(little_endian,
     141                 :            :                                                  skb_headlen(skb));
     142                 :          0 :                 hdr->gso_size = __cpu_to_virtio16(little_endian,
     143                 :            :                                                   sinfo->gso_size);
     144         [ #  # ]:          0 :                 if (sinfo->gso_type & SKB_GSO_TCPV4)
     145                 :          0 :                         hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
     146         [ #  # ]:          0 :                 else if (sinfo->gso_type & SKB_GSO_TCPV6)
     147                 :          0 :                         hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
     148                 :            :                 else
     149                 :            :                         return -EINVAL;
     150         [ #  # ]:          0 :                 if (sinfo->gso_type & SKB_GSO_TCP_ECN)
     151                 :          0 :                         hdr->gso_type |= VIRTIO_NET_HDR_GSO_ECN;
     152                 :            :         } else
     153                 :          0 :                 hdr->gso_type = VIRTIO_NET_HDR_GSO_NONE;
     154                 :            : 
     155         [ #  # ]:          0 :         if (skb->ip_summed == CHECKSUM_PARTIAL) {
     156                 :          0 :                 hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
     157                 :          0 :                 hdr->csum_start = __cpu_to_virtio16(little_endian,
     158                 :            :                         skb_checksum_start_offset(skb) + vlan_hlen);
     159                 :          0 :                 hdr->csum_offset = __cpu_to_virtio16(little_endian,
     160                 :            :                                 skb->csum_offset);
     161   [ #  #  #  # ]:          0 :         } else if (has_data_valid &&
     162                 :            :                    skb->ip_summed == CHECKSUM_UNNECESSARY) {
     163                 :          0 :                 hdr->flags = VIRTIO_NET_HDR_F_DATA_VALID;
     164                 :            :         } /* else everything is zero */
     165                 :            : 
     166                 :            :         return 0;
     167                 :            : }
     168                 :            : 
     169                 :            : #endif /* _LINUX_VIRTIO_NET_H */

Generated by: LCOV version 1.14