diff --git a/src/Makefile b/src/Makefile index 656e03d702790df9d52ffcb35c17e39f41d2b418..69e8a0830451a8451fc456d84b698d7dc2cbe36c 100644 --- a/src/Makefile +++ b/src/Makefile @@ -7,6 +7,7 @@ OBJS = \ utils/liblist.o \ utils/utils.o \ utils/alloctrace.o \ + utils/opclass.o \ allsta.o \ cntlr_ubus.o \ cntlr.o \ diff --git a/src/cntlr.c b/src/cntlr.c index df09ce19cf1ce72da0d46d6feab300360c0ddec0..6f1a39ec7f2bb175ed574d76c3f0a549d3c77395 100644 --- a/src/cntlr.c +++ b/src/cntlr.c @@ -1134,135 +1134,68 @@ static enum wifi_freqband get_op_class_band(int opclass) } } -static struct opclass_entry *cntlr_radio_opclass_find_entry(struct opclass *opclass, uint8_t id) -{ - struct opclass_entry *entry; - int i; - - for (i = 0; i < opclass->entry_num; i++) { - entry = &opclass->entry[i]; - if (entry->id != id) - continue; - - return entry; - } - - return NULL; -} - -static struct opclass_entry *cntlr_radio_opclass_new_entry(struct opclass *opclass) -{ - struct opclass_entry *entry; - - if (opclass->entry_num >= ARRAY_SIZE(opclass->entry)) - return NULL; - - entry = &opclass->entry[opclass->entry_num]; - opclass->entry_num++; - opclass->entry_time = time(NULL); - - return entry; -} - -static int cntlr_radio_opclass_add_channel(struct opclass_entry *entry, uint8_t channel, uint8_t preference) -{ - int i; - - /* First check if we already have this */ - for (i = 0; i < entry->channels_num; i++) { - if (entry->channels[i].channel == channel) { - entry->channels[i].preference = preference; - return 0; - } - } - - /* Add new channel */ - if (entry->channels_num >= ARRAY_SIZE(entry->channels)) - return -1; - - entry->channels[entry->channels_num].channel = channel; - entry->channels[entry->channels_num].preference = preference; - entry->channels_num++; - - return 0; -} - -static void _cntlr_radio_opclass_reset(struct opclass *opclass) -{ - opclass->entry_num = 0; - memset(opclass->entry, 0, sizeof(opclass->entry)); -} - -static void _cntlr_radio_opclass_dump(struct opclass *opclass) -{ - struct opclass_entry *entry; - int i, j; - - dbg(">>> opclass num: %d\n", opclass->entry_num); - for (i = 0; i < opclass->entry_num; i++) { - entry = &opclass->entry[i]; - dbg("opclass: %u\n", entry->id); - for (j = 0; j < entry->channels_num; j++) { - dbg("\tchan %u pref %u reason %u\n", - entry->channels[j].channel, - (entry->channels[j].preference & CHANNEL_PREF_MASK) >> 4, - entry->channels[j].preference & CHANNEL_PREF_REASON); - } - } - dbg("<<<\n"); -} void cntlr_radio_opclass_reset(struct netif_radio *radio) { - _cntlr_radio_opclass_reset(&radio->opclass); + opclass_reset(&radio->opclass); } int cntlr_radio_opclass_add(struct netif_radio *radio, uint8_t id, uint8_t channel, uint8_t preference) { + struct opclass_channel chan = {}; struct opclass_entry *entry; - entry = cntlr_radio_opclass_find_entry(&radio->opclass, id); + entry = opclass_find_entry(&radio->opclass, id); if (!entry) - entry = cntlr_radio_opclass_new_entry(&radio->opclass); + entry = opclass_new_entry(&radio->opclass); if (!entry) return -1; entry->id = id; entry->bandwidth = get_op_class_bw(id); - return cntlr_radio_opclass_add_channel(entry, channel, preference); + + chan.channel = channel; + chan.preference = preference; + + return opclass_add_channel(entry, &chan); } void cntlr_radio_opclass_dump(struct netif_radio *radio) { - _cntlr_radio_opclass_dump(&radio->opclass); + opclass_dump(&radio->opclass); } void cntlr_radio_cur_opclass_reset(struct netif_radio *radio) { - _cntlr_radio_opclass_reset(&radio->cur_opclass); + opclass_reset(&radio->cur_opclass); } int cntlr_radio_cur_opclass_add(struct netif_radio *radio, uint8_t id, uint8_t channel, uint8_t txpower) { + struct opclass_channel chan = {}; struct opclass_entry *entry; - entry = cntlr_radio_opclass_find_entry(&radio->cur_opclass, id); + entry = opclass_find_entry(&radio->cur_opclass, id); if (!entry) - entry = cntlr_radio_opclass_new_entry(&radio->cur_opclass); + entry = opclass_new_entry(&radio->cur_opclass); if (!entry) return -1; entry->id = id; entry->bandwidth = get_op_class_bw(id); entry->max_txpower = txpower; - return cntlr_radio_opclass_add_channel(entry, channel, 15 << 4); + + chan.channel = channel; + chan.preference = 15 << 4; + + return opclass_add_channel(entry, &chan); } void cntlr_radio_cur_opclass_dump(struct netif_radio *radio) { - _cntlr_radio_opclass_dump(&radio->cur_opclass); + opclass_dump(&radio->cur_opclass); } static bool cntlr_radio_opclass_expired(struct netif_radio *radio) diff --git a/src/cntlr.h b/src/cntlr.h index 6807ecb4f7127684f9606b9cd3ead8f927016a41..8f4146d95a7d9b632b4137274e37671c3fd8ee4e 100644 --- a/src/cntlr.h +++ b/src/cntlr.h @@ -17,6 +17,7 @@ #include <timer_impl.h> #include <cmdu_ackq.h> #include <map_module.h> +#include "utils/opclass.h" extern const char *ubus_socket; @@ -251,36 +252,6 @@ struct netif_link { struct list_head list; }; -enum opclass_dfs { - OPCLASS_CHANNEL_DFS_NONE, - OPCLASS_CHANNEL_DFS_USABLE, - OPCLASS_CHANNEL_DFS_AVAILABLE, - OPCLASS_CHANNEL_DFS_NOP, - OPCLASS_CHANNEL_DFS_CAC, -}; - -struct opclass_entry { - uint8_t id; - int bandwidth; - int max_txpower; - - int channels_num; - struct { - uint8_t channel; - uint8_t preference; - - enum opclass_dfs dfs; - uint32_t cac_time; - uint32_t nop_time; - } channels[64]; -}; - -struct opclass { - struct opclass_entry entry[64]; - int entry_num; - time_t entry_time; -}; - /* TODO - fill this structure */ struct netif_radio { char name[16]; diff --git a/src/cntlr_acs.c b/src/cntlr_acs.c index 03edf335c397cf7361f31f5f54dd861ae3cb8499..8a7b8a55e55900f27aec2265cd85bb89ccf30a06 100644 --- a/src/cntlr_acs.c +++ b/src/cntlr_acs.c @@ -64,10 +64,10 @@ int cntlr_acs_radio_channel_recalc(struct netif_radio *radio, struct acs_params if (params->bw && params->bw != entry->bandwidth) continue; - for (j = 0; j < entry->channels_num; j++) { - chan = entry->channels[j].channel; - pref = (entry->channels[j].preference & CHANNEL_PREF_MASK) >> 4; - reas = entry->channels[j].preference & CHANNEL_PREF_REASON; + for (j = 0; j < entry->channel_num; j++) { + chan = entry->channel[j].channel; + pref = (entry->channel[j].preference & CHANNEL_PREF_MASK) >> 4; + reas = entry->channel[j].preference & CHANNEL_PREF_REASON; trace("\tacs check/cmp chan %d pref %d reas %d\n", chan, pref, reas); @@ -181,7 +181,7 @@ static int cntlr_get_current_acs_params(struct netif_radio *radio, struct acs_pa params->opclass = radio->cur_opclass.entry[0].id; params->bw = radio->cur_opclass.entry[0].bandwidth; - params->best_channel = radio->cur_opclass.entry[0].channels[0].channel; + params->best_channel = radio->cur_opclass.entry[0].channel[0].channel; params->best_bw = params->bw; params->best_opclass = params->opclass; @@ -245,12 +245,12 @@ static bool cntlr_dfs_get_usable(struct opclass_entry *entry, struct cac_data *c uint8_t reas; int i; - for (i = 0; i < entry->channels_num; i++) { - reas = entry->channels[i].preference & CHANNEL_PREF_REASON; + for (i = 0; i < entry->channel_num; i++) { + reas = entry->channel[i].preference & CHANNEL_PREF_REASON; /* Usable - we can run CAC */ if (reas == CHANNEL_PREF_REASON_DFS_USABLE) { - cac_data->channel = entry->channels[i].channel; + cac_data->channel = entry->channel[i].channel; cac_data->opclass = entry->id; return true; } @@ -296,7 +296,7 @@ static bool cntlr_dfs_get_cac_data(struct netif_radio *radio, struct cac_data *c continue; /* TODO check chan/bw - not only control channel */ - if (cac_data->channel == cur_opclass->entry[0].channels[0].channel) + if (cac_data->channel == cur_opclass->entry[0].channel[0].channel) continue; /* TODO define this in ieee1905 */ diff --git a/src/cntlr_map.c b/src/cntlr_map.c index f9b55a46ae2e193522134a13aac56380b47ee2ee..0f24e09c50ea25893c87952767354fb0d22905fb 100644 --- a/src/cntlr_map.c +++ b/src/cntlr_map.c @@ -75,18 +75,18 @@ static void _cntlr_update_steer_params(struct controller *c, struct opclass *op) for (i = 0; i < op->entry_num; i++) { oe = &op->entry[i]; - for (j = 0; j < oe->channels_num; j++) { + for (j = 0; j < oe->channel_num; j++) { sp = &c->steer_params; found = false; for (k = 0; k < sp->channels_num; k++) { - if(sp->channels[k] == oe->channels[j].channel) { + if(sp->channels[k] == oe->channel[j].channel) { found = true; break; } } if (!found) { - sp->channels[sp->channels_num] = oe->channels[j].channel; + sp->channels[sp->channels_num] = oe->channel[j].channel; sp->channels_num++; } } @@ -1284,8 +1284,8 @@ static uint8_t cntlr_get_opclass_ht20(struct netif_radio *nr, uint8_t channel) if (entry->bandwidth != 20) continue; - for (j = 0; j < entry->channels_num; j++) { - if (entry->channels[j].channel == channel) + for (j = 0; j < entry->channel_num; j++) { + if (entry->channel[j].channel == channel) return entry->id; } } diff --git a/src/cntlr_ubus.c b/src/cntlr_ubus.c index fdf87f01d50632b8da80c420634a1d72b6dc52e0..06fefc977edfb457e898802be2990a13b920d6cf 100644 --- a/src/cntlr_ubus.c +++ b/src/cntlr_ubus.c @@ -450,12 +450,12 @@ static void cntlr_status_add_opclass(struct blob_buf *bb, struct opclass *opclas if (strstr(name, "cur")) blobmsg_add_u32(bb, "txpower", opclass->entry[j].max_txpower); aa = blobmsg_open_array(bb, "channels"); - for (k = 0; k < opclass->entry[j].channels_num; k++) { + for (k = 0; k < opclass->entry[j].channel_num; k++) { tt = blobmsg_open_table(bb, ""); - blobmsg_add_u32(bb, "channel", opclass->entry[j].channels[k].channel); + blobmsg_add_u32(bb, "channel", opclass->entry[j].channel[k].channel); if (!strstr(name, "cur")) { - pref = (opclass->entry[j].channels[k].preference & CHANNEL_PREF_MASK) >> 4; - reas = opclass->entry[j].channels[k].preference & CHANNEL_PREF_REASON; + pref = (opclass->entry[j].channel[k].preference & CHANNEL_PREF_MASK) >> 4; + reas = opclass->entry[j].channel[k].preference & CHANNEL_PREF_REASON; blobmsg_add_u32(bb, "preference", pref); blobmsg_add_string(bb, "reason", cntrl_status_reason(reas)); } diff --git a/src/utils/opclass.c b/src/utils/opclass.c new file mode 100644 index 0000000000000000000000000000000000000000..eaf4018be9408bd6c90401fa721da0066b4b7192 --- /dev/null +++ b/src/utils/opclass.c @@ -0,0 +1,131 @@ +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#include <easy/easy.h> +#include <map2.h> +#include "utils.h" +#include "debug.h" +#include "opclass.h" + +struct opclass_entry *opclass_find_entry(struct opclass *opclass, uint8_t id) +{ + struct opclass_entry *entry; + int i; + + for (i = 0; i < opclass->entry_num; i++) { + entry = &opclass->entry[i]; + if (entry->id != id) + continue; + + return entry; + } + + return NULL; +} + +struct opclass_entry *opclass_new_entry(struct opclass *opclass) +{ + struct opclass_entry *entry; + + if (opclass->entry_num >= ARRAY_SIZE(opclass->entry)) + return NULL; + + entry = &opclass->entry[opclass->entry_num]; + opclass->entry_num++; + opclass->entry_time = time(NULL); + + return entry; +} + +struct opclass_channel *opclass_find_channel(struct opclass_entry *entry, uint8_t chan) +{ + struct opclass_channel *channel; + int i; + + for (i = 0; i < entry->channel_num; i++) { + channel = &entry->channel[i]; + if (channel->channel != chan) + continue; + + return channel; + } + + return NULL; +} + +struct opclass_channel *opclass_new_channel(struct opclass_entry *entry) +{ + struct opclass_channel *channel; + + if (entry->channel_num >= ARRAY_SIZE(entry->channel)) + return NULL; + + channel = &entry->channel[entry->channel_num]; + entry->channel_num++; + + return channel; +} + +int opclass_add_channel(struct opclass_entry *entry, struct opclass_channel *new) +{ + struct opclass_channel *channel; + + channel = opclass_find_channel(entry, new->channel); + if (!channel) + channel = opclass_new_channel(entry); + if (!channel) + return -1; + + memcpy(channel, new, sizeof(*channel)); + return 0; +} + +int opclass_add_entry(struct opclass *opclass, struct opclass_entry *new) +{ + struct opclass_entry *entry; + int ret = -1; + int i; + + entry = opclass_find_entry(opclass, new->id); + if (!entry) + entry = opclass_new_entry(opclass); + if (!entry) + return ret; + + entry->id = new->id; + entry->bandwidth = new->bandwidth; + entry->max_txpower = new->max_txpower; + + for (i = 0; i < new->channel_num; i++) + ret |= opclass_add_channel(entry, &new->channel[i]); + + return ret; +} + +void opclass_reset(struct opclass *opclass) +{ + opclass->entry_num = 0; + memset(opclass->entry, 0, sizeof(opclass->entry)); +} + +void opclass_dump(struct opclass *opclass) +{ + struct opclass_entry *entry; + int i, j; + + dbg(">>> opclass num: %d\n", opclass->entry_num); + for (i = 0; i < opclass->entry_num; i++) { + entry = &opclass->entry[i]; + dbg("opclass: %u\n", entry->id); + for (j = 0; j < entry->channel_num; j++) { + dbg("\tchan %u pref %u reason %u\n", + entry->channel[j].channel, + (entry->channel[j].preference & CHANNEL_PREF_MASK) >> 4, + entry->channel[j].preference & CHANNEL_PREF_REASON); + } + } + dbg("<<<\n"); +} + diff --git a/src/utils/opclass.h b/src/utils/opclass.h new file mode 100644 index 0000000000000000000000000000000000000000..88bb0c4360c0083dbbfe167fd1cea38a1f97bfe5 --- /dev/null +++ b/src/utils/opclass.h @@ -0,0 +1,49 @@ +#ifndef _OPCLASS_H_ +#define _OPCLASS_H_ + +enum opclass_dfs { + OPCLASS_CHANNEL_DFS_NONE, + OPCLASS_CHANNEL_DFS_USABLE, + OPCLASS_CHANNEL_DFS_AVAILABLE, + OPCLASS_CHANNEL_DFS_NOP, + OPCLASS_CHANNEL_DFS_CAC, +}; + +struct opclass_channel { + uint8_t channel; + uint8_t preference; + + enum opclass_dfs dfs; + uint32_t cac_time; + uint32_t nop_time; +}; + +struct opclass_entry { + uint8_t id; + int bandwidth; + int max_txpower; + + int channel_num; + struct opclass_channel channel[64]; +}; + +struct opclass { + time_t entry_time; + + int entry_num; + struct opclass_entry entry[64]; +}; + +struct opclass_entry *opclass_find_entry(struct opclass *opclass, uint8_t id); +struct opclass_entry *opclass_new_entry(struct opclass *opclass); + +struct opclass_channel *opclass_find_channel(struct opclass_entry *entry, uint8_t chan); +struct opclass_channel *opclass_new_channel(struct opclass_entry *entry); + +int opclass_add_channel(struct opclass_entry *entry, struct opclass_channel *new); +int opclass_add_entry(struct opclass *opclass, struct opclass_entry *new); + +void opclass_reset(struct opclass *opclass); +void opclass_dump(struct opclass *opclass); + +#endif /* _OPCLASS_H_ */