Line data Source code
1 : #include <rte_ethdev.h>
2 :
3 : #include "dpdklibs/ipv4_addr.hpp"
4 : #include "dpdklibs/udp/Utils.hpp"
5 : #include "dpdklibs/udp/PacketCtor.hpp"
6 :
7 : #include "detdataformats/DAQEthHeader.hpp"
8 :
9 : #define IPV4_VERSION 4
10 :
11 : //DEFAULT_TTL = 8 -> TTL on wireshark 5
12 : //DEFAULT_TTL = 5 -> TTL on wireshark 2
13 : //DEFAULT_TTL = 4 -> TTL on wireshark 1
14 :
15 : namespace dunedaq {
16 : namespace dpdklibs {
17 : namespace udp {
18 :
19 : enum {
20 : MIN_TOS = 0,
21 : DEFAULT_TOS = MIN_TOS,
22 : DEFAULT_TTL = 8
23 : };
24 : //// Defined as static in DPDK
25 0 : static int8_t get_xdigit(char ch)
26 : {
27 0 : if (ch >= '0' && ch <= '9')
28 0 : return ch - '0';
29 0 : if (ch >= 'a' && ch <= 'f')
30 0 : return ch - 'a' + 10;
31 0 : if (ch >= 'A' && ch <= 'F')
32 0 : return ch - 'A' + 10;
33 : return -1;
34 : }
35 :
36 :
37 0 : bool get_ether_addr6(const char *s0, struct rte_ether_addr *ea)
38 : {
39 0 : const char *s = s0;
40 0 : int i;
41 :
42 0 : for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) {
43 0 : int8_t x;
44 :
45 0 : x = get_xdigit(*s++);
46 0 : if (x < 0)
47 : return false;
48 :
49 0 : ea->addr_bytes[i] = x << 4;
50 0 : x = get_xdigit(*s++);
51 0 : if (x < 0)
52 : return false;
53 0 : ea->addr_bytes[i] |= x;
54 :
55 0 : if (i < RTE_ETHER_ADDR_LEN - 1 &&
56 0 : *s++ != ':')
57 : return false;
58 : }
59 :
60 : /* return true if at end of string */
61 0 : return *s == '\0';
62 : }
63 :
64 :
65 : rte_le16_t
66 0 : packet_fill(struct ipv4_udp_packet_hdr * packet_hdr)
67 : {
68 : //rte_le16_t total_length = 64;
69 : //char message[] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
70 :
71 :
72 0 : rte_le16_t total_length = 2000;
73 0 : char message[] = "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE";
74 :
75 :
76 :
77 0 : char * payload = (char *)(packet_hdr + 1);
78 0 : memcpy(payload, message, total_length);
79 0 : return total_length;
80 : }
81 :
82 :
83 : /**************************************************************************//**
84 : *
85 : * pktgen_udp_hdr_ctor - UDP header constructor routine.
86 : *
87 : * DESCRIPTION
88 : * Construct the UDP header in a packer buffer.
89 : *
90 : * RETURNS: next header location
91 : *
92 : * SEE ALSO:
93 : */
94 : void
95 0 : pktgen_udp_hdr_ctor(struct ipv4_udp_packet_hdr * packet_hdr, rte_le16_t packet_len, int sport, int dport)
96 : {
97 0 : packet_hdr->udp_hdr.dgram_len = rte_cpu_to_be_16(packet_len);
98 :
99 0 : packet_hdr->udp_hdr.src_port = rte_cpu_to_be_16(sport);
100 0 : packet_hdr->udp_hdr.dst_port = rte_cpu_to_be_16(dport);
101 :
102 0 : packet_hdr->udp_hdr.dgram_cksum = 0; // checksum must be set to 0 in the L4 header by the caller.
103 : //TODO I think that the payload must be already there and continuous in memory..
104 0 : return ;
105 : }
106 :
107 : /**************************************************************************//**
108 : *
109 : * pktgen_ipv4_ctor - Construct the IPv4 header for a packet
110 : *
111 : * DESCRIPTION
112 : * Constructor for the IPv4 header for a given packet.
113 : *
114 : * RETURNS: N/A
115 : *
116 : * SEE ALSO:
117 : */
118 : void
119 0 : pktgen_ipv4_ctor(struct ipv4_udp_packet_hdr * packet_hdr, rte_le16_t packet_len, const std::string& src_ip_addr, const std::string& dst_ip_addr)
120 : {
121 : /* IPv4 Header constructor */
122 :
123 : /* Zero out the header space */
124 0 : memset((char *) &packet_hdr->ipv4_hdr, 0, sizeof(struct rte_ipv4_hdr));
125 :
126 0 : IpAddr src(src_ip_addr);
127 0 : IpAddr dst(dst_ip_addr);
128 :
129 0 : struct ipaddr src_reversed_order;
130 0 : src_reversed_order.addr_bytes[3] = src.addr_bytes[0];
131 0 : src_reversed_order.addr_bytes[2] = src.addr_bytes[1];
132 0 : src_reversed_order.addr_bytes[1] = src.addr_bytes[2];
133 0 : src_reversed_order.addr_bytes[0] = src.addr_bytes[3];
134 :
135 0 : struct ipaddr dst_reversed_order;
136 0 : dst_reversed_order.addr_bytes[3] = dst.addr_bytes[0];
137 0 : dst_reversed_order.addr_bytes[2] = dst.addr_bytes[1];
138 0 : dst_reversed_order.addr_bytes[1] = dst.addr_bytes[2];
139 0 : dst_reversed_order.addr_bytes[0] = dst.addr_bytes[3];
140 :
141 0 : rte_le32_t src_addr_ser = *((rte_le32_t *) &src_reversed_order);
142 0 : rte_le32_t dst_addr_ser = *((rte_le32_t *) &dst_reversed_order);
143 :
144 0 : packet_hdr->ipv4_hdr.src_addr = rte_cpu_to_be_32(src_addr_ser);
145 0 : packet_hdr->ipv4_hdr.dst_addr = rte_cpu_to_be_32(dst_addr_ser);
146 :
147 0 : packet_hdr->ipv4_hdr.version_ihl = (IPV4_VERSION << 4) | (sizeof(struct rte_ipv4_hdr) / 4);
148 :
149 0 : packet_hdr->ipv4_hdr.total_length = rte_cpu_to_be_16(packet_len); // Payload + udp_hdr + iphdr
150 0 : packet_hdr->ipv4_hdr.time_to_live = DEFAULT_TTL;
151 0 : packet_hdr->ipv4_hdr.type_of_service = DEFAULT_TOS;
152 :
153 : // https://perso.telecom-paristech.fr/drossi/paper/rossi17ipid.pdf
154 0 : packet_hdr->ipv4_hdr.packet_id = rte_cpu_to_be_16(0); // I put a constant here..
155 0 : packet_hdr->ipv4_hdr.fragment_offset = 0;
156 0 : packet_hdr->ipv4_hdr.next_proto_id = IPPROTO_UDP;
157 :
158 0 : packet_hdr->ipv4_hdr.hdr_checksum = 0;
159 : //packet_hdr->ipv4_hdr.hdr_checksum = rte_ipv4_cksum(&packet_hdr->ipv4_hdr);
160 :
161 : //UDP checksum
162 0 : packet_hdr->udp_hdr.dgram_cksum = 0;
163 : //packet_hdr->udp_hdr.dgram_cksum = rte_ipv4_udptcp_cksum(&packet_hdr->ipv4_hdr, (void *) &packet_hdr->udp_hdr);
164 : //if (packet_hdr->udp_hdr.dgram_cksum == 0) {
165 : // packet_hdr->udp_hdr.dgram_cksum = 0xFFFF;
166 : //}
167 0 : return ;
168 : }
169 :
170 :
171 : /**************************************************************************//**
172 : *
173 : * pktgen_ether_hdr_ctor - Ethernet header constructor routine.
174 : *
175 : * DESCRIPTION
176 : * Construct the ethernet header for a given packet buffer.
177 : *
178 : * RETURNS: Pointer to memory after the ethernet header.
179 : *
180 : * SEE ALSO:
181 : */
182 : void
183 0 : pktgen_ether_hdr_ctor(struct ipv4_udp_packet_hdr * packet_hdr, const std::string& router_mac_address, const int port_id)
184 : {
185 : //pg_ether_addr_copy(&pkt->eth_src_addr, ð->src_addr);
186 : //pg_ether_addr_copy(&pkt->eth_dst_addr, ð->dst_addr);
187 :
188 : /* src and dest addr */
189 : // See definition dpdk-20.08/lib/librte_net/rte_ether.c is defined as static -> not exposed to the lib... redefining here
190 :
191 0 : get_ether_addr6(router_mac_address.c_str(), &packet_hdr->eth_hdr.dst_addr);
192 :
193 0 : rte_eth_macaddr_get(port_id, &packet_hdr->eth_hdr.src_addr);
194 :
195 : /* normal ethernet header */
196 0 : packet_hdr->eth_hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
197 0 : return;
198 : }
199 :
200 :
201 :
202 0 : void construct_packets_for_burst(const int port_id, const std::string& dst_mac_addr, const int payload_bytes, const int burst_size, rte_mbuf** bufs) {
203 0 : struct ipv4_udp_packet_hdr packet_hdr;
204 :
205 0 : constexpr int eth_header_bytes = 14;
206 0 : constexpr int udp_header_bytes = 8;
207 0 : constexpr int ipv4_header_bytes = 20;
208 :
209 0 : int eth_packet_bytes = eth_header_bytes + ipv4_header_bytes + udp_header_bytes + sizeof(detdataformats::DAQEthHeader) + payload_bytes;
210 0 : int ipv4_packet_bytes = eth_packet_bytes - eth_header_bytes;
211 0 : int udp_datagram_bytes = ipv4_packet_bytes - ipv4_header_bytes;
212 :
213 : // Get info for the ethernet header (protocol stack level 2)
214 0 : pktgen_ether_hdr_ctor(&packet_hdr, dst_mac_addr, port_id);
215 :
216 : // Get info for the internet header (protocol stack level 3)
217 0 : pktgen_ipv4_ctor(&packet_hdr, ipv4_packet_bytes);
218 :
219 : // Get info for the UDP header (protocol stack level 4)
220 0 : pktgen_udp_hdr_ctor(&packet_hdr, udp_datagram_bytes);
221 :
222 0 : detdataformats::DAQEthHeader daqethheader_obj;
223 0 : set_daqethheader_test_values(daqethheader_obj);
224 :
225 0 : void* dataloc = nullptr;
226 0 : for (int i_pkt = 0; i_pkt < burst_size; ++i_pkt) {
227 :
228 0 : dataloc = rte_pktmbuf_mtod(bufs[i_pkt], char*);
229 0 : rte_memcpy(dataloc, &packet_hdr, sizeof(packet_hdr));
230 :
231 0 : dataloc = rte_pktmbuf_mtod_offset(bufs[i_pkt], char*, sizeof(packet_hdr));
232 0 : rte_memcpy(dataloc, &daqethheader_obj, sizeof(daqethheader_obj));
233 :
234 0 : bufs[i_pkt]->pkt_len = eth_packet_bytes;
235 0 : bufs[i_pkt]->data_len = eth_packet_bytes;
236 : }
237 0 : }
238 :
239 :
240 : } // namespace udp
241 : } // namespace dpdklibs
242 : } // namespace dunedaq
|