handle WTP QoS IE
This commit is contained in:
		| @ -113,6 +113,42 @@ application: { | ||||
| 				current = 100; | ||||
| 				supported = [ 100 ]; | ||||
| 			}; | ||||
| 			qos = { | ||||
| 				taggingpolicy = 0;		# not used yet | ||||
| 				voice = { | ||||
| 					queuedepth = 1;		# not used yet | ||||
| 					cwmin = 2; | ||||
| 					cwmax = 3; | ||||
| 					aifs = 2; | ||||
| 					priority8021p = 0;	# not used yet | ||||
| 					dscp = 0;		# not used yet | ||||
| 				}; | ||||
| 				video = { | ||||
| 					queuedepth = 1;		# not used yet | ||||
| 					cwmin = 3; | ||||
| 					cwmax = 4; | ||||
| 					aifs = 2; | ||||
| 					priority8021p = 0;	# not used yet | ||||
| 					dscp = 0;		# not used yet | ||||
| 				}; | ||||
|  | ||||
| 				besteffort = { | ||||
| 					queuedepth = 1;		# not used yet | ||||
| 					cwmin = 4; | ||||
| 					cwmax = 10; | ||||
| 					aifs = 3; | ||||
| 					priority8021p = 0;	# not used yet | ||||
| 					dscp = 0;		# not used yet | ||||
| 				}; | ||||
| 				background = { | ||||
| 					queuedepth = 1;		# not used yet | ||||
| 					cwmin = 4; | ||||
| 					cwmax = 10; | ||||
| 					aifs = 7; | ||||
| 					priority8021p = 0;	# not used yet | ||||
| 					dscp = 0;		# not used yet | ||||
| 				}; | ||||
| 			}; | ||||
| 		} | ||||
| 	); | ||||
|  | ||||
|  | ||||
| @ -1438,6 +1438,37 @@ int wifi_device_setfrequency(struct wifi_device* device, uint32_t band, uint32_t | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| int wifi_device_settxqueue(struct wifi_device *device, struct capwap_80211_wtpqos_element *qos) | ||||
| { | ||||
| 	int i, txop; | ||||
|  | ||||
| 	for (i = 0; i < CAPWAP_UPDATE_STATION_QOS_SUBELEMENTS; i++) { | ||||
| 		switch (i) { | ||||
| 		case 0:			/* Best Effort */ | ||||
| 			txop = 0; | ||||
| 			break; | ||||
| 		case 1:			/* Background */ | ||||
| 			txop = 0; | ||||
| 			break; | ||||
| 		case 2:			/* Video */ | ||||
| 			txop = 94; | ||||
| 			break; | ||||
| 		case 3:			/* Voice */ | ||||
| 			txop = 47; | ||||
| 			break; | ||||
| 		default: | ||||
| 			return -1; | ||||
| 		} | ||||
|  | ||||
| 		if (device->instance->ops->device_settxqueue(device, i, | ||||
| 							     qos->qos[i].aifs, | ||||
| 							     qos->qos[i].cwmin, | ||||
| 							     qos->qos[i].cwmax, txop) < 0) | ||||
| 			return -1; | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| /* */ | ||||
| int wifi_device_updaterates(struct wifi_device* device, uint8_t* rates, int ratescount) { | ||||
| 	struct device_setrates_params buildrate; | ||||
|  | ||||
| @ -67,6 +67,8 @@ DECLARE_OPAQUE_TYPE(wifi_global_handle); | ||||
| DECLARE_OPAQUE_TYPE(wifi_device_handle); | ||||
| DECLARE_OPAQUE_TYPE(wifi_wlan_handle); | ||||
|  | ||||
| struct capwap_80211_wtpqos_element; | ||||
|  | ||||
| /* */ | ||||
| struct device_setrates_params { | ||||
| 	int supportedratescount; | ||||
| @ -380,6 +382,8 @@ struct wifi_driver_ops { | ||||
| 	int (*device_getcapability)(struct wifi_device* device, struct wifi_capability* capability); | ||||
| 	void (*device_updatebeacons)(struct wifi_device* device); | ||||
| 	int (*device_setfrequency)(struct wifi_device* device); | ||||
| 	int (*device_settxqueue)(struct wifi_device* device, int queue, int aifs, | ||||
| 				 int cw_min, int cw_max, int txop); | ||||
| 	void (*device_deinit)(struct wifi_device* device); | ||||
|  | ||||
| 	/* WLAN functions */ | ||||
| @ -410,6 +414,7 @@ struct wifi_device* wifi_device_connect(const char* ifname, const char* driver); | ||||
| const struct wifi_capability* wifi_device_getcapability(struct wifi_device* device); | ||||
| int wifi_device_setconfiguration(struct wifi_device* device, struct device_setconfiguration_params* params); | ||||
| int wifi_device_setfrequency(struct wifi_device* device, uint32_t band, uint32_t mode, uint8_t channel); | ||||
| int wifi_device_settxqueue(struct wifi_device *device, struct capwap_80211_wtpqos_element *qos); | ||||
| int wifi_device_updaterates(struct wifi_device* device, uint8_t* rates, int ratescount); | ||||
|  | ||||
| /* WLAN management */ | ||||
|  | ||||
| @ -1553,6 +1553,80 @@ static void nl80211_device_updatebeacons(struct wifi_device* device) { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* */ | ||||
| static int nl80211_device_settxqueue(struct wifi_device* device, int queue, int aifs, | ||||
| 				     int cw_min, int cw_max, int txop) | ||||
| { | ||||
| 	int result; | ||||
| 	struct nl_msg* msg; | ||||
| 	struct capwap_list_item* wlansearch; | ||||
| 	struct nl80211_device_handle* devicehandle; | ||||
| 	struct wifi_wlan* wlan = NULL; | ||||
| 	struct nlattr *txq, *params; | ||||
|  | ||||
| 	ASSERT(device != NULL); | ||||
| 	ASSERT(device->handle != NULL); | ||||
|  | ||||
| 	/* Search a valid interface */ | ||||
| 	for (wlansearch = device->wlans->first; wlansearch; wlansearch = wlansearch->next) { | ||||
| 		struct wifi_wlan* element = (struct wifi_wlan*)wlansearch->item; | ||||
|  | ||||
| 		if (element->flags & WIFI_WLAN_RUNNING) { | ||||
| 			wlan = element; | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 	if (!wlan) | ||||
| 		return -1; | ||||
|  | ||||
| 	msg = nlmsg_alloc(); | ||||
| 	if (!msg) | ||||
| 		return -1; | ||||
|  | ||||
| 	/* Set TX Queue using device index of first BSS */ | ||||
| 	devicehandle = (struct nl80211_device_handle*)device->handle; | ||||
| 	genlmsg_put(msg, 0, 0, devicehandle->globalhandle->nl80211_id, 0, 0, NL80211_CMD_SET_WIPHY, 0); | ||||
| 	nla_put_u32(msg, NL80211_ATTR_IFINDEX, wlan->virtindex); | ||||
|  | ||||
| 	txq = nla_nest_start(msg, NL80211_ATTR_WIPHY_TXQ_PARAMS); | ||||
|  | ||||
| 	/* We are only sending parameters for a single TXQ at a time */ | ||||
| 	params = nla_nest_start(msg, 1); | ||||
|  | ||||
| 	switch (queue) { | ||||
| 	case 0: | ||||
| 		nla_put_u8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_VO); | ||||
| 		break; | ||||
| 	case 1: | ||||
| 		nla_put_u8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_VI); | ||||
| 		break; | ||||
| 	case 2: | ||||
| 		nla_put_u8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_BE); | ||||
| 		break; | ||||
| 	case 3: | ||||
| 		nla_put_u8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_BK); | ||||
| 		break; | ||||
| 	default: | ||||
| 		nlmsg_free(msg); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	nla_put_u16(msg, NL80211_TXQ_ATTR_TXOP, txop); | ||||
| 	nla_put_u16(msg, NL80211_TXQ_ATTR_CWMIN, cw_min); | ||||
| 	nla_put_u16(msg, NL80211_TXQ_ATTR_CWMAX, cw_max); | ||||
| 	nla_put_u8(msg, NL80211_TXQ_ATTR_AIFS, aifs); | ||||
| 	nla_nest_end(msg, params); | ||||
|  | ||||
| 	nla_nest_end(msg, txq); | ||||
|  | ||||
| 	result = nl80211_send_and_recv_msg(devicehandle->globalhandle, msg, NULL, NULL); | ||||
| 	if (result) | ||||
| 		capwap_logging_error("Unable set TX Queue, error code: %d", result); | ||||
|  | ||||
| 	nlmsg_free(msg); | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| /* */ | ||||
| static int nl80211_device_setfrequency(struct wifi_device* device) { | ||||
| 	ASSERT(device != NULL); | ||||
| @ -1793,6 +1867,7 @@ const struct wifi_driver_ops wifi_driver_nl80211_ops = { | ||||
| 	.device_getfdevent = nl80211_device_getfdevent, | ||||
| 	.device_getcapability = nl80211_device_getcapability, | ||||
| 	.device_updatebeacons = nl80211_device_updatebeacons, | ||||
| 	.device_settxqueue = nl80211_device_settxqueue, | ||||
| 	.device_setfrequency = nl80211_device_setfrequency, | ||||
| 	.device_deinit = nl80211_device_deinit, | ||||
|  | ||||
|  | ||||
| @ -157,6 +157,49 @@ static void wtp_print_usage(void) { | ||||
| 	/* TODO */ | ||||
| } | ||||
|  | ||||
| static int wtp_parsing_radio_qos_configuration(config_setting_t *elem, const char *section, | ||||
| 					       struct capwap_80211_wtpqos_subelement *qos) | ||||
| { | ||||
| 	config_setting_t *sect; | ||||
| 	LIBCONFIG_LOOKUP_INT_ARG val; | ||||
|  | ||||
| 	sect = config_setting_get_member(elem, section); | ||||
| 	if (!sect) | ||||
| 		return 0; | ||||
|  | ||||
| 	if (config_setting_lookup_int(sect, "queuedepth", &val) != CONFIG_TRUE || | ||||
| 	    val > 255) | ||||
| 		return 0; | ||||
| 	qos->queuedepth = val; | ||||
|  | ||||
| 	if (config_setting_lookup_int(sect, "cwmin", &val) != CONFIG_TRUE || | ||||
| 	    val > 65565) | ||||
| 		return 0; | ||||
| 	qos->cwmin = val; | ||||
|  | ||||
| 	if (config_setting_lookup_int(sect, "cwmax", &val) != CONFIG_TRUE || | ||||
| 	    val > 65565) | ||||
| 		return 0; | ||||
| 	qos->cwmax = val; | ||||
|  | ||||
| 	if (config_setting_lookup_int(sect, "aifs", &val) != CONFIG_TRUE || | ||||
| 	    val > 255) | ||||
| 		return 0; | ||||
| 	qos->aifs = val; | ||||
|  | ||||
| 	if (config_setting_lookup_int(sect, "priority8021p", &val) != CONFIG_TRUE || | ||||
| 	    val > 7) | ||||
| 		return 0; | ||||
| 	qos->priority8021p = val; | ||||
|  | ||||
| 	if (config_setting_lookup_int(sect, "dscp", &val) != CONFIG_TRUE || | ||||
| 	    val > 255) | ||||
| 		return 0; | ||||
| 	qos->dscp = val; | ||||
|  | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| /* */ | ||||
| static int wtp_parsing_radio_configuration(config_setting_t* configElement, struct wtp_radio* radio) { | ||||
| 	int i, len, cnt; | ||||
| @ -398,6 +441,23 @@ static int wtp_parsing_radio_configuration(config_setting_t* configElement, stru | ||||
| 	else | ||||
| 		radio->radioconfig.country[2] = (uint8_t)' '; | ||||
|  | ||||
| 	/* QoS */ | ||||
| 	radio->qos.radioid = radio->radioid; | ||||
|  | ||||
| 	configSection = config_setting_get_member(configElement, "qos"); | ||||
| 	if (!configSection) | ||||
| 		return 0; | ||||
|  | ||||
| 	if (config_setting_lookup_int(configSection, "taggingpolicy", &configInt) != CONFIG_TRUE || | ||||
| 	    configInt > 255) | ||||
| 		return 0; | ||||
| 	radio->qos.taggingpolicy = (uint8_t)configInt; | ||||
|  | ||||
| 	if (wtp_parsing_radio_qos_configuration(configSection, "voice", &radio->qos.qos[3]) == 0 || | ||||
| 	    wtp_parsing_radio_qos_configuration(configSection, "video", &radio->qos.qos[2]) == 0 || | ||||
| 	    wtp_parsing_radio_qos_configuration(configSection, "besteffort", &radio->qos.qos[0]) == 0 || | ||||
| 	    wtp_parsing_radio_qos_configuration(configSection, "background", &radio->qos.qos[1]) == 0) | ||||
| 		return 0; | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
|  | ||||
| @ -10,6 +10,7 @@ | ||||
| #define WTP_UPDATE_FREQUENCY_OFDM				2 | ||||
| #define WTP_UPDATE_RATES					3 | ||||
| #define WTP_UPDATE_CONFIGURATION				4 | ||||
| #define WTP_UPDATE_TX_QUEUE					5 | ||||
|  | ||||
| struct wtp_update_configuration_item { | ||||
| 	int type; | ||||
| @ -403,6 +404,11 @@ int wtp_radio_setconfiguration(struct capwap_parsed_packet* packet) { | ||||
| 								radio = wtp_radio_get_phy(qos->radioid); | ||||
| 								if (radio && (radio->radioid == qos->radioid)) { | ||||
| 									memcpy(&radio->qos, qos, sizeof(struct capwap_80211_wtpqos_element)); | ||||
|  | ||||
| 									/* Pending change radio channel */ | ||||
| 									item = (struct wtp_update_configuration_item*)capwap_array_get_item_pointer(updateitems, updateitems->count); | ||||
| 									item->type = WTP_UPDATE_TX_QUEUE; | ||||
| 									item->radio = radio; | ||||
| 								} | ||||
| 							} | ||||
| 						} | ||||
| @ -483,6 +489,9 @@ int wtp_radio_setconfiguration(struct capwap_parsed_packet* packet) { | ||||
| 				result = wifi_device_setconfiguration(item->radio->devicehandle, ¶ms); | ||||
| 				break; | ||||
| 			} | ||||
| 			case WTP_UPDATE_TX_QUEUE: | ||||
| 				result = wifi_device_settxqueue(item->radio->devicehandle, &item->radio->qos); | ||||
| 				break; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
|  | ||||
		Reference in New Issue
	
	Block a user