Ensō 0.4.6
Software API reference
Loading...
Searching...
No Matches
helpers.cpp
Go to the documentation of this file.
1/*
2 * Copyright (c) 2023, Carnegie Mellon University
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted (subject to the limitations in the disclaimer
6 * below) provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * * Neither the name of the copyright holder nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
20 * THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
21 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
22 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
30 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
40#include <enso/helpers.h>
41
42#include <cstdio>
43#include <iostream>
44#include <thread>
45#include <vector>
46namespace enso {
47
48uint16_t get_bdf_from_pcie_addr(const std::string& pcie_addr) {
49 uint32_t domain, bus, dev, func;
50 uint16_t bdf = 0;
51 // Check if the address has format 00:00.0 (without domain).
52 if (sscanf(pcie_addr.c_str(), "%x:%x.%x", &bus, &dev, &func) != 3) {
53 // Check if the address has format 0000:00:00.0 (with domain).
54 if (sscanf(pcie_addr.c_str(), "%x:%x:%x.%x", &domain, &bus, &dev, &func) !=
55 4) {
56 // Could not parse PCIe address.
57 return 0;
58 }
59 }
60 bdf = (bus << 8) | (dev << 3) | (func & 0x7);
61 return bdf;
62}
63
64void print_buf(void* buf, const uint32_t nb_cache_lines) {
65 for (uint32_t i = 0; i < nb_cache_lines * 64; i++) {
66 printf("%02x ", ((uint8_t*)buf)[i]);
67 if ((i + 1) % 8 == 0) {
68 printf(" ");
69 }
70 if ((i + 1) % 16 == 0) {
71 printf("\n");
72 }
73 if ((i + 1) % 64 == 0) {
74 printf("\n");
75 }
76 }
77}
78
79void print_ip(uint32_t ip) {
80 std::cout << ((ip >> 0) & 0xff) << "." << ((ip >> 8) & 0xff) << "."
81 << ((ip >> 16) & 0xff) << "." << ((ip >> 24) & 0xff);
82}
83
84void print_pkt_ips(uint8_t* pkt) {
85 struct ether_header* l2_hdr = (struct ether_header*)pkt;
86 struct iphdr* l3_hdr = (struct iphdr*)(l2_hdr + 1);
87
88 std::cout << "src: ";
89 print_ip(l3_hdr->saddr);
90
91 std::cout << " dst: ";
92 print_ip(l3_hdr->daddr);
93
94 std::cout << std::endl;
95}
96
97void print_pkt_header(uint8_t* pkt) {
98 struct ether_header* l2_hdr = (struct ether_header*)pkt;
99 std::cout << "Eth - dst MAC: " << ether_ntoa((ether_addr*)l2_hdr->ether_dhost)
100 << " src MAC: " << ether_ntoa((ether_addr*)l2_hdr->ether_shost)
101 << std::endl;
102
103 struct iphdr* l3_hdr = (struct iphdr*)(l2_hdr + 1);
104
105 uint8_t protocol = l3_hdr->protocol;
106 std::cout << "IP - protocol: " << (uint32_t)protocol
107 << " checksum: " << ntohs(l3_hdr->check);
108
109 std::cout << " src IP: ";
110 print_ip(l3_hdr->saddr);
111
112 std::cout << " dst IP: ";
113 print_ip(l3_hdr->daddr);
114 std::cout << std::endl;
115
116 switch (protocol) {
117 case IPPROTO_TCP: {
118 struct tcphdr* l4_hdr = (struct tcphdr*)(l3_hdr + 1);
119 std::cout << "TCP - src port: " << ntohs(l4_hdr->source)
120 << " dst port: " << ntohs(l4_hdr->dest)
121 << " seq: " << ntohl(l4_hdr->seq) << std::endl;
122 break;
123 }
124 case IPPROTO_UDP: {
125 struct udphdr* l4_hdr = (struct udphdr*)(l3_hdr + 1);
126 std::cout << "UDP - src port: " << ntohs(l4_hdr->source)
127 << " dst port: " << ntohs(l4_hdr->dest) << std::endl;
128 break;
129 }
130 default:
131 break;
132 }
133}
134
135int set_core_id(std::thread& thread, int core_id) {
136 cpu_set_t cpuset;
137 CPU_ZERO(&cpuset);
138 CPU_SET(core_id, &cpuset);
139 return pthread_setaffinity_np(thread.native_handle(), sizeof(cpuset),
140 &cpuset);
141}
142
143static void print_stats_line(uint64_t recv_bytes, uint64_t nb_batches,
144 uint64_t nb_pkts, uint64_t delta_bytes,
145 uint64_t delta_pkts, uint64_t delta_batches) {
146 std::cout << std::dec << (delta_bytes + delta_pkts * 20) * 8. / 1e6
147 << " Mbps " << delta_pkts / 1e6 << " Mpps " << recv_bytes
148 << " B " << nb_batches << " batches " << nb_pkts << " pkts";
149
150 if (delta_batches > 0) {
151 std::cout << " " << delta_bytes / delta_batches << " B/batch";
152 std::cout << " " << delta_pkts / delta_batches << " pkt/batch";
153 }
154 std::cout << std::endl;
155}
156
157void show_stats(const std::vector<stats_t>& thread_stats,
158 volatile bool* keep_running) {
159 while (*keep_running) {
160 std::vector<uint64_t> recv_bytes_before;
161 std::vector<uint64_t> nb_batches_before;
162 std::vector<uint64_t> nb_pkts_before;
163
164 std::vector<uint64_t> recv_bytes_after;
165 std::vector<uint64_t> nb_batches_after;
166 std::vector<uint64_t> nb_pkts_after;
167
168 recv_bytes_before.reserve(thread_stats.size());
169 nb_batches_before.reserve(thread_stats.size());
170 nb_pkts_before.reserve(thread_stats.size());
171
172 recv_bytes_after.reserve(thread_stats.size());
173 nb_batches_after.reserve(thread_stats.size());
174 nb_pkts_after.reserve(thread_stats.size());
175
176 for (auto& stats : thread_stats) {
177 recv_bytes_before.push_back(stats.recv_bytes);
178 nb_batches_before.push_back(stats.nb_batches);
179 nb_pkts_before.push_back(stats.nb_pkts);
180 }
181
182 std::this_thread::sleep_for(std::chrono::seconds(1));
183
184 for (auto& stats : thread_stats) {
185 recv_bytes_after.push_back(stats.recv_bytes);
186 nb_batches_after.push_back(stats.nb_batches);
187 nb_pkts_after.push_back(stats.nb_pkts);
188 }
189
190 uint64_t total_recv_bytes = 0;
191 uint64_t total_nb_batches = 0;
192 uint64_t total_nb_pkts = 0;
193
194 uint64_t total_delta_bytes = 0;
195 uint64_t total_delta_pkts = 0;
196 uint64_t total_delta_batches = 0;
197
198 for (uint16_t i = 0; i < thread_stats.size(); ++i) {
199 uint64_t recv_bytes = recv_bytes_after[i];
200 uint64_t nb_batches = nb_batches_after[i];
201 uint64_t nb_pkts = nb_pkts_after[i];
202
203 total_recv_bytes += recv_bytes;
204 total_nb_batches += nb_batches;
205 total_nb_pkts += nb_pkts;
206
207 uint64_t delta_bytes = recv_bytes - recv_bytes_before[i];
208 uint64_t delta_pkts = nb_pkts - nb_pkts_before[i];
209 uint64_t delta_batches = nb_batches - nb_batches_before[i];
210
211 total_delta_bytes += delta_bytes;
212 total_delta_pkts += delta_pkts;
213 total_delta_batches += delta_batches;
214
215 // Only print per-thread stats if there are multiple threads.
216 if (thread_stats.size() > 1) {
217 std::cout << " Thread " << i << ":" << std::endl;
218 std::cout << " ";
219 print_stats_line(recv_bytes, nb_batches, nb_pkts, delta_bytes,
220 delta_pkts, delta_batches);
221 }
222 }
223 print_stats_line(total_recv_bytes, total_nb_batches, total_nb_pkts,
224 total_delta_bytes, total_delta_pkts, total_delta_batches);
225
226 if (thread_stats.size() > 1) {
227 std::cout << std::endl;
228 }
229 }
230}
231
232} // namespace enso
Miscellaneous helper functions.