root/tools/testing/selftests/net/txring_overwrite.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. build_packet
  2. setup_rx
  3. setup_tx
  4. send_pkt
  5. read_verify_pkt
  6. main

   1 // SPDX-License-Identifier: GPL-2.0
   2 
   3 /*
   4  * Verify that consecutive sends over packet tx_ring are mirrored
   5  * with their original content intact.
   6  */
   7 
   8 #define _GNU_SOURCE
   9 
  10 #include <arpa/inet.h>
  11 #include <assert.h>
  12 #include <error.h>
  13 #include <errno.h>
  14 #include <fcntl.h>
  15 #include <linux/filter.h>
  16 #include <linux/if_packet.h>
  17 #include <net/ethernet.h>
  18 #include <net/if.h>
  19 #include <netinet/in.h>
  20 #include <netinet/ip.h>
  21 #include <netinet/udp.h>
  22 #include <poll.h>
  23 #include <pthread.h>
  24 #include <sched.h>
  25 #include <sys/ioctl.h>
  26 #include <sys/mman.h>
  27 #include <sys/socket.h>
  28 #include <sys/time.h>
  29 #include <sys/types.h>
  30 #include <sys/utsname.h>
  31 #include <stdbool.h>
  32 #include <stdint.h>
  33 #include <stdio.h>
  34 #include <stdlib.h>
  35 #include <string.h>
  36 #include <unistd.h>
  37 
  38 const int eth_off = TPACKET_HDRLEN - sizeof(struct sockaddr_ll);
  39 const int cfg_frame_size = 1000;
  40 
  41 static void build_packet(void *buffer, size_t blen, char payload_char)
  42 {
  43         struct udphdr *udph;
  44         struct ethhdr *eth;
  45         struct iphdr *iph;
  46         size_t off = 0;
  47 
  48         memset(buffer, 0, blen);
  49 
  50         eth = buffer;
  51         eth->h_proto = htons(ETH_P_IP);
  52 
  53         off += sizeof(*eth);
  54         iph = buffer + off;
  55         iph->ttl        = 8;
  56         iph->ihl        = 5;
  57         iph->version    = 4;
  58         iph->saddr      = htonl(INADDR_LOOPBACK);
  59         iph->daddr      = htonl(INADDR_LOOPBACK + 1);
  60         iph->protocol   = IPPROTO_UDP;
  61         iph->tot_len    = htons(blen - off);
  62         iph->check      = 0;
  63 
  64         off += sizeof(*iph);
  65         udph = buffer + off;
  66         udph->dest      = htons(8000);
  67         udph->source    = htons(8001);
  68         udph->len       = htons(blen - off);
  69         udph->check     = 0;
  70 
  71         off += sizeof(*udph);
  72         memset(buffer + off, payload_char, blen - off);
  73 }
  74 
  75 static int setup_rx(void)
  76 {
  77         int fdr;
  78 
  79         fdr = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP));
  80         if (fdr == -1)
  81                 error(1, errno, "socket r");
  82 
  83         return fdr;
  84 }
  85 
  86 static int setup_tx(char **ring)
  87 {
  88         struct sockaddr_ll laddr = {};
  89         struct tpacket_req req = {};
  90         int fdt;
  91 
  92         fdt = socket(PF_PACKET, SOCK_RAW, 0);
  93         if (fdt == -1)
  94                 error(1, errno, "socket t");
  95 
  96         laddr.sll_family = AF_PACKET;
  97         laddr.sll_protocol = htons(0);
  98         laddr.sll_ifindex = if_nametoindex("lo");
  99         if (!laddr.sll_ifindex)
 100                 error(1, errno, "if_nametoindex");
 101 
 102         if (bind(fdt, (void *)&laddr, sizeof(laddr)))
 103                 error(1, errno, "bind fdt");
 104 
 105         req.tp_block_size = getpagesize();
 106         req.tp_block_nr   = 1;
 107         req.tp_frame_size = getpagesize();
 108         req.tp_frame_nr   = 1;
 109 
 110         if (setsockopt(fdt, SOL_PACKET, PACKET_TX_RING,
 111                        (void *)&req, sizeof(req)))
 112                 error(1, errno, "setsockopt ring");
 113 
 114         *ring = mmap(0, req.tp_block_size * req.tp_block_nr,
 115                      PROT_READ | PROT_WRITE, MAP_SHARED, fdt, 0);
 116         if (*ring == MAP_FAILED)
 117                 error(1, errno, "mmap");
 118 
 119         return fdt;
 120 }
 121 
 122 static void send_pkt(int fdt, void *slot, char payload_char)
 123 {
 124         struct tpacket_hdr *header = slot;
 125         int ret;
 126 
 127         while (header->tp_status != TP_STATUS_AVAILABLE)
 128                 usleep(1000);
 129 
 130         build_packet(slot + eth_off, cfg_frame_size, payload_char);
 131 
 132         header->tp_len = cfg_frame_size;
 133         header->tp_status = TP_STATUS_SEND_REQUEST;
 134 
 135         ret = sendto(fdt, NULL, 0, 0, NULL, 0);
 136         if (ret == -1)
 137                 error(1, errno, "kick tx");
 138 }
 139 
 140 static int read_verify_pkt(int fdr, char payload_char)
 141 {
 142         char buf[100];
 143         int ret;
 144 
 145         ret = read(fdr, buf, sizeof(buf));
 146         if (ret != sizeof(buf))
 147                 error(1, errno, "read");
 148 
 149         if (buf[60] != payload_char) {
 150                 printf("wrong pattern: 0x%x != 0x%x\n", buf[60], payload_char);
 151                 return 1;
 152         }
 153 
 154         printf("read: %c (0x%x)\n", buf[60], buf[60]);
 155         return 0;
 156 }
 157 
 158 int main(int argc, char **argv)
 159 {
 160         const char payload_patterns[] = "ab";
 161         char *ring;
 162         int fdr, fdt, ret = 0;
 163 
 164         fdr = setup_rx();
 165         fdt = setup_tx(&ring);
 166 
 167         send_pkt(fdt, ring, payload_patterns[0]);
 168         send_pkt(fdt, ring, payload_patterns[1]);
 169 
 170         ret |= read_verify_pkt(fdr, payload_patterns[0]);
 171         ret |= read_verify_pkt(fdr, payload_patterns[1]);
 172 
 173         if (close(fdt))
 174                 error(1, errno, "close t");
 175         if (close(fdr))
 176                 error(1, errno, "close r");
 177 
 178         return ret;
 179 }

/* [<][>][^][v][top][bottom][index][help] */