xref: /aosp_15_r20/external/wmediumd/wmediumd/wmediumd.c (revision 621120a22a0cd8ba80b131fe8bcb37c86ff453e3)
1 /*
2  *	wmediumd, wireless medium simulator for mac80211_hwsim kernel module
3  *	Copyright (c) 2011 cozybit Inc.
4  *	Copyright (C) 2020 Intel Corporation
5  *
6  *	Author:	Javier Lopez	<[email protected]>
7  *		Javier Cardona	<[email protected]>
8  *
9  *	This program is free software; you can redistribute it and/or
10  *	modify it under the terms of the GNU General Public License
11  *	as published by the Free Software Foundation; either version 2
12  *	of the License, or (at your option) any later version.
13  *
14  *	This program is distributed in the hope that it will be useful,
15  *	but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *	GNU General Public License for more details.
18  *
19  *	You should have received a copy of the GNU General Public License
20  *	along with this program; if not, write to the Free Software
21  *	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22  *	02110-1301, USA.
23  */
24 
25 #include <netlink/netlink.h>
26 #include <netlink/genl/genl.h>
27 #include <netlink/genl/ctrl.h>
28 #include <netlink/genl/family.h>
29 #include <assert.h>
30 #include <stdint.h>
31 #include <getopt.h>
32 #include <signal.h>
33 #include <math.h>
34 #include <sys/syslog.h>
35 #include <sys/timerfd.h>
36 #include <errno.h>
37 #include <limits.h>
38 #include <time.h>
39 #include <unistd.h>
40 #include <stdarg.h>
41 #include <endian.h>
42 #include <pthread.h>
43 #include <sys/msg.h>
44 #include <usfstl/loop.h>
45 #include <usfstl/sched.h>
46 #include <usfstl/schedctrl.h>
47 #include <usfstl/vhost.h>
48 #include <usfstl/uds.h>
49 
50 #include "wmediumd.h"
51 #include "ieee80211.h"
52 #include "config.h"
53 #include "api.h"
54 #include "pmsr.h"
55 #include "grpc.h"
56 
57 USFSTL_SCHEDULER(scheduler);
58 
59 static void wmediumd_deliver_frame(struct usfstl_job *job);
60 
61 enum {
62 	HWSIM_VQ_TX,
63 	HWSIM_VQ_RX,
64 	HWSIM_NUM_VQS,
65 };
66 
stpcpy_safe(char * dst,const char * src)67 static char *stpcpy_safe(char *dst, const char *src) {
68 	if (dst == NULL) {
69 		return NULL;
70 	}
71 
72 	if (src == NULL) {
73 		*dst = '\0';
74 		return dst;
75 	}
76 
77 	return stpcpy(dst, src);
78 }
79 
strlen_safe(const char * src)80 static int strlen_safe(const char *src) {
81 	return src == NULL ? 0 : strlen(src);
82 }
83 
div_round(int a,int b)84 static inline int div_round(int a, int b)
85 {
86 	return (a + b - 1) / b;
87 }
88 
sec_to_ns(time_t sec)89 static inline u64 sec_to_ns(time_t sec)
90 {
91 	return sec * 1000 * 1000 * 1000;
92 }
93 
ns_to_us(u64 ns)94 static inline u64 ns_to_us(u64 ns)
95 {
96 	return ns / 1000L;
97 }
98 
ts_to_ns(struct timespec ts)99 static inline u64 ts_to_ns(struct timespec ts)
100 {
101 	return sec_to_ns(ts.tv_sec) + ts.tv_nsec;
102 }
103 
distance_to_rtt(double distance)104 static inline double distance_to_rtt(double distance)
105 {
106 	const long light_speed = 299792458L;
107 	return distance / light_speed;
108 }
109 
sec_to_ps(double sec)110 static inline double sec_to_ps(double sec)
111 {
112 	return sec * 1000 * 1000 * 1000;
113 }
114 
meter_to_mm(double meter)115 static inline double meter_to_mm(double meter)
116 {
117 	return meter * 1000;
118 }
119 
pkt_duration(int len,int rate)120 static inline int pkt_duration(int len, int rate)
121 {
122 	/* preamble + signal + t_sym * n_sym, rate in 100 kbps */
123 	return 16 + 4 + 4 * div_round((16 + 8 * len + 6) * 10, 4 * rate);
124 }
125 
w_logf(struct wmediumd * ctx,u8 level,const char * format,...)126 int w_logf(struct wmediumd *ctx, u8 level, const char *format, ...)
127 {
128 	va_list(args);
129 	va_start(args, format);
130 	if (ctx->log_lvl >= level) {
131 		return vprintf(format, args);
132 	}
133 	return -1;
134 }
135 
w_flogf(struct wmediumd * ctx,u8 level,FILE * stream,const char * format,...)136 int w_flogf(struct wmediumd *ctx, u8 level, FILE *stream, const char *format, ...)
137 {
138 	va_list(args);
139 	va_start(args, format);
140 	if (ctx->log_lvl >= level) {
141 		return vfprintf(stream, format, args);
142 	}
143 	return -1;
144 }
145 
wqueue_init(struct wqueue * wqueue,int cw_min,int cw_max)146 static void wqueue_init(struct wqueue *wqueue, int cw_min, int cw_max)
147 {
148 	INIT_LIST_HEAD(&wqueue->frames);
149 	wqueue->cw_min = cw_min;
150 	wqueue->cw_max = cw_max;
151 }
152 
station_init_queues(struct station * station)153 void station_init_queues(struct station *station)
154 {
155 	wqueue_init(&station->queues[IEEE80211_AC_BK], 15, 1023);
156 	wqueue_init(&station->queues[IEEE80211_AC_BE], 15, 1023);
157 	wqueue_init(&station->queues[IEEE80211_AC_VI], 7, 15);
158 	wqueue_init(&station->queues[IEEE80211_AC_VO], 3, 7);
159 }
160 
frame_has_a4(struct frame * frame)161 static inline bool frame_has_a4(struct frame *frame)
162 {
163 	struct ieee80211_hdr *hdr = (void *)frame->data;
164 
165 	return (hdr->frame_control[1] & (FCTL_TODS | FCTL_FROMDS)) ==
166 		(FCTL_TODS | FCTL_FROMDS);
167 }
168 
frame_is_mgmt(struct frame * frame)169 static inline bool frame_is_mgmt(struct frame *frame)
170 {
171 	struct ieee80211_hdr *hdr = (void *)frame->data;
172 
173 	return (hdr->frame_control[0] & FCTL_FTYPE) == FTYPE_MGMT;
174 }
175 
frame_is_data(struct frame * frame)176 static inline bool frame_is_data(struct frame *frame)
177 {
178 	struct ieee80211_hdr *hdr = (void *)frame->data;
179 
180 	return (hdr->frame_control[0] & FCTL_FTYPE) == FTYPE_DATA;
181 }
182 
frame_is_data_qos(struct frame * frame)183 static inline bool frame_is_data_qos(struct frame *frame)
184 {
185 	struct ieee80211_hdr *hdr = (void *)frame->data;
186 
187 	return (hdr->frame_control[0] & (FCTL_FTYPE | STYPE_QOS_DATA)) ==
188 		(FTYPE_DATA | STYPE_QOS_DATA);
189 }
190 
frame_is_probe_req(struct frame * frame)191 static inline bool frame_is_probe_req(struct frame *frame)
192 {
193 	struct ieee80211_hdr *hdr = (void *)frame->data;
194 
195 	return (hdr->frame_control[0] & (FCTL_FTYPE | STYPE_PROBE_REQ)) ==
196 		(FTYPE_MGMT | STYPE_PROBE_REQ);
197 }
198 
frame_has_zero_rates(const struct frame * frame)199 static inline bool frame_has_zero_rates(const struct frame *frame)
200 {
201 	for (int i = 0; i < frame->tx_rates_count; i++) {
202 		if (frame->tx_rates[i].idx < 0)
203 			break;
204 
205 		if (frame->tx_rates[i].count > 0) {
206 			return false;
207 		}
208 	}
209 
210 	return true;
211 }
212 
fill_tx_rates(struct frame * frame)213 static inline void fill_tx_rates(struct frame *frame)
214 {
215 	if (frame->tx_rates_count <= 0) {
216 		return;
217 	}
218 
219 	int max_index = get_max_index();
220 
221 	/* Starting from OFDM rate (See per.c#rateset) */
222 	const int basic_rate_start = 4; /* 6 mbps */
223 
224 	int i;
225 	int rate_count = min(max_index - basic_rate_start + 1, frame->tx_rates_count);
226 
227 	for (i = 0; i < rate_count; i++) {
228 		frame->tx_rates[i].idx = basic_rate_start + rate_count - i - 1;
229 		frame->tx_rates[i].count = 4;
230 	}
231 
232 	for (; i < frame->tx_rates_count; i++) {
233 		frame->tx_rates[i].idx = -1;
234 		frame->tx_rates[i].count = 0;
235 	}
236 }
237 
frame_get_qos_ctl(struct frame * frame)238 static inline u8 *frame_get_qos_ctl(struct frame *frame)
239 {
240 	struct ieee80211_hdr *hdr = (void *)frame->data;
241 
242 	if (frame_has_a4(frame))
243 		return (u8 *)hdr + 30;
244 	else
245 		return (u8 *)hdr + 24;
246 }
247 
frame_select_queue_80211(struct frame * frame)248 static enum ieee80211_ac_number frame_select_queue_80211(struct frame *frame)
249 {
250 	u8 *p;
251 	int priority;
252 
253 	if (!frame_is_data(frame))
254 		return IEEE80211_AC_VO;
255 
256 	if (!frame_is_data_qos(frame))
257 		return IEEE80211_AC_BE;
258 
259 	p = frame_get_qos_ctl(frame);
260 	priority = *p & QOS_CTL_TAG1D_MASK;
261 
262 	return ieee802_1d_to_ac[priority];
263 }
264 
dBm_to_milliwatt(int decibel_intf)265 static double dBm_to_milliwatt(int decibel_intf)
266 {
267 #define INTF_LIMIT (31)
268 	int intf_diff = NOISE_LEVEL - decibel_intf;
269 
270 	if (intf_diff >= INTF_LIMIT)
271 		return 0.001;
272 
273 	if (intf_diff <= -INTF_LIMIT)
274 		return 1000.0;
275 
276 	return pow(10.0, -intf_diff / 10.0);
277 }
278 
milliwatt_to_dBm(double value)279 static double milliwatt_to_dBm(double value)
280 {
281 	return 10.0 * log10(value);
282 }
283 
set_interference_duration(struct wmediumd * ctx,int src_idx,int duration,int signal)284 static int set_interference_duration(struct wmediumd *ctx, int src_idx,
285 				     int duration, int signal)
286 {
287 	int i;
288 
289 	if (!ctx->intf)
290 		return 0;
291 
292 	if (signal >= CCA_THRESHOLD)
293 		return 0;
294 
295 	for (i = 0; i < ctx->num_stas; i++) {
296 		ctx->intf[ctx->num_stas * src_idx + i].duration += duration;
297 		// use only latest value
298 		ctx->intf[ctx->num_stas * src_idx + i].signal = signal;
299 	}
300 
301 	return 1;
302 }
303 
get_signal_offset_by_interference(struct wmediumd * ctx,int src_idx,int dst_idx)304 static int get_signal_offset_by_interference(struct wmediumd *ctx, int src_idx,
305 					     int dst_idx)
306 {
307 	int i;
308 	double intf_power;
309 
310 	if (!ctx->intf)
311 		return 0;
312 
313 	intf_power = 0.0;
314 	for (i = 0; i < ctx->num_stas; i++) {
315 		if (i == src_idx || i == dst_idx)
316 			continue;
317 		if (drand48() < ctx->intf[i * ctx->num_stas + dst_idx].prob_col)
318 			intf_power += dBm_to_milliwatt(
319 				ctx->intf[i * ctx->num_stas + dst_idx].signal);
320 	}
321 
322 	if (intf_power <= 1.0)
323 		return 0;
324 
325 	return (int)(milliwatt_to_dBm(intf_power) + 0.5);
326 }
327 
is_multicast_ether_addr(const u8 * addr)328 static bool is_multicast_ether_addr(const u8 *addr)
329 {
330 	return 0x01 & addr[0];
331 }
332 
get_station_by_addr(struct wmediumd * ctx,u8 * addr)333 static struct station *get_station_by_addr(struct wmediumd *ctx, u8 *addr)
334 {
335 	struct station *station;
336 
337 	list_for_each_entry(station, &ctx->stations, list) {
338 		if (memcmp(station->addr, addr, ETH_ALEN) == 0)
339 			return station;
340 	}
341 	return NULL;
342 }
343 
station_has_addr(struct station * station,const u8 * addr)344 static bool station_has_addr(struct station *station, const u8 *addr)
345 {
346 	unsigned int i;
347 
348 	if (memcmp(station->addr, addr, ETH_ALEN) == 0)
349 		return true;
350 
351 	for (i = 0; i < station->n_addrs; i++) {
352 		if (memcmp(station->addrs[i].addr, addr, ETH_ALEN) == 0)
353 			return true;
354 	}
355 
356 	return false;
357 }
358 
get_station_by_used_addr(struct wmediumd * ctx,u8 * addr)359 static struct station *get_station_by_used_addr(struct wmediumd *ctx, u8 *addr)
360 {
361 	struct station *station;
362 
363 	list_for_each_entry(station, &ctx->stations, list) {
364 		if (station_has_addr(station, addr))
365 			return station;
366 	}
367 	return NULL;
368 }
369 
wmediumd_wait_for_client_ack(struct wmediumd * ctx,struct client * client)370 static void wmediumd_wait_for_client_ack(struct wmediumd *ctx,
371 					 struct client *client)
372 {
373 	client->wait_for_ack = true;
374 
375 	while (client->wait_for_ack)
376 		usfstl_loop_wait_and_handle();
377 }
378 
379 static void wmediumd_remove_client(struct wmediumd *ctx, struct client *client);
380 
wmediumd_notify_frame_start(struct usfstl_job * job)381 static void wmediumd_notify_frame_start(struct usfstl_job *job)
382 {
383 	struct frame *frame = container_of(job, struct frame, start_job);
384 	struct wmediumd *ctx = job->data;
385 	struct client *client, *tmp;
386 	struct {
387 		struct wmediumd_message_header hdr;
388 		struct wmediumd_tx_start start;
389 	} __attribute__((packed)) msg = {
390 		.hdr.type = WMEDIUMD_MSG_TX_START,
391 		.hdr.data_len = sizeof(msg.start),
392 		.start.freq = frame->freq,
393 	};
394 
395 	if (ctx->ctrl)
396 		usfstl_sched_ctrl_sync_to(ctx->ctrl);
397 
398 	list_for_each_entry_safe(client, tmp, &ctx->clients, list) {
399 		if (!(client->flags & WMEDIUMD_CTL_NOTIFY_TX_START))
400 			continue;
401 
402 		if (client == frame->src)
403 			msg.start.cookie = frame->cookie;
404 		else
405 			msg.start.cookie = 0;
406 
407 		/* must be API socket since flags cannot otherwise be set */
408 		assert(client->type == CLIENT_API_SOCK);
409 
410 		if (write(client->loop.fd, &msg, sizeof(msg)) < sizeof(msg)) {
411 			usfstl_loop_unregister(&client->loop);
412 			wmediumd_remove_client(ctx, client);
413 			continue;
414 		}
415 
416 		wmediumd_wait_for_client_ack(ctx, client);
417 	}
418 }
419 
log2pcap(struct wmediumd * ctx,struct frame * frame,uint64_t ts)420 static void log2pcap(struct wmediumd *ctx, struct frame *frame, uint64_t ts)
421 {
422 	struct {
423 		uint8_t it_version;
424 		uint8_t it_pad;
425 		uint16_t it_len;
426 		uint32_t it_present;
427 		struct {
428 			uint16_t freq, flags;
429 		} channel;
430 		uint8_t signal;
431 	} __attribute__((packed)) radiotap_hdr = {
432 		.it_len = htole16(sizeof(radiotap_hdr)),
433 		.it_present = htole32(1 << 3 /* channel */ |
434 				      1 << 5 /* signal dBm */),
435 		.channel.freq = htole16(frame->freq),
436 		.signal = frame->signal,
437 	};
438 	struct {
439 		uint32_t type, blocklen, ifidx, ts_hi, ts_lo, caplen, pktlen;
440 	} __attribute__((packed)) blockhdr = {
441 		.type = 6,
442 		.ts_hi = ts / (1ULL << 32),
443 		.ts_lo = ts,
444 		.caplen = frame->data_len + sizeof(radiotap_hdr),
445 		.pktlen = frame->data_len + sizeof(radiotap_hdr),
446 	};
447 	static const uint8_t pad[3];
448 	uint32_t sz, align;
449 
450 	sz = blockhdr.caplen + sizeof(blockhdr) + sizeof(uint32_t);
451 	blockhdr.blocklen = (sz + 3) & ~3;
452 	align = blockhdr.blocklen - sz;
453 
454 	fwrite(&blockhdr, sizeof(blockhdr), 1, ctx->pcap_file);
455 	fwrite(&radiotap_hdr, sizeof(radiotap_hdr), 1, ctx->pcap_file);
456 	fwrite(frame->data, frame->data_len, 1, ctx->pcap_file);
457 	fwrite(pad, align, 1, ctx->pcap_file);
458 	fwrite(&blockhdr.blocklen, sizeof(blockhdr.blocklen), 1, ctx->pcap_file);
459 	fflush(ctx->pcap_file);
460 }
461 
queue_frame(struct wmediumd * ctx,struct station * station,struct frame * frame)462 static void queue_frame(struct wmediumd *ctx, struct station *station,
463 			struct frame *frame)
464 {
465 	struct ieee80211_hdr *hdr = (void *)frame->data;
466 	u8 *dest = hdr->addr1;
467 	uint64_t target;
468 	struct wqueue *queue;
469 	struct frame *tail;
470 	struct station *tmpsta, *deststa;
471 	int send_time;
472 	int cw;
473 	double error_prob;
474 	bool is_acked = false;
475 	bool noack = false;
476 	int i, j;
477 	int rate_idx;
478 	int ac;
479 
480 	/* TODO configure phy parameters */
481 	int slot_time = 9;
482 	int sifs = 16;
483 	int difs = 2 * slot_time + sifs;
484 
485 	int retries = 0;
486 
487 	int ack_time_usec = pkt_duration(14, index_to_rate(0, frame->freq)) +
488 	                    sifs;
489 
490 	/*
491 	 * To determine a frame's expiration time, we compute the
492 	 * number of retries we might have to make due to radio conditions
493 	 * or contention, and add backoff time accordingly.  To that, we
494 	 * add the expiration time of the previous frame in the queue.
495 	 */
496 
497 	ac = frame_select_queue_80211(frame);
498 	queue = &station->queues[ac];
499 
500 	/* try to "send" this frame at each of the rates in the rateset */
501 	send_time = 0;
502 	cw = queue->cw_min;
503 
504 	int snr = SNR_DEFAULT;
505 
506 	if (is_multicast_ether_addr(dest)) {
507 		deststa = NULL;
508 	} else {
509 		deststa = get_station_by_used_addr(ctx, dest);
510 		if (deststa) {
511 			snr = ctx->get_link_snr(ctx, station, deststa) -
512 				get_signal_offset_by_interference(ctx,
513 					station->index, deststa->index);
514 			snr += ctx->get_fading_signal(ctx);
515 		}
516 	}
517 	frame->signal = snr + NOISE_LEVEL;
518 
519 	noack = is_multicast_ether_addr(dest);
520 
521 	/*
522 	 * TODO(b/211353765) Remove this when fundamenal solution is applied
523 	 *
524 	 *   Temporary workaround for relaying probe_req frame.
525 	 */
526 	if (frame_is_probe_req(frame) && frame_has_zero_rates(frame)) {
527 		fill_tx_rates(frame);
528 	}
529 
530 	double choice = drand48();
531 
532 	for (i = 0; i < frame->tx_rates_count && !is_acked; i++) {
533 
534 		rate_idx = frame->tx_rates[i].idx;
535 
536 		/* no more rates in MRR */
537 		if (rate_idx < 0)
538 			break;
539 
540 		error_prob = ctx->get_error_prob(ctx, snr, rate_idx,
541 						 frame->freq, frame->data_len,
542 						 station, deststa);
543 		for (j = 0; j < frame->tx_rates[i].count; j++) {
544 			send_time += difs + pkt_duration(frame->data_len,
545 				index_to_rate(rate_idx, frame->freq));
546 
547 			retries++;
548 
549 			/* skip ack/backoff/retries for noack frames */
550 			if (noack) {
551 				is_acked = true;
552 				break;
553 			}
554 
555 			/* TODO TXOPs */
556 
557 			/* backoff */
558 			if (j > 0) {
559 				send_time += (cw * slot_time) / 2;
560 				cw = (cw << 1) + 1;
561 				if (cw > queue->cw_max)
562 					cw = queue->cw_max;
563 			}
564 
565 			send_time += ack_time_usec;
566 
567 			if (choice > error_prob) {
568 				is_acked = true;
569 				break;
570 			}
571 
572 			if (!use_fixed_random_value(ctx))
573 				choice = drand48();
574 		}
575 	}
576 
577 	if (is_acked) {
578 		frame->tx_rates[i-1].count = j + 1;
579 		for (; i < frame->tx_rates_count; i++) {
580 			frame->tx_rates[i].idx = -1;
581 			frame->tx_rates[i].count = -1;
582 		}
583 		frame->flags |= HWSIM_TX_STAT_ACK;
584 	}
585 
586 	/*
587 	 * delivery time starts after any equal or higher prio frame
588 	 * (or now, if none).
589 	 */
590 	target = scheduler.current_time;
591 	for (i = 0; i <= ac; i++) {
592 		list_for_each_entry(tmpsta, &ctx->stations, list) {
593 			tail = list_last_entry_or_null(&tmpsta->queues[i].frames,
594 						       struct frame, list);
595 			if (tail && target < tail->job.start)
596 				target = tail->job.start;
597 		}
598 	}
599 
600 	if (ctx->pcap_file) {
601 		log2pcap(ctx, frame, target);
602 
603 		if (is_acked && !noack) {
604 			struct {
605 				struct frame frame;
606 				uint16_t fc;
607 				uint16_t dur;
608 				uint8_t ra[6];
609 			} __attribute__((packed, aligned(8))) ack = {
610 				.fc = htole16(0xd4),
611 				.dur = htole16(ack_time_usec),
612 			};
613 
614 			memcpy(&ack.frame, frame, sizeof(ack.frame));
615 			ack.frame.data_len = 10;
616 			memcpy(ack.ra, frame->data + 10, 6);
617 
618 			log2pcap(ctx, &ack.frame,
619 				 target + send_time - ack_time_usec);
620 		}
621 	}
622 
623 	target += send_time;
624 
625 	frame->duration = send_time;
626 	frame->src = station->client;
627 
628 	if (ctx->need_start_notify) {
629 		frame->start_job.start = target - send_time;
630 		frame->start_job.callback = wmediumd_notify_frame_start;
631 		frame->start_job.data = ctx;
632 		frame->start_job.name = "frame-start";
633 		usfstl_sched_add_job(&scheduler, &frame->start_job);
634 	}
635 
636 	frame->job.start = target;
637 	frame->job.callback = wmediumd_deliver_frame;
638 	frame->job.data = ctx;
639 	frame->job.name = "frame";
640 	usfstl_sched_add_job(&scheduler, &frame->job);
641 	list_add_tail(&frame->list, &queue->frames);
642 }
643 
wmediumd_send_to_client(struct wmediumd * ctx,struct client * client,struct nl_msg * msg)644 static void wmediumd_send_to_client(struct wmediumd *ctx,
645 				    struct client *client,
646 				    struct nl_msg *msg)
647 {
648 	struct wmediumd_message_header hdr;
649 	size_t len;
650 	int ret;
651 
652 	switch (client->type) {
653 	case CLIENT_NETLINK:
654 		ret = nl_send_auto_complete(ctx->sock, msg);
655 		if (ret < 0)
656 			w_logf(ctx, LOG_ERR, "%s: nl_send_auto failed\n", __func__);
657 		break;
658 	case CLIENT_VHOST_USER:
659 		len = nlmsg_total_size(nlmsg_datalen(nlmsg_hdr(msg)));
660 		usfstl_vhost_user_dev_notify(client->dev, HWSIM_VQ_RX,
661 					     (void *)nlmsg_hdr(msg), len);
662 		break;
663 	case CLIENT_API_SOCK:
664 		len = nlmsg_total_size(nlmsg_datalen(nlmsg_hdr(msg)));
665 		hdr.type = WMEDIUMD_MSG_NETLINK;
666 		hdr.data_len = len;
667 
668 		if (write(client->loop.fd, &hdr, sizeof(hdr)) < sizeof(hdr))
669 			goto disconnect;
670 
671 		if (write(client->loop.fd, (void *)nlmsg_hdr(msg), len) < len)
672 			goto disconnect;
673 
674 		wmediumd_wait_for_client_ack(ctx, client);
675 		break;
676 	}
677 
678 	return;
679 
680 	disconnect:
681 	usfstl_loop_unregister(&client->loop);
682 	wmediumd_remove_client(ctx, client);
683 }
684 
wmediumd_remove_client(struct wmediumd * ctx,struct client * client)685 static void wmediumd_remove_client(struct wmediumd *ctx, struct client *client)
686 {
687 	struct frame *frame, *tmp;
688 	struct wqueue *queue;
689 	struct station *station;
690 	int ac;
691 
692 	list_for_each_entry(station, &ctx->stations, list) {
693 		if (station->client == client)
694 			station->client = NULL;
695 	}
696 
697 	list_for_each_entry(station, &ctx->stations, list) {
698 		for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
699 			queue = &station->queues[ac];
700 			list_for_each_entry_safe(frame, tmp, &queue->frames,
701 						 list) {
702 				if (frame->src == client) {
703 					list_del(&frame->list);
704 					usfstl_sched_del_job(&frame->job);
705 					free(frame);
706 				}
707 			}
708 		}
709 	}
710 
711 	if (!list_empty(&client->list))
712 		list_del(&client->list);
713 	list_add(&client->list, &ctx->clients_to_free);
714 
715 	if (client->flags & WMEDIUMD_CTL_NOTIFY_TX_START)
716 		ctx->need_start_notify--;
717 
718 	client->wait_for_ack = false;
719 }
720 
721 /*
722  * Report transmit status to the kernel.
723  */
send_tx_info_frame_nl(struct wmediumd * ctx,struct frame * frame)724 static void send_tx_info_frame_nl(struct wmediumd *ctx, struct frame *frame)
725 {
726 	struct nl_msg *msg;
727 
728 	msg = nlmsg_alloc();
729 	if (!msg) {
730 		w_logf(ctx, LOG_ERR, "Error allocating new message MSG!\n");
731 		return;
732 	}
733 
734 	if (genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, ctx->family_id,
735 			0, NLM_F_REQUEST, HWSIM_CMD_TX_INFO_FRAME,
736 			VERSION_NR) == NULL) {
737 		w_logf(ctx, LOG_ERR, "%s: genlmsg_put failed\n", __func__);
738 		goto out;
739 	}
740 
741 	if (nla_put(msg, HWSIM_ATTR_ADDR_TRANSMITTER, ETH_ALEN,
742 		    frame->sender->hwaddr) ||
743 	    nla_put_u32(msg, HWSIM_ATTR_FLAGS, frame->flags) ||
744 	    nla_put_u32(msg, HWSIM_ATTR_SIGNAL, frame->signal) ||
745 	    nla_put(msg, HWSIM_ATTR_TX_INFO,
746 		    frame->tx_rates_count * sizeof(struct hwsim_tx_rate),
747 		    frame->tx_rates) ||
748 	    nla_put_u64(msg, HWSIM_ATTR_COOKIE, frame->cookie)) {
749 		w_logf(ctx, LOG_ERR, "%s: Failed to fill a payload\n", __func__);
750 		goto out;
751 	}
752 
753 	if (ctx->ctrl)
754 		usfstl_sched_ctrl_sync_to(ctx->ctrl);
755 	wmediumd_send_to_client(ctx, frame->src, msg);
756 
757 out:
758 	nlmsg_free(msg);
759 }
760 
761 /*
762  * Send a data frame to the kernel for reception at a specific radio.
763  */
send_cloned_frame_msg(struct wmediumd * ctx,struct client * src,struct station * dst,u8 * data,int data_len,int rate_idx,int signal,int freq,uint64_t cookie)764 static void send_cloned_frame_msg(struct wmediumd *ctx, struct client *src,
765 				  struct station *dst, u8 *data, int data_len,
766 				  int rate_idx, int signal, int freq,
767 				  uint64_t cookie)
768 {
769 	struct client *client, *tmp;
770 	struct nl_msg *msg, *cmsg = NULL;
771 
772 	msg = nlmsg_alloc();
773 	if (!msg) {
774 		w_logf(ctx, LOG_ERR, "Error allocating new message MSG!\n");
775 		return;
776 	}
777 
778 	if (genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, ctx->family_id,
779 			0, NLM_F_REQUEST, HWSIM_CMD_FRAME,
780 			VERSION_NR) == NULL) {
781 		w_logf(ctx, LOG_ERR, "%s: genlmsg_put failed\n", __func__);
782 		goto out;
783 	}
784 
785 	if (nla_put(msg, HWSIM_ATTR_ADDR_RECEIVER, ETH_ALEN,
786 		    dst->hwaddr) ||
787 	    nla_put(msg, HWSIM_ATTR_FRAME, data_len, data) ||
788 	    nla_put_u32(msg, HWSIM_ATTR_RX_RATE, 7) ||
789 	    nla_put_u32(msg, HWSIM_ATTR_FREQ, freq) ||
790 	    nla_put_u32(msg, HWSIM_ATTR_SIGNAL, signal)) {
791 		w_logf(ctx, LOG_ERR, "%s: Failed to fill a payload\n", __func__);
792 		goto out;
793 	}
794 
795 	w_logf(ctx, LOG_DEBUG, "cloned msg dest " MAC_FMT " (radio: " MAC_FMT ") len %d\n",
796 		   MAC_ARGS(dst->addr), MAC_ARGS(dst->hwaddr), data_len);
797 
798 	if (ctx->ctrl)
799 		usfstl_sched_ctrl_sync_to(ctx->ctrl);
800 
801 	list_for_each_entry_safe(client, tmp, &ctx->clients, list) {
802 		if (client->flags & WMEDIUMD_CTL_RX_ALL_FRAMES) {
803 			if (src == client && !cmsg) {
804 				struct nlmsghdr *nlh = nlmsg_hdr(msg);
805 
806 				cmsg = nlmsg_inherit(nlh);
807 				nlmsg_append(cmsg, nlmsg_data(nlh), nlmsg_datalen(nlh), 0);
808 				assert(nla_put_u64(cmsg, HWSIM_ATTR_COOKIE, cookie) == 0);
809 			}
810 			wmediumd_send_to_client(ctx, client,
811 						src == client ? cmsg : msg);
812 		} else if (!dst->client || dst->client == client) {
813 			wmediumd_send_to_client(ctx, client, msg);
814 		}
815 	}
816 
817 out:
818 	nlmsg_free(msg);
819 	if (cmsg)
820 		nlmsg_free(cmsg);
821 }
822 
wmediumd_deliver_frame(struct usfstl_job * job)823 static void wmediumd_deliver_frame(struct usfstl_job *job)
824 {
825 	struct wmediumd *ctx = job->data;
826 	struct frame *frame = container_of(job, struct frame, job);
827 	struct ieee80211_hdr *hdr = (void *) frame->data;
828 	struct station *station;
829 	u8 *dest = hdr->addr1;
830 	u8 *src = frame->sender->addr;
831 
832 	list_del(&frame->list);
833 
834 	if (frame->flags & HWSIM_TX_STAT_ACK) {
835 		/* rx the frame on the dest interface */
836 		list_for_each_entry(station, &ctx->stations, list) {
837 			if (memcmp(src, station->addr, ETH_ALEN) == 0)
838 				continue;
839 
840 			if (is_multicast_ether_addr(dest) && station->client != NULL) {
841 				int snr, rate_idx, signal;
842 				double error_prob;
843 
844 				/*
845 				 * we may or may not receive this based on
846 				 * reverse link from sender -- check for
847 				 * each receiver.
848 				 */
849 				snr = ctx->get_link_snr(ctx, frame->sender,
850 							station);
851 				snr += ctx->get_fading_signal(ctx);
852 				signal = snr + NOISE_LEVEL;
853 				if (signal < CCA_THRESHOLD)
854 					continue;
855 
856 				if (set_interference_duration(ctx,
857 					frame->sender->index, frame->duration,
858 					signal))
859 					continue;
860 
861 				snr -= get_signal_offset_by_interference(ctx,
862 					frame->sender->index, station->index);
863 				rate_idx = frame->tx_rates[0].idx;
864 				error_prob = ctx->get_error_prob(ctx,
865 					(double)snr, rate_idx, frame->freq,
866 					frame->data_len, frame->sender,
867 					station);
868 
869 				if (drand48() <= error_prob) {
870 					w_logf(ctx, LOG_INFO, "Dropped mcast from "
871 						   MAC_FMT " to " MAC_FMT " at receiver\n",
872 						   MAC_ARGS(src), MAC_ARGS(station->addr));
873 					continue;
874 				}
875 
876 				send_cloned_frame_msg(ctx, frame->sender->client,
877 						      station,
878 						      frame->data,
879 						      frame->data_len,
880 						      1, signal,
881 						      frame->freq,
882 						      frame->cookie);
883 
884 			} else if (station_has_addr(station, dest)) {
885 				if (set_interference_duration(ctx,
886 					frame->sender->index, frame->duration,
887 					frame->signal))
888 					continue;
889 
890 				send_cloned_frame_msg(ctx, frame->sender->client,
891 						      station,
892 						      frame->data,
893 						      frame->data_len,
894 						      1, frame->signal,
895 						      frame->freq,
896 						      frame->cookie);
897 			}
898 		}
899 	} else
900 		set_interference_duration(ctx, frame->sender->index,
901 					  frame->duration, frame->signal);
902 
903 	send_tx_info_frame_nl(ctx, frame);
904 
905 	free(frame);
906 }
907 
wmediumd_intf_update(struct usfstl_job * job)908 static void wmediumd_intf_update(struct usfstl_job *job)
909 {
910 	struct wmediumd *ctx = job->data;
911 	int i, j;
912 
913 	for (i = 0; i < ctx->num_stas; i++)
914 		for (j = 0; j < ctx->num_stas; j++) {
915 			if (i == j)
916 				continue;
917 			// probability is used for next calc
918 			ctx->intf[i * ctx->num_stas + j].prob_col =
919 				ctx->intf[i * ctx->num_stas + j].duration /
920 				(double)10000;
921 			ctx->intf[i * ctx->num_stas + j].duration = 0;
922 		}
923 
924 	job->start += 10000;
925 	usfstl_sched_add_job(&scheduler, job);
926 }
927 
928 static
nl_err_cb(struct sockaddr_nl * nla,struct nlmsgerr * nlerr,void * arg)929 int nl_err_cb(struct sockaddr_nl *nla, struct nlmsgerr *nlerr, void *arg)
930 {
931 	struct genlmsghdr *gnlh = nlmsg_data(&nlerr->msg);
932 	struct wmediumd *ctx = arg;
933 
934 	w_flogf(ctx, LOG_ERR, stderr, "nl: cmd %d, seq %d: %s\n", gnlh->cmd,
935 			nlerr->msg.nlmsg_seq, strerror(abs(nlerr->error)));
936 
937 	return NL_SKIP;
938 }
939 
send_pmsr_result_ftm(struct nl_msg * msg,struct pmsr_request_ftm * req,struct wmediumd * ctx,struct station * sender,struct station * receiver)940 static int send_pmsr_result_ftm(struct nl_msg *msg,
941 				struct pmsr_request_ftm *req,
942 				struct wmediumd *ctx,
943 				struct station *sender,
944 				struct station *receiver)
945 {
946 	struct nlattr *ftm;
947 	int err;
948 
949 	ftm = nla_nest_start(msg, NL80211_PMSR_TYPE_FTM);
950 	if (!ftm)
951 		return -ENOMEM;
952 
953 	if (!receiver) {
954 		err = nla_put_u32(msg, NL80211_PMSR_FTM_RESP_ATTR_FAIL_REASON,
955 				  NL80211_PMSR_FTM_FAILURE_NO_RESPONSE);
956 		goto out;
957 	}
958 
959 	double distance =
960 		sqrt(pow(sender->x - receiver->x, 2) + pow(sender->y - receiver->y, 2));
961 	double distance_in_mm = meter_to_mm(distance);
962 	double rtt_in_ps = sec_to_ps(distance_to_rtt(distance));
963 	if (distance_in_mm > UINT64_MAX || rtt_in_ps > UINT64_MAX) {
964 		w_logf(ctx, LOG_WARNING,
965 		       "%s: Devices are too far away", __func__);
966 		return nla_put_u32(msg, NL80211_PMSR_FTM_RESP_ATTR_FAIL_REASON,
967 				   NL80211_PMSR_FTM_FAILURE_NO_RESPONSE);
968 	}
969 
970 	int rssi = receiver->tx_power -
971 		   ctx->calc_path_loss(NULL, sender, receiver);
972 
973 	if (nla_put_u32(msg, NL80211_PMSR_FTM_RESP_ATTR_NUM_FTMR_ATTEMPTS,
974 			req->ftmr_retries) ||
975 		nla_put_u32(msg, NL80211_PMSR_FTM_RESP_ATTR_NUM_FTMR_SUCCESSES,
976 			req->ftmr_retries) ||
977 		nla_put_u8(msg, NL80211_PMSR_FTM_RESP_ATTR_NUM_BURSTS_EXP,
978 			req->num_bursts_exp) ||
979 		nla_put_u8(msg, NL80211_PMSR_FTM_RESP_ATTR_BURST_DURATION,
980 			 req->burst_duration) ||
981 		nla_put_u8(msg, NL80211_PMSR_FTM_RESP_ATTR_FTMS_PER_BURST,
982 			 req->ftms_per_burst) ||
983 		nla_put_s32(msg, NL80211_PMSR_FTM_RESP_ATTR_RSSI_AVG, rssi) ||
984 		nla_put_s32(msg, NL80211_PMSR_FTM_RESP_ATTR_RSSI_SPREAD, 0) ||
985 		nla_put_u64(msg, NL80211_PMSR_FTM_RESP_ATTR_RTT_AVG,
986 			  (uint64_t)rtt_in_ps) ||
987 		nla_put_u64(msg, NL80211_PMSR_FTM_RESP_ATTR_RTT_VARIANCE, 0) ||
988 		nla_put_u64(msg, NL80211_PMSR_FTM_RESP_ATTR_RTT_SPREAD, 0) ||
989 		nla_put_u64(msg, NL80211_PMSR_FTM_RESP_ATTR_DIST_AVG,
990 			 (uint64_t)distance_in_mm) ||
991 		nla_put_u64(msg, NL80211_PMSR_FTM_RESP_ATTR_DIST_VARIANCE, 0) ||
992 		nla_put_u64(msg, NL80211_PMSR_FTM_RESP_ATTR_DIST_SPREAD, 0)) {
993 		w_logf(ctx, LOG_ERR, "%s: Failed to fill a payload\n", __func__);
994 		return -ENOMEM;
995 	}
996 
997 	if (req->request_lci && receiver->lci) {
998 		nla_put_string(msg, NL80211_PMSR_FTM_RESP_ATTR_LCI,
999 			       receiver->lci);
1000 	}
1001 
1002 	if (req->request_civicloc && receiver->civicloc) {
1003 		nla_put_string(msg, NL80211_PMSR_FTM_RESP_ATTR_CIVICLOC,
1004 			       receiver->civicloc);
1005 	}
1006 
1007 out:
1008 	if (ftm)
1009 		nla_nest_end(msg, ftm);
1010 
1011 	return 0;
1012 }
1013 
send_pmsr_result_peer(struct nl_msg * msg,struct pmsr_request_peer * req,struct wmediumd * ctx,struct station * sender)1014 static int send_pmsr_result_peer(struct nl_msg *msg,
1015 				 struct pmsr_request_peer *req,
1016 				 struct wmediumd *ctx,
1017 				 struct station *sender)
1018 {
1019 	struct nlattr *peer, *resp, *data;
1020 	struct station *receiver;
1021 	int status;
1022 	struct timespec ts;
1023 	u64 host_time_ns;
1024 	u64 ap_tsf_us;
1025 	int err;
1026 
1027 	peer = nla_nest_start(msg, 1);
1028 	if (!peer)
1029 		return -ENOMEM;
1030 
1031 	receiver = get_station_by_addr(ctx, req->addr);
1032 	if (receiver)
1033 		status = NL80211_PMSR_STATUS_SUCCESS;
1034 	else {
1035 		w_logf(ctx, LOG_WARNING, "%s: unknown pmsr target " MAC_FMT "\n",
1036 		       __func__, MAC_ARGS(req->addr));
1037 		status = NL80211_PMSR_STATUS_FAILURE;
1038 	}
1039 
1040 	if (clock_gettime(CLOCK_BOOTTIME, &ts)) {
1041 		w_logf(ctx, LOG_ERR, "%s: clock_gettime() failed\n", __func__);
1042 		return -EINVAL;
1043 	}
1044 
1045 	host_time_ns = ts_to_ns(ts);
1046 	ap_tsf_us = ns_to_us(ts_to_ns(ts));
1047 
1048 	err = nla_put(msg, NL80211_PMSR_PEER_ATTR_ADDR, ETH_ALEN, req->addr);
1049 	if (err)
1050 		return err;
1051 
1052 	resp = nla_nest_start(msg, NL80211_PMSR_PEER_ATTR_RESP);
1053 	if (!resp)
1054 		return -ENOMEM;
1055 
1056 	if (nla_put_u32(msg, NL80211_PMSR_RESP_ATTR_STATUS, status) ||
1057 		nla_put_u64(msg, NL80211_PMSR_RESP_ATTR_HOST_TIME, host_time_ns) ||
1058 		nla_put_u64(msg, NL80211_PMSR_RESP_ATTR_AP_TSF, ap_tsf_us) ||
1059 		nla_put_flag(msg, NL80211_PMSR_RESP_ATTR_FINAL)) {
1060 		w_logf(ctx, LOG_ERR, "%s: Failed to fill a payload\n", __func__);
1061 		return -ENOMEM;
1062 	}
1063 
1064 	data = nla_nest_start(msg, NL80211_PMSR_RESP_ATTR_DATA);
1065 	if (!data)
1066 		return -ENOMEM;
1067 
1068 	err = send_pmsr_result_ftm(msg, &req->ftm, ctx, sender, receiver);
1069 
1070 	nla_nest_end(msg, data);
1071 	nla_nest_end(msg, resp);
1072 	nla_nest_end(msg, peer);
1073 
1074 	return err;
1075 }
1076 
send_pmsr_result(struct pmsr_request * request,struct wmediumd * ctx,struct station * sender,struct client * client)1077 static void send_pmsr_result(struct pmsr_request* request, struct wmediumd *ctx,
1078 			     struct station *sender, struct client *client)
1079 {
1080 	struct nl_msg *msg;
1081 	struct nlattr *pmsr, *peers;
1082 	struct pmsr_request_peer *peer;
1083 	int cnt;
1084 	int err;
1085 
1086 	msg = nlmsg_alloc();
1087 	if (!msg) {
1088 		w_logf(ctx, LOG_ERR, "%s: nlmsg_alloc failed\n", __func__);
1089 		return;
1090 	}
1091 
1092 	if (!genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, ctx->family_id,
1093 			 0, NLM_F_REQUEST, HWSIM_CMD_REPORT_PMSR, VERSION_NR)) {
1094 		w_logf(ctx, LOG_ERR, "%s: genlmsg_put failed\n", __func__);
1095 		goto out;
1096 	}
1097 
1098 	err = nla_put(msg, HWSIM_ATTR_ADDR_TRANSMITTER,
1099 		      ETH_ALEN, sender->hwaddr);
1100 
1101 	pmsr = nla_nest_start(msg, HWSIM_ATTR_PMSR_RESULT);
1102 	if (!pmsr)
1103 		goto out;
1104 
1105 	peers = nla_nest_start(msg, NL80211_PMSR_ATTR_PEERS);
1106 	if (!peers)
1107 		goto out;
1108 
1109 	list_for_each_entry(peer, &request->peers, list) {
1110 		err = send_pmsr_result_peer(msg, peer, ctx, sender);
1111 		if (err) {
1112 			w_logf(ctx, LOG_ERR,
1113 			       "%s: Failed to send pmsr result from " MAC_FMT \
1114 			       " to " MAC_FMT ". Stopping\n", __func__,
1115 			       MAC_ARGS(sender->addr),
1116 			       MAC_ARGS(peer->addr));
1117 			break;
1118 		}
1119 	}
1120 
1121 	nla_nest_end(msg, peers);
1122 	nla_nest_end(msg, pmsr);
1123 
1124 	wmediumd_send_to_client(ctx, client, msg);
1125 
1126 out:
1127 	nlmsg_free(msg);
1128 }
1129 
process_start_pmsr(struct nlattr * attrs[],struct wmediumd * ctx,struct client * client)1130 static void process_start_pmsr(struct nlattr *attrs[], struct wmediumd *ctx,
1131 			       struct client *client)
1132 {
1133 	u8 *hwaddr;
1134 	struct station *sender;
1135 
1136 	struct pmsr_request request;
1137 	struct pmsr_request_peer *peer, *tmp;
1138 	int err;
1139 
1140 	if (!attrs[HWSIM_ATTR_ADDR_TRANSMITTER]) {
1141 		w_logf(ctx, LOG_ERR, "%s: Missing sender information\n",
1142 		       __func__);
1143 	}
1144 
1145 	hwaddr = (u8 *)nla_data(attrs[HWSIM_ATTR_ADDR_TRANSMITTER]);
1146 	sender = get_station_by_addr(ctx, hwaddr);
1147 	if (!sender) {
1148 		w_logf(ctx, LOG_ERR, "%s: Unknown sender " MAC_FMT "\n",
1149 		       __func__, MAC_ARGS(hwaddr));
1150 		return;
1151 	}
1152 
1153 	err = parse_pmsr_request(attrs[HWSIM_ATTR_PMSR_REQUEST], &request);
1154 	if (err)
1155 		goto out;
1156 
1157 	send_pmsr_result(&request, ctx, sender, client);
1158 
1159 out:
1160 	list_for_each_entry_safe(peer, tmp, &request.peers, list) {
1161 		list_del(&peer->list);
1162 		free(peer);
1163 	}
1164 }
1165 
1166 /*
1167  * Handle events from the kernel.  Process CMD_FRAME events and queue them
1168  * for later delivery with the scheduler.
1169  */
_process_messages(struct nl_msg * msg,struct wmediumd * ctx,struct client * client)1170 static void _process_messages(struct nl_msg *msg,
1171 			      struct wmediumd *ctx,
1172 			      struct client *client)
1173 {
1174 	struct nlattr *attrs[HWSIM_ATTR_MAX+1];
1175 	/* netlink header */
1176 	struct nlmsghdr *nlh = nlmsg_hdr(msg);
1177 	/* generic netlink header*/
1178 	struct genlmsghdr *gnlh = nlmsg_data(nlh);
1179 
1180 	struct station *sender;
1181 	struct frame *frame;
1182 	struct ieee80211_hdr *hdr;
1183 	u8 *src, *hwaddr, *addr;
1184 	void *new_addrs;
1185 	unsigned int i;
1186 
1187 	genlmsg_parse(nlh, 0, attrs, HWSIM_ATTR_MAX, NULL);
1188 
1189 	switch (gnlh->cmd) {
1190 	case HWSIM_CMD_FRAME:
1191 		if (attrs[HWSIM_ATTR_ADDR_TRANSMITTER]) {
1192 			hwaddr = (u8 *)nla_data(attrs[HWSIM_ATTR_ADDR_TRANSMITTER]);
1193 
1194 			unsigned int data_len =
1195 				nla_len(attrs[HWSIM_ATTR_FRAME]);
1196 			char *data = (char *)nla_data(attrs[HWSIM_ATTR_FRAME]);
1197 			unsigned int flags =
1198 				nla_get_u32(attrs[HWSIM_ATTR_FLAGS]);
1199 			unsigned int tx_rates_len =
1200 				nla_len(attrs[HWSIM_ATTR_TX_INFO]);
1201 			struct hwsim_tx_rate *tx_rates =
1202 				(struct hwsim_tx_rate *)
1203 				nla_data(attrs[HWSIM_ATTR_TX_INFO]);
1204 			u64 cookie = nla_get_u64(attrs[HWSIM_ATTR_COOKIE]);
1205 			u32 freq;
1206 
1207 			freq = attrs[HWSIM_ATTR_FREQ] ?
1208 				nla_get_u32(attrs[HWSIM_ATTR_FREQ]) : 2412;
1209 
1210 			hdr = (struct ieee80211_hdr *)data;
1211 			src = hdr->addr2;
1212 
1213 			if (data_len < 6 + 6 + 4)
1214 				return;
1215 
1216 			sender = get_station_by_addr(ctx, hwaddr);
1217 			if (!sender) {
1218 				sender = get_station_by_used_addr(ctx, src);
1219 				if (!sender) {
1220 					w_flogf(ctx, LOG_ERR, stderr,
1221 						"Unable to find sender station by src=" MAC_FMT " nor hwaddr=" MAC_FMT "\n",
1222 						MAC_ARGS(src), MAC_ARGS(hwaddr));
1223 					return;
1224 				}
1225 				memcpy(sender->hwaddr, hwaddr, ETH_ALEN);
1226 			}
1227 
1228 			if (!sender->client)
1229 				sender->client = client;
1230 
1231 			frame = calloc(1, sizeof(*frame) + data_len);
1232 			if (!frame)
1233 				return;
1234 
1235 			memcpy(frame->data, data, data_len);
1236 			frame->data_len = data_len;
1237 			frame->flags = flags;
1238 			frame->cookie = cookie;
1239 			frame->freq = freq;
1240 			frame->sender = sender;
1241 			frame->tx_rates_count =
1242 				tx_rates_len / sizeof(struct hwsim_tx_rate);
1243 			memcpy(frame->tx_rates, tx_rates,
1244 			       min(tx_rates_len, sizeof(frame->tx_rates)));
1245 			queue_frame(ctx, sender, frame);
1246 		}
1247 		break;
1248 	case HWSIM_CMD_ADD_MAC_ADDR:
1249 		if (!attrs[HWSIM_ATTR_ADDR_TRANSMITTER] ||
1250 		    !attrs[HWSIM_ATTR_ADDR_RECEIVER])
1251 			break;
1252 		hwaddr = (u8 *)nla_data(attrs[HWSIM_ATTR_ADDR_TRANSMITTER]);
1253 		addr = (u8 *)nla_data(attrs[HWSIM_ATTR_ADDR_RECEIVER]);
1254 		sender = get_station_by_addr(ctx, hwaddr);
1255 		if (!sender)
1256 			break;
1257 		for (i = 0; i < sender->n_addrs; i++) {
1258 			if (memcmp(sender->addrs[i].addr, addr, ETH_ALEN) == 0) {
1259 				sender->addrs[i].count += 1;
1260 				return;
1261 			}
1262 		}
1263 		new_addrs = realloc(sender->addrs, sizeof(struct addr) * (sender->n_addrs + 1));
1264 		if (!new_addrs)
1265 			break;
1266 		sender->addrs = new_addrs;
1267 		sender->addrs[sender->n_addrs].count = 1;
1268 		memcpy(sender->addrs[sender->n_addrs].addr, addr, ETH_ALEN);
1269 		sender->n_addrs += 1;
1270 		break;
1271 	case HWSIM_CMD_DEL_MAC_ADDR:
1272 		if (!attrs[HWSIM_ATTR_ADDR_TRANSMITTER] ||
1273 		    !attrs[HWSIM_ATTR_ADDR_RECEIVER])
1274 			break;
1275 		hwaddr = (u8 *)nla_data(attrs[HWSIM_ATTR_ADDR_TRANSMITTER]);
1276 		addr = (u8 *)nla_data(attrs[HWSIM_ATTR_ADDR_RECEIVER]);
1277 		sender = get_station_by_addr(ctx, hwaddr);
1278 		if (!sender)
1279 			break;
1280 		for (i = 0; i < sender->n_addrs; i++) {
1281 			if (memcmp(sender->addrs[i].addr, addr, ETH_ALEN))
1282 				continue;
1283 			sender->addrs[i].count -= 1;
1284 			if (sender->addrs[i].count <= 0) {
1285 				sender->n_addrs -= 1;
1286 				memmove(&sender->addrs[i],
1287 					&sender->addrs[sender->n_addrs],
1288 					sizeof(struct addr));
1289 			}
1290 			break;
1291 		}
1292 		break;
1293 	case HWSIM_CMD_START_PMSR:
1294 		process_start_pmsr(attrs, ctx, client);
1295 		break;
1296 
1297 	case HWSIM_CMD_ABORT_PMSR:
1298 		// Do nothing. Too late to abort any PMSR.
1299 		break;
1300 	}
1301 }
1302 
process_messages_cb(struct nl_msg * msg,void * arg)1303 static int process_messages_cb(struct nl_msg *msg, void *arg)
1304 {
1305 	struct wmediumd *ctx = arg;
1306 
1307 	_process_messages(msg, ctx, &ctx->nl_client);
1308 	return 0;
1309 }
1310 
wmediumd_vu_connected(struct usfstl_vhost_user_dev * dev)1311 static void wmediumd_vu_connected(struct usfstl_vhost_user_dev *dev)
1312 {
1313 	struct wmediumd *ctx = dev->server->data;
1314 	struct client *client;
1315 
1316 	client = calloc(1, sizeof(*client));
1317 	dev->data = client;
1318 	client->type = CLIENT_VHOST_USER;
1319 	client->dev = dev;
1320 	list_add(&client->list, &ctx->clients);
1321 }
1322 
wmediumd_vu_handle(struct usfstl_vhost_user_dev * dev,struct usfstl_vhost_user_buf * buf,unsigned int vring)1323 static void wmediumd_vu_handle(struct usfstl_vhost_user_dev *dev,
1324 			       struct usfstl_vhost_user_buf *buf,
1325 			       unsigned int vring)
1326 {
1327 	struct nl_msg *nlmsg;
1328 	char data[4096];
1329 	size_t len;
1330 
1331 	len = iov_read(data, sizeof(data), buf->out_sg, buf->n_out_sg);
1332 
1333 	if (!nlmsg_ok((const struct nlmsghdr *)data, len))
1334 		return;
1335 	nlmsg = nlmsg_convert((struct nlmsghdr *)data);
1336 	if (!nlmsg)
1337 		return;
1338 
1339 	_process_messages(nlmsg, dev->server->data, dev->data);
1340 
1341 	nlmsg_free(nlmsg);
1342 }
1343 
wmediumd_vu_disconnected(struct usfstl_vhost_user_dev * dev)1344 static void wmediumd_vu_disconnected(struct usfstl_vhost_user_dev *dev)
1345 {
1346 	struct client *client = dev->data;
1347 
1348 	dev->data = NULL;
1349 	wmediumd_remove_client(dev->server->data, client);
1350 }
1351 
do_data_transfer(void * cookie)1352 static void *do_data_transfer(void *cookie) {
1353 	struct wmediumd *ctx = cookie;
1354 	switch (ctx->data_transfer_direction) {
1355 	case 0: // save
1356 		// No device state to save yet, just close the FD.
1357 		close(ctx->data_transfer_fd);
1358 		break;
1359 	case 1: { // load
1360 		// No device state to load yet, just verify it is empty.
1361 		uint8_t buf;
1362 		int n = read(ctx->data_transfer_fd, &buf, 1);
1363 		if (n < 0) {
1364 			w_logf(ctx, LOG_ERR, "%s: read failed: %s\n", __func__, strerror(errno));
1365 			abort();
1366 		}
1367 		if (n != 0) {
1368 			w_logf(ctx, LOG_ERR, "%s: loaded device state is non-empty. BUG!\n", __func__);
1369 			abort();
1370 		}
1371 		close(ctx->data_transfer_fd);
1372 		break;
1373 	}
1374 	default:
1375 		w_logf(ctx, LOG_ERR, "%s: invalid transfer_direction: %d\n", __func__, ctx->data_transfer_direction);
1376 		abort();
1377 	}
1378 	return NULL;
1379 }
1380 
wmediumd_vu_start_data_transfer(struct usfstl_vhost_user_dev * dev,uint32_t transfer_direction,int fd)1381 static void wmediumd_vu_start_data_transfer(struct usfstl_vhost_user_dev *dev, uint32_t transfer_direction, int fd) {
1382 	struct wmediumd *ctx = dev->server->data;
1383 
1384 	if (ctx->data_transfer_fd != -1) {
1385 		w_logf(ctx, LOG_ERR, "%s: can't start multiple data transfers\n", __func__);
1386 		abort();
1387 	}
1388 
1389 	ctx->data_transfer_fd = fd;
1390 	ctx->data_transfer_direction = transfer_direction;
1391 	if (pthread_create(&ctx->data_transfer_thread, NULL, &do_data_transfer, ctx)) {
1392 		w_logf(ctx, LOG_ERR, "%s: pthread_create failed: %s\n", __func__, strerror(errno));
1393 		abort();
1394 	}
1395 }
wmediumd_vu_check_data_transfer(struct usfstl_vhost_user_dev * dev)1396 static void wmediumd_vu_check_data_transfer(struct usfstl_vhost_user_dev *dev) {
1397 	struct wmediumd *ctx = dev->server->data;
1398 	if (ctx->data_transfer_fd == -1) {
1399 		w_logf(ctx, LOG_ERR, "%s: no active data transfer\n", __func__);
1400 		abort();
1401 	}
1402 	if (pthread_join(ctx->data_transfer_thread, NULL)) {
1403 		w_logf(ctx, LOG_ERR, "%s: pthread_join failed: %s\n", __func__, strerror(errno));
1404 		abort();
1405 	}
1406 	ctx->data_transfer_fd = -1;
1407 }
1408 
process_set_snr_message(struct wmediumd * ctx,struct wmediumd_set_snr * set_snr)1409 static int process_set_snr_message(struct wmediumd *ctx, struct wmediumd_set_snr *set_snr) {
1410 	struct station *node1 = get_station_by_addr(ctx, set_snr->node1_mac);
1411 	struct station *node2 = get_station_by_addr(ctx, set_snr->node2_mac);
1412 
1413 	if (node1 == NULL || node2 == NULL) {
1414 		return -1;
1415 	}
1416 
1417 	ctx->snr_matrix[ctx->num_stas * node2->index + node1->index] = set_snr->snr;
1418 	ctx->snr_matrix[ctx->num_stas * node1->index + node2->index] = set_snr->snr;
1419 
1420 	return 0;
1421 }
1422 
process_load_config_message(struct wmediumd * ctx,struct wmediumd_load_config * reload_config)1423 static int process_load_config_message(struct wmediumd *ctx,
1424 					 struct wmediumd_load_config *reload_config) {
1425 	char *config_path;
1426 	int result = 0;
1427 
1428 	config_path = reload_config->config_path;
1429 
1430 	if (validate_config(config_path)) {
1431 		clear_config(ctx);
1432 		load_config(ctx, config_path, NULL);
1433 	} else {
1434 		result = -1;
1435 	}
1436 
1437 	return result;
1438 }
1439 
process_reload_current_config_message(struct wmediumd * ctx)1440 static int process_reload_current_config_message(struct wmediumd *ctx) {
1441 	char *config_path;
1442 	int result = 0;
1443 
1444 	config_path = strdup(ctx->config_path);
1445 
1446 	if (validate_config(config_path)) {
1447 		clear_config(ctx);
1448 		load_config(ctx, config_path, NULL);
1449 	} else {
1450 		result = -1;
1451 	}
1452 
1453 	free(config_path);
1454 
1455 	return result;
1456 }
1457 
process_get_stations_message(struct wmediumd * ctx,ssize_t * response_len,unsigned char ** response_data)1458 static int process_get_stations_message(struct wmediumd *ctx, ssize_t *response_len, unsigned char **response_data) {
1459 	struct station *station;
1460 	int station_count = 0;
1461 	int extra_data_len = 0;
1462 
1463 	// *reponse_data contains struct wmediumd_station_infos
1464 	// and then lci and civiclocs for each station follows afterwards.
1465 	list_for_each_entry(station, &ctx->stations, list) {
1466 		if (station->client != NULL) {
1467 			++station_count;
1468 			extra_data_len += strlen_safe(station->lci) + 1;
1469 			extra_data_len += strlen_safe(station->civicloc) + 1;
1470 		}
1471 	}
1472 
1473 	int station_len = sizeof(uint32_t) + sizeof(struct wmediumd_station_info) * station_count;
1474 	*response_len = station_len + extra_data_len;
1475 	*response_data = malloc(*response_len);
1476 
1477 	if (*response_data == NULL) {
1478 		w_logf(ctx, LOG_ERR, "%s: failed allocate response data\n", __func__);
1479 		return -1;
1480 	}
1481 
1482 	struct wmediumd_station_infos *station_infos = (struct wmediumd_station_infos *)*response_data;
1483 	station_infos->count = station_count;
1484 	int station_index = 0;
1485 	// Pointer to the memory after structs wmediumd_station_infos
1486 	// to write lci and civicloc for each station.
1487 	char *extra_data_cursor = (char *)&(station_infos->stations[station_count]);
1488 
1489 	list_for_each_entry(station, &ctx->stations, list) {
1490 		if (station->client != NULL) {
1491 			struct wmediumd_station_info *station_info = &station_infos->stations[station_index];
1492 			memcpy(station_info->addr, station->addr, ETH_ALEN);
1493 			memcpy(station_info->hwaddr, station->hwaddr, ETH_ALEN);
1494 
1495 			station_info->x = station->x;
1496 			station_info->y = station->y;
1497 			station_info->lci_offset = extra_data_cursor - (char *)station_info;
1498 			extra_data_cursor = stpcpy_safe(extra_data_cursor, station->lci) + 1;
1499 			station_info->civicloc_offset = extra_data_cursor - (char *)station_info;
1500 			extra_data_cursor = stpcpy_safe(extra_data_cursor, station->civicloc) + 1;
1501 			station_info->tx_power = station->tx_power;
1502 			station_index++;
1503 		}
1504 	}
1505 
1506 	return 0;
1507 }
1508 
process_set_position_message(struct wmediumd * ctx,struct wmediumd_set_position * set_position)1509 static int process_set_position_message(struct wmediumd *ctx, struct wmediumd_set_position *set_position) {
1510 	struct station *node = get_station_by_addr(ctx, set_position->mac);
1511 
1512 	if (node == NULL) {
1513 		return -1;
1514 	}
1515 
1516 	node->x = set_position->x;
1517 	node->y = set_position->y;
1518 
1519 	calc_path_loss(ctx);
1520 
1521 	return 0;
1522 }
1523 
process_set_tx_power_message(struct wmediumd * ctx,struct wmediumd_set_tx_power * set_tx_power)1524 static int process_set_tx_power_message(struct wmediumd *ctx, struct wmediumd_set_tx_power *set_tx_power) {
1525 	struct station *node = get_station_by_addr(ctx, set_tx_power->mac);
1526 
1527 	if (node == NULL) {
1528 		return -1;
1529 	}
1530 
1531 	node->tx_power = set_tx_power->tx_power;
1532 
1533 	calc_path_loss(ctx);
1534 
1535 	return 0;
1536 }
1537 
process_set_lci_message(struct wmediumd * ctx,struct wmediumd_set_lci * set_lci,size_t data_len)1538 static int process_set_lci_message(struct wmediumd *ctx, struct wmediumd_set_lci *set_lci, size_t data_len) {
1539 	struct station *node = get_station_by_addr(ctx, set_lci->mac);
1540 
1541 	if (node == NULL) {
1542 		return -1;
1543 	}
1544 	int expected_len = data_len - offsetof(struct wmediumd_set_lci, lci) - 1;
1545 	if (set_lci->lci[expected_len] != '\0') {
1546 		return -1;
1547 	}
1548 
1549 	if (node->lci) {
1550 		free(node->lci);
1551 	}
1552 	node->lci = strdup(set_lci->lci);
1553 
1554 	return node->lci == NULL ? -1 : 0;
1555 }
1556 
process_set_civicloc_message(struct wmediumd * ctx,struct wmediumd_set_civicloc * set_civicloc,size_t data_len)1557 static int process_set_civicloc_message(struct wmediumd *ctx, struct wmediumd_set_civicloc *set_civicloc, size_t data_len) {
1558 	struct station *node = get_station_by_addr(ctx, set_civicloc->mac);
1559 
1560 	if (node == NULL) {
1561 		return -1;
1562 	}
1563 	int expected_len = data_len - offsetof(struct wmediumd_set_civicloc, civicloc) - 1;
1564 	if (set_civicloc->civicloc[expected_len] != '\0') {
1565 		return -1;
1566 	}
1567 
1568 	if (node->civicloc) {
1569 		free(node->civicloc);
1570 	}
1571 	node->civicloc = strdup(set_civicloc->civicloc);
1572 
1573 	return node->civicloc == NULL ? -1 : 0;
1574 }
1575 
1576 static const struct usfstl_vhost_user_ops wmediumd_vu_ops = {
1577 	.connected = wmediumd_vu_connected,
1578 	.handle = wmediumd_vu_handle,
1579 	.disconnected = wmediumd_vu_disconnected,
1580 	.start_data_transfer = wmediumd_vu_start_data_transfer,
1581 	.check_data_transfer = wmediumd_vu_check_data_transfer,
1582 };
1583 
close_pcapng(struct wmediumd * ctx)1584 static void close_pcapng(struct wmediumd *ctx) {
1585 	if (ctx->pcap_file == NULL) {
1586 		return;
1587 	}
1588 
1589 	fflush(ctx->pcap_file);
1590 	fclose(ctx->pcap_file);
1591 
1592 	ctx->pcap_file = NULL;
1593 }
1594 
1595 static void init_pcapng(struct wmediumd *ctx, const char *filename);
1596 
wmediumd_send_grpc_response(int msq_id,long msg_type_response,enum wmediumd_grpc_response_data_type data_type,ssize_t data_size,unsigned char * data_payload)1597 static void wmediumd_send_grpc_response(int msq_id, long msg_type_response, enum wmediumd_grpc_response_data_type data_type, ssize_t data_size, unsigned char *data_payload) {
1598 	struct wmediumd_grpc_response_message response_message;
1599 	response_message.msg_type_response = msg_type_response;
1600 	response_message.data_type = data_type;
1601 	response_message.data_size = data_size;
1602 	if (data_size > 0) {
1603 		memcpy(response_message.data_payload, data_payload, data_size);
1604 	}
1605 	msgsnd(msq_id, &response_message, MSG_TYPE_RESPONSE_SIZE, 0);
1606 }
1607 
wmediumd_grpc_service_handler(struct usfstl_loop_entry * entry)1608 static void wmediumd_grpc_service_handler(struct usfstl_loop_entry *entry) {
1609 	struct wmediumd *ctx = entry->data;
1610 	ssize_t msg_len;
1611 
1612 	// Receive event from wmediumd_server
1613 	uint64_t evt;
1614 	read(entry->fd, &evt, sizeof(evt));
1615 
1616 	struct wmediumd_grpc_request_message request_message;
1617 	msg_len = msgrcv(ctx->msq_id, &request_message, MSG_TYPE_REQUEST_SIZE, MSG_TYPE_REQUEST, IPC_NOWAIT);
1618 	if (msg_len != MSG_TYPE_REQUEST_SIZE) {
1619 		w_logf(ctx, LOG_ERR, "%s: failed to get request message\n", __func__);
1620 	} else {
1621 		switch (request_message.data_type) {
1622 		case REQUEST_LIST_STATIONS: {
1623 			ssize_t size = 0;
1624 			unsigned char *payload = NULL;
1625 			if (process_get_stations_message(ctx, &size, &payload) < 0) {
1626 				w_logf(ctx, LOG_ERR, "%s: failed to execute list_stations\n", __func__);
1627 				wmediumd_send_grpc_response(ctx->msq_id, request_message.msg_type_response, RESPONSE_INVALID, 0, NULL);
1628 			} else {
1629 				wmediumd_send_grpc_response(ctx->msq_id, request_message.msg_type_response, RESPONSE_ACK_LIST_STATIONS, size, payload);
1630 			}
1631 			break;
1632 		}
1633 		case REQUEST_LOAD_CONFIG:
1634 			if (process_load_config_message(ctx, (struct wmediumd_load_config *)(request_message.data_payload)) < 0) {
1635 				w_logf(ctx, LOG_ERR, "%s: failed to execute load_config\n", __func__);
1636 				wmediumd_send_grpc_response(ctx->msq_id, request_message.msg_type_response, RESPONSE_INVALID, 0, NULL);
1637 				break;
1638 			}
1639 			wmediumd_send_grpc_response(ctx->msq_id, request_message.msg_type_response, RESPONSE_ACK, 0, NULL);
1640 			break;
1641 		case REQUEST_RELOAD_CONFIG:
1642 			if (process_reload_current_config_message(ctx) < 0) {
1643 				w_logf(ctx, LOG_ERR, "%s: failed to execute reload_config\n", __func__);
1644 				wmediumd_send_grpc_response(ctx->msq_id, request_message.msg_type_response, RESPONSE_INVALID, 0, NULL);
1645 				break;
1646 			}
1647 			wmediumd_send_grpc_response(ctx->msq_id, request_message.msg_type_response, RESPONSE_ACK, 0, NULL);
1648 			break;
1649 		case REQUEST_SET_CIVICLOC:
1650 			if (process_set_civicloc_message(ctx, (struct wmediumd_set_civicloc *)(request_message.data_payload), request_message.data_size) < 0) {
1651 				w_logf(ctx, LOG_ERR, "%s: failed to execute set_civicloc\n", __func__);
1652 				wmediumd_send_grpc_response(ctx->msq_id, request_message.msg_type_response, RESPONSE_INVALID, 0, NULL);
1653 				break;
1654 			}
1655 			wmediumd_send_grpc_response(ctx->msq_id, request_message.msg_type_response, RESPONSE_ACK, 0, NULL);
1656 			break;
1657 		case REQUEST_SET_LCI:
1658 			if (process_set_lci_message(ctx, (struct wmediumd_set_lci *)(request_message.data_payload), request_message.data_size) < 0) {
1659 				w_logf(ctx, LOG_ERR, "%s: failed to execute set_lci\n", __func__);
1660 				wmediumd_send_grpc_response(ctx->msq_id, request_message.msg_type_response, RESPONSE_INVALID, 0, NULL);
1661 				break;
1662 			}
1663 			wmediumd_send_grpc_response(ctx->msq_id, request_message.msg_type_response, RESPONSE_ACK, 0, NULL);
1664 			break;
1665 		case REQUEST_SET_POSITION:
1666 			if (process_set_position_message(ctx, (struct wmediumd_set_position *)(request_message.data_payload)) < 0) {
1667 				w_logf(ctx, LOG_ERR, "%s: failed to execute set_position\n", __func__);
1668 				wmediumd_send_grpc_response(ctx->msq_id, request_message.msg_type_response, RESPONSE_INVALID, 0, NULL);
1669 				break;
1670 			}
1671 			wmediumd_send_grpc_response(ctx->msq_id, request_message.msg_type_response, RESPONSE_ACK, 0, NULL);
1672 			break;
1673 		case REQUEST_SET_SNR:
1674 			if (process_set_snr_message(ctx, (struct wmediumd_set_snr *)(request_message.data_payload)) < 0) {
1675 				w_logf(ctx, LOG_ERR, "%s: failed to execute set_snr\n", __func__);
1676 				wmediumd_send_grpc_response(ctx->msq_id, request_message.msg_type_response, RESPONSE_INVALID, 0, NULL);
1677 				break;
1678 			}
1679 			wmediumd_send_grpc_response(ctx->msq_id, request_message.msg_type_response, RESPONSE_ACK, 0, NULL);
1680 			break;
1681 		case REQUEST_SET_TX_POWER:
1682 			if (process_set_tx_power_message(ctx, (struct wmediumd_set_tx_power *)(request_message.data_payload)) < 0) {
1683 				w_logf(ctx, LOG_ERR, "%s: failed to execute set_tx_power\n", __func__);
1684 				wmediumd_send_grpc_response(ctx->msq_id, request_message.msg_type_response, RESPONSE_INVALID, 0, NULL);
1685 				break;
1686 			}
1687 			wmediumd_send_grpc_response(ctx->msq_id, request_message.msg_type_response, RESPONSE_ACK, 0, NULL);
1688 			break;
1689 		case REQUEST_START_PCAP:
1690 			init_pcapng(ctx, ((struct wmediumd_start_pcap *)(request_message.data_payload))->pcap_path);
1691 			wmediumd_send_grpc_response(ctx->msq_id, request_message.msg_type_response, RESPONSE_ACK, 0, NULL);
1692 			break;
1693 		case REQUEST_STOP_PCAP:
1694 			close_pcapng(ctx);
1695 			wmediumd_send_grpc_response(ctx->msq_id, request_message.msg_type_response, RESPONSE_ACK, 0, NULL);
1696 			break;
1697 		default:
1698 			w_logf(ctx, LOG_ERR, "%s: unknown request type\n", __func__);
1699 			wmediumd_send_grpc_response(ctx->msq_id, request_message.msg_type_response, RESPONSE_INVALID, 0, NULL);
1700 			break;
1701 		}
1702 	}
1703 	return;
1704 }
1705 
1706 // TODO(273384914): Deprecate messages used in wmediumd_control after
1707 // implementing in wmediumd_grpc_service_handler to be used in the command
1708 // 'cvd env'.
wmediumd_api_handler(struct usfstl_loop_entry * entry)1709 static void wmediumd_api_handler(struct usfstl_loop_entry *entry)
1710 {
1711 	struct client *client = container_of(entry, struct client, loop);
1712 	struct wmediumd *ctx = entry->data;
1713 	struct wmediumd_message_header hdr;
1714 	enum wmediumd_message response = WMEDIUMD_MSG_ACK;
1715 	struct wmediumd_message_control control = {};
1716 	struct nl_msg *nlmsg;
1717 	unsigned char *data;
1718 	ssize_t response_len = 0;
1719 	unsigned char *response_data = NULL;
1720 	ssize_t len;
1721 
1722 	len = read(entry->fd, &hdr, sizeof(hdr));
1723 	if (len != sizeof(hdr)) {
1724 		if (len > 0) {
1725 			// Skipping log if the fd is closed.
1726 			w_logf(ctx, LOG_ERR, "%s: failed to read header\n", __func__);
1727 		}
1728 		goto disconnect;
1729 	}
1730 
1731 	/* safety valve */
1732 	if (hdr.data_len > 1024 * 1024) {
1733 		w_logf(ctx, LOG_ERR, "%s: too large data\n", __func__);
1734 		goto disconnect;
1735 	}
1736 
1737 	data = malloc(hdr.data_len);
1738 	if (!data) {
1739 		w_logf(ctx, LOG_ERR, "%s: failed to malloc\n", __func__);
1740 		goto disconnect;
1741 	}
1742 
1743 	len = read(entry->fd, data, hdr.data_len);
1744 	if (len != hdr.data_len) {
1745 		w_logf(ctx, LOG_ERR, "%s: failed to read data\n", __func__);
1746 		goto disconnect;
1747 	}
1748 
1749 	switch (hdr.type) {
1750 	case WMEDIUMD_MSG_REGISTER:
1751 		if (!list_empty(&client->list)) {
1752 			response = WMEDIUMD_MSG_INVALID;
1753 			break;
1754 		}
1755 		list_add(&client->list, &ctx->clients);
1756 		break;
1757 	case WMEDIUMD_MSG_UNREGISTER:
1758 		if (list_empty(&client->list)) {
1759 			response = WMEDIUMD_MSG_INVALID;
1760 			break;
1761 		}
1762 		list_del_init(&client->list);
1763 		break;
1764 	case WMEDIUMD_MSG_NETLINK:
1765 		if (ctx->ctrl)
1766 			usfstl_sched_ctrl_sync_from(ctx->ctrl);
1767 
1768 		if (!nlmsg_ok((const struct nlmsghdr *)data, len)) {
1769 			response = WMEDIUMD_MSG_INVALID;
1770 			break;
1771 		}
1772 
1773 		nlmsg = nlmsg_convert((struct nlmsghdr *)data);
1774 		if (!nlmsg)
1775 			break;
1776 
1777 		_process_messages(nlmsg, ctx, client);
1778 
1779 		nlmsg_free(nlmsg);
1780 		break;
1781 	case WMEDIUMD_MSG_SET_CONTROL:
1782 		/* copy what we get and understand, leave the rest zeroed */
1783 		memcpy(&control, data,
1784 		       min(sizeof(control), hdr.data_len));
1785 
1786 		if (client->flags & WMEDIUMD_CTL_NOTIFY_TX_START)
1787 			ctx->need_start_notify--;
1788 		if (control.flags & WMEDIUMD_CTL_NOTIFY_TX_START)
1789 			ctx->need_start_notify++;
1790 
1791 		client->flags = control.flags;
1792 		break;
1793 	case WMEDIUMD_MSG_GET_STATIONS:
1794 		if (process_get_stations_message(ctx, &response_len, &response_data) < 0) {
1795 			response = WMEDIUMD_MSG_INVALID;
1796 		}
1797 		response = WMEDIUMD_MSG_STATIONS_LIST;
1798 		break;
1799 	case WMEDIUMD_MSG_SET_SNR:
1800 		if (process_set_snr_message(ctx, (struct wmediumd_set_snr *)data) < 0) {
1801 			response = WMEDIUMD_MSG_INVALID;
1802 		}
1803 		break;
1804 	case WMEDIUMD_MSG_RELOAD_CONFIG:
1805 		if (process_load_config_message(ctx,
1806 				(struct wmediumd_load_config *)data) < 0) {
1807 			response = WMEDIUMD_MSG_INVALID;
1808 		}
1809 		break;
1810 	case WMEDIUMD_MSG_RELOAD_CURRENT_CONFIG:
1811 		if (process_reload_current_config_message(ctx) < 0) {
1812 			response = WMEDIUMD_MSG_INVALID;
1813 		}
1814 		break;
1815 	case WMEDIUMD_MSG_START_PCAP:
1816 		init_pcapng(ctx, ((struct wmediumd_start_pcap *)data)->pcap_path);
1817 		break;
1818 	case WMEDIUMD_MSG_STOP_PCAP:
1819 		close_pcapng(ctx);
1820 		break;
1821 	case WMEDIUMD_MSG_SET_POSITION:
1822 		if (process_set_position_message(ctx, (struct wmediumd_set_position *)data) < 0) {
1823 			response = WMEDIUMD_MSG_INVALID;
1824 		}
1825 		break;
1826 	case WMEDIUMD_MSG_SET_LCI:
1827 		if (process_set_lci_message(ctx,
1828 				(struct wmediumd_set_lci *)data,
1829 				hdr.data_len) < 0) {
1830 			response = WMEDIUMD_MSG_INVALID;
1831 		}
1832 		break;
1833 	case WMEDIUMD_MSG_SET_CIVICLOC:
1834 		if (process_set_civicloc_message(ctx,
1835 				(struct wmediumd_set_civicloc *)data,
1836 				hdr.data_len) < 0) {
1837 			response = WMEDIUMD_MSG_INVALID;
1838 		}
1839 		break;
1840 	case WMEDIUMD_MSG_ACK:
1841 		assert(client->wait_for_ack == true);
1842 		assert(hdr.data_len == 0);
1843 		client->wait_for_ack = false;
1844 		/* don't send a response to a response, of course */
1845 		return;
1846 	default:
1847 		w_logf(ctx, LOG_ERR, "%s: unknown message\n", __func__);
1848 		response = WMEDIUMD_MSG_INVALID;
1849 		break;
1850 	}
1851 
1852 	/* return a response */
1853 	hdr.type = response;
1854 	hdr.data_len = response_len;
1855 	len = write(entry->fd, &hdr, sizeof(hdr));
1856 	if (len != sizeof(hdr)) {
1857 		w_logf(ctx, LOG_ERR, "%s: failed to write response header\n", __func__);
1858 		goto disconnect;
1859 	}
1860 
1861 	if (response_data != NULL) {
1862 		if (response_len != 0) {
1863 			len = write(entry->fd, response_data, response_len);
1864 
1865 			if (len != response_len) {
1866 				free(response_data);
1867 				w_logf(ctx, LOG_ERR, "%s: failed to write response data\n", __func__);
1868 				goto disconnect;
1869 			}
1870 		}
1871 
1872 		free(response_data);
1873 		response_data = NULL;
1874 	}
1875 
1876 	return;
1877 disconnect:
1878 	usfstl_loop_unregister(&client->loop);
1879 	wmediumd_remove_client(ctx, client);
1880 }
1881 
wmediumd_api_connected(int fd,void * data)1882 static void wmediumd_api_connected(int fd, void *data)
1883 {
1884 	struct wmediumd *ctx = data;
1885 	struct client *client;
1886 
1887 	client = calloc(1, sizeof(*client));
1888 	client->type = CLIENT_API_SOCK;
1889 	client->loop.fd = fd;
1890 	client->loop.data = ctx;
1891 	client->loop.handler = wmediumd_api_handler;
1892 	usfstl_loop_register(&client->loop);
1893 	INIT_LIST_HEAD(&client->list);
1894 }
1895 
1896 /*
1897  * Register with the kernel to start receiving new frames.
1898  */
send_register_msg(struct wmediumd * ctx)1899 static int send_register_msg(struct wmediumd *ctx)
1900 {
1901 	struct nl_sock *sock = ctx->sock;
1902 	struct nl_msg *msg;
1903 	int ret;
1904 
1905 	msg = nlmsg_alloc();
1906 	if (!msg) {
1907 		w_logf(ctx, LOG_ERR, "Error allocating new message MSG!\n");
1908 		return -1;
1909 	}
1910 
1911 	if (genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, ctx->family_id,
1912 			0, NLM_F_REQUEST, HWSIM_CMD_REGISTER,
1913 			VERSION_NR) == NULL) {
1914 		w_logf(ctx, LOG_ERR, "%s: genlmsg_put failed\n", __func__);
1915 		ret = -1;
1916 		goto out;
1917 	}
1918 
1919 	ret = nl_send_auto_complete(sock, msg);
1920 	if (ret < 0) {
1921 		w_logf(ctx, LOG_ERR, "%s: nl_send_auto failed\n", __func__);
1922 		ret = -1;
1923 		goto out;
1924 	}
1925 	ret = 0;
1926 
1927 out:
1928 	nlmsg_free(msg);
1929 	return ret;
1930 }
1931 
sock_event_cb(struct usfstl_loop_entry * entry)1932 static void sock_event_cb(struct usfstl_loop_entry *entry)
1933 {
1934 	struct wmediumd *ctx = entry->data;
1935 
1936 	nl_recvmsgs_default(ctx->sock);
1937 }
1938 
1939 /*
1940  * Setup netlink socket and callbacks.
1941  */
init_netlink(struct wmediumd * ctx)1942 static int init_netlink(struct wmediumd *ctx)
1943 {
1944 	struct nl_sock *sock;
1945 	int ret;
1946 
1947 	ctx->cb = nl_cb_alloc(NL_CB_CUSTOM);
1948 	if (!ctx->cb) {
1949 		w_logf(ctx, LOG_ERR, "Error allocating netlink callbacks\n");
1950 		return -1;
1951 	}
1952 
1953 	sock = nl_socket_alloc_cb(ctx->cb);
1954 	if (!sock) {
1955 		w_logf(ctx, LOG_ERR, "Error allocating netlink socket\n");
1956 		return -1;
1957 	}
1958 
1959 	ctx->sock = sock;
1960 
1961 	ret = genl_connect(sock);
1962 	if (ret < 0) {
1963 		w_logf(ctx, LOG_ERR, "Error connecting netlink socket ret=%d\n", ret);
1964 		return -1;
1965 	}
1966 
1967 	ctx->family_id = genl_ctrl_resolve(sock, "MAC80211_HWSIM");
1968 	if (ctx->family_id < 0) {
1969 		w_logf(ctx, LOG_ERR, "Family MAC80211_HWSIM not registered\n");
1970 		return -1;
1971 	}
1972 
1973 	nl_cb_set(ctx->cb, NL_CB_MSG_IN, NL_CB_CUSTOM, process_messages_cb, ctx);
1974 	nl_cb_err(ctx->cb, NL_CB_CUSTOM, nl_err_cb, ctx);
1975 
1976 	return 0;
1977 }
1978 
1979 /*
1980  *	Print the CLI help
1981  */
print_help(int exval)1982 static void print_help(int exval)
1983 {
1984 	printf("wmediumd v%s - a wireless medium simulator\n", VERSION_STR);
1985 	printf("wmediumd [-h] [-V] [-l LOG_LVL] [-x FILE] -c FILE \n\n");
1986 
1987 	printf("  -h              print this help and exit\n");
1988 	printf("  -V              print version and exit\n\n");
1989 
1990 	printf("  -l LOG_LVL      set the logging level\n");
1991 	printf("                  LOG_LVL: RFC 5424 severity, values 0 - 7\n");
1992 	printf("                  >= 3: errors are logged\n");
1993 	printf("                  >= 5: startup msgs are logged\n");
1994 	printf("                  >= 6: dropped packets are logged (default)\n");
1995 	printf("                  == 7: all packets will be logged\n");
1996 	printf("  -c FILE         set input config file\n");
1997 	printf("  -x FILE         set input PER file\n");
1998 	printf("  -t socket       set the time control socket\n");
1999 	printf("  -u socket       expose vhost-user socket, don't use netlink\n");
2000 	printf("  -a socket       expose wmediumd API socket\n");
2001 	printf("  -n              force netlink use even with vhost-user\n");
2002 	printf("  -p FILE         log packets to pcapng file FILE\n");
2003 
2004 	exit(exval);
2005 }
2006 
init_pcapng(struct wmediumd * ctx,const char * filename)2007 static void init_pcapng(struct wmediumd *ctx, const char *filename)
2008 {
2009 	struct {
2010 		uint32_t type, blocklen, byte_order;
2011 		uint16_t ver_maj, ver_min;
2012 		uint64_t seclen;
2013 		uint32_t blocklen2;
2014 	} __attribute__((packed)) blockhdr = {
2015 		.type = 0x0A0D0D0A,
2016 		.blocklen = sizeof(blockhdr),
2017 		.byte_order = 0x1A2B3C4D,
2018 		.ver_maj = 1,
2019 		.ver_min = 0,
2020 		.seclen = -1,
2021 		.blocklen2 = sizeof(blockhdr),
2022 	};
2023 	struct {
2024 		uint32_t type, blocklen;
2025 		uint16_t linktype, reserved;
2026 		uint32_t snaplen;
2027 		struct {
2028 			uint16_t code, len;
2029 			uint8_t val, pad[3];
2030 		} opt_if_tsresol;
2031 		struct {
2032 			uint16_t code, len;
2033 		} opt_endofopt;
2034 		uint32_t blocklen2;
2035 	} __attribute__((packed)) idb = {
2036 		.type = 1,
2037 		.blocklen = sizeof(idb),
2038 		.linktype = 127, // radiotap
2039 		.snaplen = -1,
2040 		.opt_if_tsresol.code = 9,
2041 		.opt_if_tsresol.len = 1,
2042 		.opt_if_tsresol.val = 6, // usec
2043 		.blocklen2 = sizeof(idb),
2044 	};
2045 
2046 	if (ctx->pcap_file != NULL) {
2047 		close_pcapng(ctx);
2048 	}
2049 
2050 	if (!filename)
2051 		return;
2052 
2053 	ctx->pcap_file = fopen(filename, "w+");
2054 	fwrite(&blockhdr, sizeof(blockhdr), 1, ctx->pcap_file);
2055 	fwrite(&idb, sizeof(idb), 1, ctx->pcap_file);
2056 }
2057 
2058 #ifndef VIRTIO_F_VERSION_1
2059 #define VIRTIO_F_VERSION_1 32
2060 #endif
2061 
wmediumd_main(int argc,char * argv[],int event_fd,int msq_id)2062 int wmediumd_main(int argc, char *argv[], int event_fd, int msq_id)
2063 {
2064 	int opt;
2065 	struct wmediumd ctx = {};
2066 	char *config_file = NULL;
2067 	char *per_file = NULL;
2068 	const char *time_socket = NULL, *api_socket = NULL;
2069 	struct usfstl_sched_ctrl ctrl = {};
2070 	struct usfstl_vhost_user_server vusrv = {
2071 		.ops = &wmediumd_vu_ops,
2072 		.max_queues = HWSIM_NUM_VQS,
2073 		.input_queues = 1 << HWSIM_VQ_TX,
2074 		.features = 1ULL << VIRTIO_F_VERSION_1,
2075 		.protocol_features =
2076 			1ULL << VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS,
2077 		.data = &ctx,
2078 	};
2079 	bool use_netlink, force_netlink = false;
2080 
2081 	setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
2082 
2083 	if (argc == 1) {
2084 		fprintf(stderr, "This program needs arguments....\n\n");
2085 		print_help(EXIT_FAILURE);
2086 	}
2087 
2088 	ctx.log_lvl = 6;
2089 	unsigned long int parse_log_lvl;
2090 	char* parse_end_token;
2091 
2092 	while ((opt = getopt(argc, argv, "hVc:l:x:t:u:a:np:")) != -1) {
2093 		switch (opt) {
2094 		case 'h':
2095 			print_help(EXIT_SUCCESS);
2096 			break;
2097 		case 'V':
2098 			printf("wmediumd v%s - a wireless medium simulator "
2099 			       "for mac80211_hwsim\n", VERSION_STR);
2100 			exit(EXIT_SUCCESS);
2101 			break;
2102 		case 'c':
2103 			config_file = optarg;
2104 			break;
2105 		case 'x':
2106 			printf("Input packet error rate file: %s\n", optarg);
2107 			per_file = optarg;
2108 			break;
2109 		case ':':
2110 			printf("wmediumd: Error - Option `%c' "
2111 			       "needs a value\n\n", optopt);
2112 			print_help(EXIT_FAILURE);
2113 			break;
2114 		case 'l':
2115 			parse_log_lvl = strtoul(optarg, &parse_end_token, 10);
2116 			if ((parse_log_lvl == ULONG_MAX && errno == ERANGE) ||
2117 			     optarg == parse_end_token || parse_log_lvl > 7) {
2118 				printf("wmediumd: Error - Invalid RFC 5424 severity level: "
2119 							   "%s\n\n", optarg);
2120 				print_help(EXIT_FAILURE);
2121 			}
2122 			ctx.log_lvl = parse_log_lvl;
2123 			break;
2124 		case 't':
2125 			time_socket = optarg;
2126 			break;
2127 		case 'u':
2128 			vusrv.socket = optarg;
2129 			break;
2130 		case 'a':
2131 			api_socket = optarg;
2132 			break;
2133 		case 'n':
2134 			force_netlink = true;
2135 			break;
2136 		case 'p':
2137 			init_pcapng(&ctx, optarg);
2138 			break;
2139 		case '?':
2140 			printf("wmediumd: Error - No such option: "
2141 			       "`%c'\n\n", optopt);
2142 			print_help(EXIT_FAILURE);
2143 			break;
2144 		}
2145 
2146 	}
2147 
2148 	if (optind < argc)
2149 		print_help(EXIT_FAILURE);
2150 
2151 	if (!config_file) {
2152 		printf("%s: config file must be supplied\n", argv[0]);
2153 		print_help(EXIT_FAILURE);
2154 	}
2155 
2156 	w_logf(&ctx, LOG_NOTICE, "Input configuration file: %s\n", config_file);
2157 
2158 	INIT_LIST_HEAD(&ctx.stations);
2159 	INIT_LIST_HEAD(&ctx.clients);
2160 	INIT_LIST_HEAD(&ctx.clients_to_free);
2161 
2162 	if (load_config(&ctx, config_file, per_file))
2163 		return EXIT_FAILURE;
2164 
2165 	use_netlink = force_netlink || !vusrv.socket;
2166 
2167 	/* init netlink */
2168 	if (use_netlink && init_netlink(&ctx) < 0)
2169 		return EXIT_FAILURE;
2170 
2171 	if (ctx.intf) {
2172 		ctx.intf_job.start = 10000; // usec
2173 		ctx.intf_job.name = "interference update";
2174 		ctx.intf_job.data = &ctx;
2175 		ctx.intf_job.callback = wmediumd_intf_update;
2176 		usfstl_sched_add_job(&scheduler, &ctx.intf_job);
2177 	}
2178 
2179 	if (vusrv.socket)
2180 		usfstl_vhost_user_server_start(&vusrv);
2181 
2182 	if (use_netlink) {
2183 		ctx.nl_client.type = CLIENT_NETLINK;
2184 		list_add(&ctx.nl_client.list, &ctx.clients);
2185 
2186 		ctx.nl_loop.handler = sock_event_cb;
2187 		ctx.nl_loop.data = &ctx;
2188 		ctx.nl_loop.fd = nl_socket_get_fd(ctx.sock);
2189 		usfstl_loop_register(&ctx.nl_loop);
2190 
2191 		/* register for new frames */
2192 		if (send_register_msg(&ctx) == 0)
2193 			w_logf(&ctx, LOG_NOTICE, "REGISTER SENT!\n");
2194 	}
2195 
2196 	if (api_socket) {
2197 		signal(SIGPIPE, SIG_IGN);
2198 		usfstl_uds_create(api_socket, wmediumd_api_connected, &ctx);
2199 	}
2200 
2201 	if (time_socket) {
2202 		usfstl_sched_ctrl_start(&ctrl, time_socket,
2203 				      100,
2204 				      (uint64_t)-1 /* no ID */,
2205 				      &scheduler);
2206 		vusrv.scheduler = &scheduler;
2207 		vusrv.ctrl = &ctrl;
2208 		ctx.ctrl = &ctrl;
2209 	} else {
2210 		usfstl_sched_wallclock_init(&scheduler, 100);
2211 	}
2212 
2213 	// Control event_fd to communicate WmediumdService.
2214 	ctx.grpc_loop.handler = wmediumd_grpc_service_handler;
2215 	ctx.grpc_loop.data = &ctx;
2216 	ctx.grpc_loop.fd = event_fd;
2217 	usfstl_loop_register(&ctx.grpc_loop);
2218 	ctx.msq_id = msq_id;
2219 
2220 	ctx.data_transfer_fd = -1;
2221 
2222 	while (1) {
2223 		if (time_socket) {
2224 			usfstl_sched_next(&scheduler);
2225 		} else {
2226 			usfstl_sched_wallclock_wait_and_handle(&scheduler);
2227 
2228 			if (usfstl_sched_next_pending(&scheduler, NULL))
2229 				usfstl_sched_next(&scheduler);
2230 		}
2231 
2232 		while (!list_empty(&ctx.clients_to_free)) {
2233 			struct client *client;
2234 
2235 			client = list_first_entry(&ctx.clients_to_free,
2236 						  struct client, list);
2237 
2238 			list_del(&client->list);
2239 			free(client);
2240 		}
2241 	}
2242 
2243 	free(ctx.sock);
2244 	free(ctx.cb);
2245 	free(ctx.intf);
2246 	free(ctx.per_matrix);
2247 
2248 	return EXIT_SUCCESS;
2249 }
2250