Skip to content

Commit

Permalink
P2P2: Add support for TWT_Power_Management and Unavailability mode
Browse files Browse the repository at this point in the history
Support for TWT_Power_Management enable/disable and for TWT
Unavailability mode.

Signed-off-by: Shivani Baranwal <quic_shivbara@quicinc.com>
  • Loading branch information
Shivani Baranwal authored and Jouni Malinen committed Feb 14, 2025
1 parent d76f857 commit cc75705
Show file tree
Hide file tree
Showing 3 changed files with 246 additions and 12 deletions.
170 changes: 170 additions & 0 deletions p2p.c
Original file line number Diff line number Diff line change
Expand Up @@ -961,10 +961,169 @@ static enum sigma_cmd_result cmd_sta_set_p2p(struct sigma_dut *dut,

}

val = get_param(cmd, "TWT_Power_Management");
if (val) {
int twt_pm = get_enable_disable(val);

snprintf(buf, sizeof(buf), "P2P_SET twt_power_mgmt %d", twt_pm);
if (wpa_command(intf, buf) < 0)
return ERROR_SEND_STATUS;

dut->is_p2p_twt_power_mgmt_enabled = twt_pm;
sigma_dut_print(dut, DUT_MSG_INFO,
"TWT_Power_Management enable: %d", twt_pm);
}

val = get_param(cmd, "UnavailabilityMode");
if (val)
dut->twt_param.unavailability_mode = !!atoi(val);

val = get_param(cmd, "TWT_Trigger");
if (val)
dut->twt_param.twt_trigger = !!atoi(val);

val = get_param(cmd, "WakeIntervalMantissa");
if (val)
dut->twt_param.wake_interval_mantissa = atoi(val);

val = get_param(cmd, "WakeIntervalExp");
if (val)
dut->twt_param.wake_interval_exp = atoi(val);

val = get_param(cmd, "NominalMinWakeDur");
if (val)
dut->twt_param.nominal_min_wake_dur = atoi(val);

val = get_param(cmd, "BTWT_ID");
if (val) {
dut->twt_param.bcast_twt_id = atoi(val);
dut->twt_param.is_bcast_twt = true;
dut->twt_param.is_user_config = true;
dut->twt_param.responder_pm = 1;
}

val = get_param(cmd, "BTWT_Persistence");
if (val)
dut->twt_param.bcast_twt_persis = atoi(val);

val = get_param(cmd, "BTWT_Recommendation");
if (val)
dut->twt_param.bcast_twt_recommdn = atoi(val);

return 1;
}


static int set_p2p_twt_unavailability_mode(struct sigma_dut *dut,
struct sigma_conn *conn,
const char *intf)
{
#ifdef NL80211_SUPPORT
struct nlattr *params;
struct nlattr *attr;
struct nl_msg *msg;
int ifindex, ret;

ifindex = if_nametoindex(intf);
if (ifindex == 0) {
sigma_dut_print(dut, DUT_MSG_ERROR,
"%s: Index for interface %s failed",
__func__, intf);
return -1;
}

msg = nl80211_drv_msg(dut, dut->nl_ctx, ifindex, 0,
NL80211_CMD_VENDOR);
if (!msg ||
nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifindex) ||
nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT)) {
sigma_dut_print(dut, DUT_MSG_ERROR,
"%s: err in adding vendor_cmd", __func__);
nlmsg_free(msg);
return -1;
}

attr = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
if (!attr ||
nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION,
QCA_WLAN_TWT_SET_PARAM)) {
sigma_dut_print(dut, DUT_MSG_ERROR,
"%s: err in adding vendor attr", __func__);
nlmsg_free(msg);
return -1;
}

params = nla_nest_start(msg, QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS);
if (!params ||
nla_put_flag(msg,
QCA_WLAN_VENDOR_ATTR_TWT_SET_PARAM_UNAVAILABILITY_MODE)) {
sigma_dut_print(dut, DUT_MSG_ERROR,
"%s: err in adding vendor_params", __func__);
nlmsg_free(msg);
return -1;
}

nla_nest_end(msg, params);
nla_nest_end(msg, attr);

ret = send_and_recv_msgs(dut, dut->nl_ctx, msg, NULL, NULL);
if (ret)
sigma_dut_print(dut, DUT_MSG_ERROR,
"%s: err in send_and_recv_msgs, ret=%d",
__func__, ret);

return 0;
#else /* NL80211_SUPPORT */
sigma_dut_print(dut, DUT_MSG_ERROR,
"TWT unavailability mode cannot be done without NL80211_SUPPORT defined");
return -1;
#endif /* NL80211_SUPPORT */
}


