DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
PacketCtor.cpp
Go to the documentation of this file.
1#include <rte_ethdev.h>
2
6
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
15namespace dunedaq {
16namespace dpdklibs {
17namespace udp {
18
19enum
20{
24};
26static int8_t
27get_xdigit(char ch)
28{
29 if (ch >= '0' && ch <= '9')
30 return ch - '0';
31 if (ch >= 'a' && ch <= 'f')
32 return ch - 'a' + 10;
33 if (ch >= 'A' && ch <= 'F')
34 return ch - 'A' + 10;
35 return -1;
36}
37
38bool
39get_ether_addr6(const char* s0, struct rte_ether_addr* ea)
40{
41 const char* s = s0;
42 int i;
43
44 for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) {
45 int8_t x;
46
47 x = get_xdigit(*s++);
48 if (x < 0)
49 return false;
50
51 ea->addr_bytes[i] = x << 4;
52 x = get_xdigit(*s++);
53 if (x < 0)
54 return false;
55 ea->addr_bytes[i] |= x;
56
57 if (i < RTE_ETHER_ADDR_LEN - 1 && *s++ != ':')
58 return false;
59 }
60
61 /* return true if at end of string */
62 return *s == '\0';
63}
64
65rte_le16_t
67{
68 // rte_le16_t total_length = 64;
69 // char message[] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
70
71 rte_le16_t total_length = 2000;
72 char message[] =
73 "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
74 "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
75 "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
76 "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
77 "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
78 "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
79 "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
80 "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
81 "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
82 "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
83 "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
84 "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
85 "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
86 "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
87 "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
88 "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
89 "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
90 "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE";
91
92 char* payload = (char*)(packet_hdr + 1);
93 memcpy(payload, message, total_length);
94 return total_length;
95}
96
97/**************************************************************************/
110void
111pktgen_udp_hdr_ctor(struct ipv4_udp_packet_hdr* packet_hdr, rte_le16_t packet_len, int sport, int dport)
112{
113 packet_hdr->udp_hdr.dgram_len = rte_cpu_to_be_16(packet_len);
114
115 packet_hdr->udp_hdr.src_port = rte_cpu_to_be_16(sport);
116 packet_hdr->udp_hdr.dst_port = rte_cpu_to_be_16(dport);
117
118 packet_hdr->udp_hdr.dgram_cksum = 0; // checksum must be set to 0 in the L4 header by the caller.
119 // TODO I think that the payload must be already there and continuous in memory..
120 return;
121}
122
123/**************************************************************************/
136void
138 rte_le16_t packet_len,
139 const std::string& src_ip_addr,
140 const std::string& dst_ip_addr)
141{
142 /* IPv4 Header constructor */
143
144 /* Zero out the header space */
145 memset((char*)&packet_hdr->ipv4_hdr, 0, sizeof(struct rte_ipv4_hdr));
146
147 IpAddr src(src_ip_addr);
148 IpAddr dst(dst_ip_addr);
149
150 struct ipaddr src_reversed_order;
151 src_reversed_order.addr_bytes[3] = src.addr_bytes[0];
152 src_reversed_order.addr_bytes[2] = src.addr_bytes[1];
153 src_reversed_order.addr_bytes[1] = src.addr_bytes[2];
154 src_reversed_order.addr_bytes[0] = src.addr_bytes[3];
155
156 struct ipaddr dst_reversed_order;
157 dst_reversed_order.addr_bytes[3] = dst.addr_bytes[0];
158 dst_reversed_order.addr_bytes[2] = dst.addr_bytes[1];
159 dst_reversed_order.addr_bytes[1] = dst.addr_bytes[2];
160 dst_reversed_order.addr_bytes[0] = dst.addr_bytes[3];
161
162 rte_le32_t src_addr_ser = *((rte_le32_t*)&src_reversed_order);
163 rte_le32_t dst_addr_ser = *((rte_le32_t*)&dst_reversed_order);
164
165 packet_hdr->ipv4_hdr.src_addr = rte_cpu_to_be_32(src_addr_ser);
166 packet_hdr->ipv4_hdr.dst_addr = rte_cpu_to_be_32(dst_addr_ser);
167
168 packet_hdr->ipv4_hdr.version_ihl = (IPV4_VERSION << 4) | (sizeof(struct rte_ipv4_hdr) / 4);
169
170 packet_hdr->ipv4_hdr.total_length = rte_cpu_to_be_16(packet_len); // Payload + udp_hdr + iphdr
171 packet_hdr->ipv4_hdr.time_to_live = DEFAULT_TTL;
172 packet_hdr->ipv4_hdr.type_of_service = DEFAULT_TOS;
173
174 // https://perso.telecom-paristech.fr/drossi/paper/rossi17ipid.pdf
175 packet_hdr->ipv4_hdr.packet_id = rte_cpu_to_be_16(0); // I put a constant here..
176 packet_hdr->ipv4_hdr.fragment_offset = 0;
177 packet_hdr->ipv4_hdr.next_proto_id = IPPROTO_UDP;
178
179 packet_hdr->ipv4_hdr.hdr_checksum = 0;
180 // packet_hdr->ipv4_hdr.hdr_checksum = rte_ipv4_cksum(&packet_hdr->ipv4_hdr);
181
182 // UDP checksum
183 packet_hdr->udp_hdr.dgram_cksum = 0;
184 // packet_hdr->udp_hdr.dgram_cksum = rte_ipv4_udptcp_cksum(&packet_hdr->ipv4_hdr, (void *) &packet_hdr->udp_hdr);
185 // if (packet_hdr->udp_hdr.dgram_cksum == 0) {
186 // packet_hdr->udp_hdr.dgram_cksum = 0xFFFF;
187 // }
188 return;
189}
190
191/**************************************************************************/
205void
206pktgen_ether_hdr_ctor(struct ipv4_udp_packet_hdr* packet_hdr, const std::string& router_mac_address, const int port_id)
207{
208 // pg_ether_addr_copy(&pkt->eth_src_addr, &eth->src_addr);
209 // pg_ether_addr_copy(&pkt->eth_dst_addr, &eth->dst_addr);
210
211 /* src and dest addr */
212 // See definition dpdk-20.08/lib/librte_net/rte_ether.c is defined as static -> not exposed to the lib... redefining
213 // here
214
215 get_ether_addr6(router_mac_address.c_str(), &packet_hdr->eth_hdr.dst_addr);
216
217 rte_eth_macaddr_get(port_id, &packet_hdr->eth_hdr.src_addr);
218
219 /* normal ethernet header */
220 packet_hdr->eth_hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
221 return;
222}
223
224void
226 const std::string& dst_mac_addr,
227 const int payload_bytes,
228 const int burst_size,
229 rte_mbuf** bufs)
230{
231 struct ipv4_udp_packet_hdr packet_hdr;
232
233 constexpr int eth_header_bytes = 14;
234 constexpr int udp_header_bytes = 8;
235 constexpr int ipv4_header_bytes = 20;
236
237 int eth_packet_bytes =
238 eth_header_bytes + ipv4_header_bytes + udp_header_bytes + sizeof(detdataformats::DAQEthHeader) + payload_bytes;
239 int ipv4_packet_bytes = eth_packet_bytes - eth_header_bytes;
240 int udp_datagram_bytes = ipv4_packet_bytes - ipv4_header_bytes;
241
242 // Get info for the ethernet header (protocol stack level 2)
243 pktgen_ether_hdr_ctor(&packet_hdr, dst_mac_addr, port_id);
244
245 // Get info for the internet header (protocol stack level 3)
246 pktgen_ipv4_ctor(&packet_hdr, ipv4_packet_bytes);
247
248 // Get info for the UDP header (protocol stack level 4)
249 pktgen_udp_hdr_ctor(&packet_hdr, udp_datagram_bytes);
250
251 detdataformats::DAQEthHeader daqethheader_obj;
252 set_daqethheader_test_values(daqethheader_obj);
253
254 void* dataloc = nullptr;
255 for (int i_pkt = 0; i_pkt < burst_size; ++i_pkt) {
256
257 dataloc = rte_pktmbuf_mtod(bufs[i_pkt], char*);
258 rte_memcpy(dataloc, &packet_hdr, sizeof(packet_hdr));
259
260 dataloc = rte_pktmbuf_mtod_offset(bufs[i_pkt], char*, sizeof(packet_hdr));
261 rte_memcpy(dataloc, &daqethheader_obj, sizeof(daqethheader_obj));
262
263 bufs[i_pkt]->pkt_len = eth_packet_bytes;
264 bufs[i_pkt]->data_len = eth_packet_bytes;
265 }
266}
267
268} // namespace udp
269} // namespace dpdklibs
270} // namespace dunedaq
#define IPV4_VERSION
Definition PacketCtor.cpp:9
void pktgen_ether_hdr_ctor(struct ipv4_udp_packet_hdr *packet_hdr, const std::string &dst_mac_address="0a:00:10:c2:15:c1", const int port_id=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)
void pktgen_ipv4_ctor(struct ipv4_udp_packet_hdr *packet_hdr, rte_le16_t packet_len, const std::string &src_ip_addr="0.0.0.0", const std::string &dst_ip_addr="0.0.0.0")
rte_le16_t packet_fill(struct ipv4_udp_packet_hdr *packet_hdr)
void set_daqethheader_test_values(detdataformats::DAQEthHeader &daqethheader_obj) noexcept
Definition Utils.cpp:237
static int8_t get_xdigit(char ch)
void pktgen_udp_hdr_ctor(struct ipv4_udp_packet_hdr *packet_hdr, rte_le16_t packet_len, int sport=55677, int dport=55678)
bool get_ether_addr6(const char *s0, struct rte_ether_addr *ea)
The DUNE-DAQ namespace.
DAQEthHeader is a versioned and unified structure for every FE electronics.