diff --git a/tools/hwsim.c b/tools/hwsim.c index 18ba111a..8fb9b0a4 100644 --- a/tools/hwsim.c +++ b/tools/hwsim.c @@ -124,6 +124,7 @@ struct hwsim_rule { bool destination_any : 1; bool bidirectional : 1; bool drop : 1; + bool drop_ack : 1; bool enabled : 1; uint32_t frequency; int priority; @@ -1170,7 +1171,7 @@ static bool radio_match_addr(const struct radio_info_rec *radio, static void process_rules(const struct radio_info_rec *src_radio, const struct radio_info_rec *dst_radio, - struct hwsim_frame *frame, bool *drop, + struct hwsim_frame *frame, bool ack, bool *drop, uint32_t *delay) { const struct l_queue_entry *rule_entry; @@ -1224,7 +1225,9 @@ static void process_rules(const struct radio_info_rec *src_radio, if (rule->signal) frame->signal = rule->signal / 100; - *drop = rule->drop; + /* Don't drop if this is an ACK, unless drop_ack is set */ + if (!ack || (ack && rule->drop_ack)) + *drop = rule->drop; if (delay) *delay = rule->delay; @@ -1314,7 +1317,7 @@ static void hwsim_frame_unref(struct hwsim_frame *frame) bool drop = false; process_rules(frame->ack_radio, frame->src_radio, - frame, &drop, NULL); + frame, true, &drop, NULL); if (!drop) frame->flags |= HWSIM_TX_STAT_ACK; @@ -1458,7 +1461,8 @@ static void process_frame(struct hwsim_frame *frame) bool drop_mcast = false; if (util_is_broadcast_address(frame->dst_ether_addr)) - process_rules(frame->src_radio, NULL, frame, &drop_mcast, NULL); + process_rules(frame->src_radio, NULL, frame, false, + &drop_mcast, NULL); for (entry = l_queue_get_entries(radio_info); entry; entry = entry->next) { @@ -1498,7 +1502,8 @@ static void process_frame(struct hwsim_frame *frame) continue; } - process_rules(frame->src_radio, radio, frame, &drop, &delay); + process_rules(frame->src_radio, radio, frame, false, + &drop, &delay); if (drop) continue; @@ -2015,6 +2020,7 @@ static struct l_dbus_message *rule_add(struct l_dbus *dbus, rule->delay = 0; rule->enabled = false; rule->match_times = -1; + rule->drop_ack = true; if (!rules) rules = l_queue_new(); @@ -2450,6 +2456,37 @@ static struct l_dbus_message *rule_property_set_match_times( return l_dbus_message_new_method_return(message); } +static bool rule_property_get_drop_ack(struct l_dbus *dbus, + struct l_dbus_message *message, + struct l_dbus_message_builder *builder, + void *user_data) +{ + struct hwsim_rule *rule = user_data; + bool bval = rule->drop_ack; + + l_dbus_message_builder_append_basic(builder, 'b', &bval); + + return true; +} + +static struct l_dbus_message *rule_property_set_drop_ack( + struct l_dbus *dbus, + struct l_dbus_message *message, + struct l_dbus_message_iter *new_value, + l_dbus_property_complete_cb_t complete, + void *user_data) +{ + struct hwsim_rule *rule = user_data; + bool bval; + + if (!l_dbus_message_iter_get_variant(new_value, "b", &bval)) + return dbus_error_invalid_args(message); + + rule->drop_ack = bval; + + return l_dbus_message_new_method_return(message); +} + static void setup_rule_interface(struct l_dbus_interface *interface) { l_dbus_interface_method(interface, "Remove", 0, rule_remove, "", ""); @@ -2498,6 +2535,10 @@ static void setup_rule_interface(struct l_dbus_interface *interface) L_DBUS_PROPERTY_FLAG_AUTO_EMIT, "q", rule_property_get_match_times, rule_property_set_match_times); + l_dbus_interface_property(interface, "DropAck", + L_DBUS_PROPERTY_FLAG_AUTO_EMIT, "b", + rule_property_get_drop_ack, + rule_property_set_drop_ack); } static void request_name_callback(struct l_dbus *dbus, bool success,