static int set_p2p_twt_params(struct sigma_dut *dut, struct sigma_conn *conn,
const char *intf)
{
/* Set default param when user config is not available. */
if (!dut->twt_param.is_user_config) {
dut->twt_param.is_bcast_twt = true;
dut->twt_param.unavailability_mode = false;
dut->twt_param.twt_trigger = false;
dut->twt_param.flow_type = 1;
dut->twt_param.protection = 0;
dut->twt_param.target_wake_time = 0;
dut->twt_param.wake_interval_mantissa = 112;
/* SI = pow(2, exp) * mantissa */
dut->twt_param.wake_interval_exp = 10;
/* SP = val * 256 us */
dut->twt_param.nominal_min_wake_dur = 78;
dut->twt_param.bcast_twt_id = 0;
dut->twt_param.bcast_twt_persis = 0;
dut->twt_param.bcast_twt_recommdn = 0;
dut->twt_param.responder_pm = 1;
}

dut->twt_param.cmd_type = 1;
dut->twt_param.ifindex = if_nametoindex(intf);
if (sta_twt_request(dut, conn, NULL) < 0) {
sigma_dut_print(dut, DUT_MSG_ERROR,
"Failed to set default BCAST TWT parms");
return -1;
}

/* Configure Unavailability Mode bit in control field of TWT element */
if (dut->twt_param.unavailability_mode &&
set_p2p_twt_unavailability_mode(dut, conn, intf) < 0) {
sigma_dut_print(dut, DUT_MSG_ERROR,
"Failed to set unavailability mode");
return -1;
}
return 0;
}


static enum sigma_cmd_result
cmd_sta_start_autonomous_go(struct sigma_dut *dut, struct sigma_conn *conn,
struct sigma_cmd *cmd)
Expand Down Expand Up @@ -1118,6 +1277,13 @@ cmd_sta_start_autonomous_go(struct sigma_dut *dut, struct sigma_conn *conn,
}
#endif /* MIRACAST */

if (dut->is_p2p_twt_power_mgmt_enabled &&
set_p2p_twt_params(dut, conn, ifname) < 0) {
sigma_dut_print(dut, DUT_MSG_ERROR,
"Failed to set default TWT-based P2P Power Management");
return ERROR_SEND_STATUS;
}

send_resp(dut, conn, SIGMA_COMPLETE, resp);
return 0;
}
Expand Down Expand Up @@ -1949,6 +2115,10 @@ enum sigma_cmd_result sta_p2p_reset_default(struct sigma_dut *dut,
dut->p2p_client = 0;
dut->wps_method = WFA_CS_WPS_NOT_READY;
dut->pasn_type = 0xf;
dut->is_p2p_twt_power_mgmt_enabled = false;
dut->twt_param.is_user_config = false;
dut->twt_param.is_bcast_twt = false;
dut->twt_param.unavailability_mode = false;

grp = dut->groups;
while (grp) {
Expand Down
23 changes: 23 additions & 0 deletions sigma_dut.h
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,25 @@ enum oper_chan_width {
CONF_OPER_CHWIDTH_320MHZ,
};

struct twt_config_params {
bool is_user_config;
bool is_bcast_twt;
bool unavailability_mode;
bool twt_trigger;
int cmd_type;
int flow_type;
int protection;
int target_wake_time;
int wake_interval_mantissa;
int wake_interval_exp;
int nominal_min_wake_dur;
int bcast_twt_id;
int bcast_twt_persis;
int bcast_twt_recommdn;
int responder_pm;
int ifindex;
};

struct sigma_dut {
const char *main_ifname;
char *main_ifname_2g;
Expand Down Expand Up @@ -1282,6 +1301,8 @@ struct sigma_dut {
bool usd_enabled;
bool p2p_r2_capable;
u8 pasn_type;
bool is_p2p_twt_power_mgmt_enabled;
struct twt_config_params twt_param;
};


Expand Down Expand Up @@ -1433,6 +1454,8 @@ int wcn_set_he_ltf(struct sigma_dut *dut, const char *intf,
#endif /* NL80211_SUPPORT */
void stop_dscp_policy_mon_thread(struct sigma_dut *dut);
void free_dscp_policy_table(struct sigma_dut *dut);
int sta_twt_request(struct sigma_dut *dut, struct sigma_conn *conn,
struct sigma_cmd *cmd);

/* p2p.c */
void p2p_register_cmds(void);
Expand Down
65 changes: 53 additions & 12 deletions sta.c
Original file line number Diff line number Diff line change
Expand Up @@ -11807,8 +11807,10 @@ static int twt_async_event_wait(struct sigma_dut *dut, unsigned int twt_op)
int err_code = 0, select_retval = 0;
struct wait_event wait_info;

if (dut->nl_ctx->event_sock)
cb = nl_socket_get_cb(dut->nl_ctx->event_sock);
if (!dut->nl_ctx->event_sock && nl80211_open_event_sock(dut))
return -1;

cb = nl_socket_get_cb(dut->nl_ctx->event_sock);
if (!cb) {
sigma_dut_print(dut, DUT_MSG_ERROR,
"event callback not found");
Expand Down Expand Up @@ -12067,12 +12069,13 @@ static int sta_twt_resume(struct sigma_dut *dut, struct sigma_conn *conn,
}


#define TWT_REQUEST_CMD 0
#define TWT_SUGGEST_CMD 1
#define TWT_DEMAND_CMD 2
#define TWT_REQUEST_CMD 0
#define TWT_SUGGEST_CMD 1
#define TWT_DEMAND_CMD 2
#define TWT_ALTERNATE_TWT_CMD 5

static int sta_twt_request(struct sigma_dut *dut, struct sigma_conn *conn,
struct sigma_cmd *cmd)
int sta_twt_request(struct sigma_dut *dut, struct sigma_conn *conn,
struct sigma_cmd *cmd)
{
#ifdef NL80211_SUPPORT
struct nlattr *params;
Expand All @@ -12087,6 +12090,32 @@ static int sta_twt_request(struct sigma_dut *dut, struct sigma_conn *conn,
protection = 0, cmd_type = QCA_WLAN_VENDOR_TWT_SETUP_SUGGEST;
int bcast_twt = 0;
int bcast_twt_id = 0, bcast_twt_recommdn = 0, bcast_twt_persis = 0;
int responder_pm = 0;

if (dut->is_p2p_twt_power_mgmt_enabled && !cmd) {
ifindex = dut->twt_param.ifindex;
flow_type = dut->twt_param.flow_type;
twt_trigger = dut->twt_param.twt_trigger;
protection = dut->twt_param.protection;
cmd_type = dut->twt_param.cmd_type;
target_wake_time = dut->twt_param.target_wake_time;
wake_interval_mantissa = dut->twt_param.wake_interval_mantissa;
wake_interval_exp = dut->twt_param.wake_interval_exp;
nominal_min_wake_dur = dut->twt_param.nominal_min_wake_dur;
bcast_twt_id = dut->twt_param.bcast_twt_id;
bcast_twt_persis = dut->twt_param.bcast_twt_persis;
bcast_twt_recommdn = dut->twt_param.bcast_twt_recommdn;
responder_pm = dut->twt_param.responder_pm;
bcast_twt = 1;

goto send_command;
}

if (!cmd) {
sigma_dut_print(dut, DUT_MSG_ERROR,
"NULL cmd received with TWT setup request");
return -1;
}

ifindex = if_nametoindex(intf);
if (ifindex == 0) {
Expand Down Expand Up @@ -12134,16 +12163,20 @@ static int sta_twt_request(struct sigma_dut *dut, struct sigma_conn *conn,
val = get_param(cmd, "SetupCommand");
if (val) {
cmd_type = atoi(val);
if (cmd_type == TWT_REQUEST_CMD)
if (cmd_type == TWT_REQUEST_CMD) {
cmd_type = QCA_WLAN_VENDOR_TWT_SETUP_REQUEST;
else if (cmd_type == TWT_SUGGEST_CMD)
} else if (cmd_type == TWT_SUGGEST_CMD) {
cmd_type = QCA_WLAN_VENDOR_TWT_SETUP_SUGGEST;
else if (cmd_type == TWT_DEMAND_CMD)
} else if (cmd_type == TWT_DEMAND_CMD) {
cmd_type = QCA_WLAN_VENDOR_TWT_SETUP_DEMAND;
else
} else if (cmd_type == TWT_ALTERNATE_TWT_CMD) {
cmd_type = QCA_WLAN_VENDOR_TWT_SETUP_ALTERNATE_TWT;
} else {
sigma_dut_print(dut, DUT_MSG_ERROR,
"Default suggest is used for cmd %d",
"cmd type not supported %d",
cmd_type);
return -1;
}
}

val = get_param(cmd, "TargetWakeTime");
Expand Down Expand Up @@ -12180,12 +12213,17 @@ static int sta_twt_request(struct sigma_dut *dut, struct sigma_conn *conn,
bcast_twt = 1;
}

val = get_param(cmd, "RespPMMode");
if (val)
responder_pm = atoi(val);

if (bcast_twt)
sigma_dut_print(dut, DUT_MSG_DEBUG,
"BCAST_TWT: ID %d, RECOMM %d, PERSIS %d",
bcast_twt_id, bcast_twt_recommdn,
bcast_twt_persis);

send_command:
if (!(msg = nl80211_drv_msg(dut, dut->nl_ctx, ifindex, 0,
NL80211_CMD_VENDOR)) ||
nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifindex) ||
Expand Down Expand Up @@ -12218,6 +12256,9 @@ static int sta_twt_request(struct sigma_dut *dut, struct sigma_conn *conn,
nla_put_u8(msg,
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_RECOMMENDATION,
bcast_twt_recommdn)) ||
(responder_pm &&
nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_RESPONDER_PM_MODE,
responder_pm)) ||
nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME,
target_wake_time) ||
nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_DURATION,
Expand Down

0 comments on commit cc75705

Please sign in to comment.