Skip to content
This repository was archived by the owner on Sep 7, 2020. It is now read-only.

Comments

PPM-249 - independent unit to deal with hostapd configuration#1514

Closed
RanRegev wants to merge 27 commits intomasterfrom
PPM-249
Closed

PPM-249 - independent unit to deal with hostapd configuration#1514
RanRegev wants to merge 27 commits intomasterfrom
PPM-249

Conversation

@RanRegev
Copy link
Collaborator

@RanRegev RanRegev commented Jul 8, 2020

Encapsulates hostapd configuration separately.
The separation enables:

@RanRegev RanRegev self-assigned this Jul 8, 2020
@RanRegev RanRegev requested a review from arnout July 8, 2020 08:53
Comment on lines 10 to 30
set(PRPLMESH_HOSTAPD_TYPE "DUMMY" CACHE STRING "PRPLMESH_HOSTAPD type")
set_property(CACHE PRPLMESH_HOSTAPD_TYPE PROPERTY STRINGS "DUMMY" "NL80211" "DWPAL")
add_definitions(-DBEEROCKS_TMP_PATH="${TMP_PATH}")

if (TARGET_PLATFORM STREQUAL "rdkb")

set(PRPLMESH_HOSTAPD_TYPE "DWPAL")
# Extra libraries
list(APPEND PRPLMESH_HOSTAPD_LIBS rt dl)

elseif(TARGET_PLATFORM STREQUAL "openwrt")

if (TARGET_PLATFORM_TYPE STREQUAL "ugw")
set(PRPLMESH_HOSTAPD_TYPE "DWPAL")
else()
set(PRPLMESH_HOSTAPD_TYPE "NL80211")
endif()

# hostapd directory
file(GLOB PRPLMESH_HOSTAPD_SEARCH_PATHS "${PLATFORM_BUILD_DIR}/hostapd*/hostapd-*")
find_path(PRPLMESH_HOSTAPD_INCLUDE_DIR NAMES "src/common/wpa_ctrl.h" PATHS ${PRPLMESH_HOSTAPD_SEARCH_PATHS} NO_CMAKE_FIND_ROOT_PATH)
set(PRPLMESH_HOSTAPD_DIR "${PRPLMESH_HOSTAPD_INCLUDE_DIR}")

endif()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None of this is needed. If it turns out to be needed, introduce it when you need it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed
Will be introduced when needed.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's still there.

@RanRegev RanRegev force-pushed the PPM-249 branch 2 times, most recently from cd2dc9f to 881285e Compare July 12, 2020 08:44
@RanRegev RanRegev marked this pull request as ready for review July 12, 2020 10:43
@RanRegev RanRegev added the don't merge This PR is not ready for merge or review label Jul 12, 2020
@RanRegev RanRegev marked this pull request as draft July 14, 2020 08:27
@RanRegev RanRegev changed the title PPM-249 PPM-249 - independent unit to deal with hostapd configuration Jul 15, 2020
@RanRegev RanRegev removed the don't merge This PR is not ready for merge or review label Jul 15, 2020
@RanRegev RanRegev marked this pull request as ready for review July 15, 2020 13:17
@RanRegev RanRegev requested a review from adam1985d as a code owner July 15, 2020 13:17
Copy link
Collaborator

@mariomaz mariomaz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unit tests should be improved.


while (getline(ifs, line)) {

// skip empty lines
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should you remove leading and trailing white spaces before checking for empty line?

//// start prerequsite ////

// save the content of the string (start clean)
// // clean_start();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove commented code

void clean_start()
{
// save the content of the string (start clean)
std::ofstream tmp(configuration_path + configuration_file_name);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you use the same file name for all the tests, then you cannot run them in multiple simultaneous threads. It's better to choose a different file name for each test.
To avoid file name conflicts in case more than one instance of the test application was executed in the same system at the same time, I used to use UUIDs for file names.
You should read the TMPDIR environment variable to get the name of the temporary directory instead of assuming it's "/tmp"

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be completely accurate, you should use mkstemp() - that guarantees a unique file.

However, even better would be if the file itself could be mocked away. I tried to convince @RanRegev of this but no success. So, I guess it should be merged as is and @mariomaz can have fun with creating something that uses mocks.

Note that all of Mario's other comments to this unit test would be resolved if the file were mocked away...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was convinced, and will eventually be aligned with this. I have two major issues that hold me from doing it now:

  1. Time frame. I need some ramp up to learn and work with these MOCKS.
  2. From the little I saw - I would need to have an interface for File just for the sake of the tests. From my point of view, if I write a File interface, it should be an interface that satisfies many kinds of files, including, among others, the mock files. This is entirely different mission than just creating a File interface that is good for my current needs and tests. In other words, thinking only on current needs and mocking will eventually resulted with something that is usable in these two use cases only. This is not an interface as I see it. Interface for me is something that I can use in many places, usually written for one or two existing use cases - but is truly opened for farther extending.

}

bool Configuration::set_create_vap_value(const std::string &vap, const std::string &key,
const int value)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const int value)
int value)


/**
* @brief get the value of the given key for the given vap
* @param
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a valid doxygen format for @params?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope.

}


TEST(configuration_test, diable_all_ap)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
TEST(configuration_test, diable_all_ap)
TEST(configuration_test, disable_all_ap_vaps)

conf.uncomment_vap("wlan0.1");
EXPECT_TRUE(conf) << conf;

conf.uncomment_vap("wlan0.2");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests are not actually testing, they are just running the code

if (line_iter == m_hostapd_config_head.end()) {
m_last_message = std::string(__FUNCTION__) +
" couldn't find requested key in head: " + key;
return "";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't you set m_ok = false before returning?
Also, if function succeeds, m_last_message should be cleared.
If m_last_message and m_ok are updated in parallel, you might infer m_ok from m_last_message

Copy link
Collaborator

@arnout arnout left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As usual, I have a lot of comments on this PR.

The commit splitting is a bit of a mess. But I guess I rushed you a bit :-) So OK.

One problem is that it adds a lot of unneeded features. Please don't do that. We don't need commenting out, we don't need changing the header part, we don't need disable of all vaps. So almost half of the commits are not even needed.

That said, nothing is critically wrong. The only critical thing is the ordering of the VAPs that isn't maintained. However, it will work in practice (at least for the time being) since openwrt generates the config file with sorted bss= sections. Well, actually, you can do funny things in uci wireless so that it generates it in a different order. Anyway, I think it can be merged as is (maybe with some cosmetic changes like fixing the errors in doxygen) but a bug has to be created for the ordering of VAPs.

Comment on lines 16 to 20
## Process
Manages hostapd process
* start
* stop
* restart
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't start or stop hostapd.

Comment on lines 20 to 23
/**
* @brief construct a Configurationn object
* @param file_name the name of the configuration file.
*/
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/**
* @brief construct a Configurationn object
* @param file_name the name of the configuration file.
*/
/**
* @brief Construct a Configuration object.
*
* @param file_name the name of the configuration file.
*/

~Configuration() = default;
Configuration(const Configuration &) = default;
Configuration(Configuration &&) = default;

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like an explicit

Suggested change
Configuration() = delete;

* }
*
*/
bool load();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, no RAII then?

bool m_ok = false;

// each string is a line in the original configuration file
// that belongs to the "head" part. read the explnation at
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// that belongs to the "head" part. read the explnation at
// that belongs to the "head" part. read the explanation at

Comment on lines 209 to 210
int dummy(0);
for_all_ap_vaps(f_with_iter, dummy, 10);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Err, so max 10 vaps supported?

Comment on lines 213 to 214
template <class func, class iter>
void Configuration::for_all_ap_vaps(func f, iter current_iter, const iter end)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would have turned it around, something like this:

Suggested change
template <class func, class iter>
void Configuration::for_all_ap_vaps(func f, iter current_iter, const iter end)
template <class func, class iter>
void Configuration::for_all_ap_vaps(func f, iter current_iter, const iter end)
{
for_all_ap_vaps([](const std::vector<std::string> &vap) {
if (current_iter != end) {
f(vap, current_iter);
current_iter++;
} else {
/* Call the second function here for the remaining vaps */
}
});

if (get_vap_value(vap.first, "mode") == "ap") {
f(vap.first);
if (end == current_iter) {
f(vap.first, end);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, actually this way indeed you can handle the remaining ones... But it's clunky because you need the condition inside, a separate function would be nicer.

Comment on lines 214 to 224
EXPECT_FALSE(conf) << conf;

// construct a configuration
ASSERT_FALSE(conf) << conf;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expect then assert of the same is weird.

return *this;
}

bool Configuration::set_create_head_value(const std::string &key, const std::string &value)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, we don't need this. We only modify VAPs.

Comment on lines 353 to 354
note: the string "bss=" may be replaced by the
user in the call to load() with another vap-indicator (e.g. "interface=")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is wrong. The actual format of the file is:

... Configuration of first VAP
bss=...
... Configuration of second VAP
bss=...
... Configuration of third VAP

interface= sets the name of the VAP. bss= also sets it, so it really is only needed for the first VAP.

As it happens, openwrt generates the configuration file as:

... Global options
interface=first_vap_name
... First VAP options
bss=second_vap_name
... Second VAP options

But that's just "coincidence", not really something we can rely on...

@RanRegev RanRegev force-pushed the PPM-249 branch 3 times, most recently from a327cef to 7190162 Compare July 30, 2020 12:09
A file explaining the content of this directory
https://jira.prplfoundation.org/browse/PPM-249

Signed-off-by: Ran Regev <ran.regev@devalore.com>
added hostapd Configuration class to
be used by applications that wants to
edit, add, delete, enable, disable, etc
parametrs in hostapd configuration file
https://jira.prplfoundation.org/browse/PPM-249

Signed-off-by: Ran Regev <ran.regev@devalore.com>
unit tests to test hostapd
configuration functionality
https://jira.prplfoundation.org/browse/PPM-249

Signed-off-by: Ran Regev <ran.regev@devalore.com>
created CMakeLists.txt to build prplmest_hostapd library
and its unit tests
https://jira.prplfoundation.org/browse/PPM-249

Signed-off-by: Ran Regev <ran.regev@devalore.com>
introducing: set_create_vap_value
functionality and unit test
also: few minor general issues:
* a variable for the test file
* interface to get the last message (not implemented yet)
* change the variable name from error to message and fix
accordingly in the code
https://jira.prplfoundation.org/browse/PPM-249

Signed-off-by: Ran Regev <ran.regev@devalore.com>
introducing: set_create_vap_value, int overload
implemented the function using the string version
added functionality and tests
https://jira.prplfoundation.org/browse/PPM-249

Signed-off-by: Ran Regev <ran.regev@devalore.com>
introducing: store
stores internal configuration into the same
file it was loaded from, effectively changing the
configuration.
added functionality and tests
also:
* chnaged prerequisite in tests from
EXPECT to ASSERT - as we can't continue without it
https://jira.prplfoundation.org/browse/PPM-249

Signed-off-by: Ran Regev <ran.regev@devalore.com>
introducing: get_vap_value
added the ability to get a value
for a specific vap with a given key.
added functionality and tests
https://jira.prplfoundation.org/browse/PPM-249

Signed-off-by: Ran Regev <ran.regev@devalore.com>
added functionality to disable all vaps that
are access-points (as opposed to STA for example).
the code mimics the existing functionality taken from
ap_wlan_hal_dwpal.cpp.
added funcvtionlity and unit test
note:
the example unit-test configuration file did not
contain any vap with the mode= line, therefore it
was added few of this.
also:
it was discovered that it is OK to look for non-exiting key
within vap's configuration and the code was changed accordingly
https://jira.prplfoundation.org/browse/PPM-249

Signed-off-by: Ran Regev <ran.regev@devalore.com>
added private helper functions for functions
changed all usages accordingly
https://jira.prplfoundation.org/browse/PPM-249

Signed-off-by: Ran Regev <ran.regev@devalore.com>
comment out (disable) the given vap
by adding a comment (#) to it and to
all keys related to this vap
added functionality and unit test
also:
clang format chages
https://jira.prplfoundation.org/browse/PPM-249

Signed-off-by: Ran Regev <ran.regev@devalore.com>
load, search and store comented lines in the
file. this ability is needed for disabling
vaps in the "up stream" version of hostapd.
the intel version disables vaps by adding the line
"start_disabled=1"
https://jira.prplfoundation.org/browse/PPM-249

Signed-off-by: Ran Regev <ran.regev@devalore.com>
uncomment (enable) the given vap
by removing all comment signes (###) from it
and from all keys related to this vap
added functionality and unit test
https://jira.prplfoundation.org/browse/PPM-249

Signed-off-by: Ran Regev <ran.regev@devalore.com>
introducing: a function that goes all over all
vaps which their mode is "ap" and apply the
input function to them.
may be used for example to disable all
vaps.
added functionality and tested by:
- adding a parameter "start_disabled=1" to all.
- commenting out
https://jira.prplfoundation.org/browse/PPM-249

Signed-off-by: Ran Regev <ran.regev@devalore.com>
There is a need to go on both the ap-vaps configured in hostapd
and in paralell go over the given configuration (non-hostapd structure)
The added functionality gives hostapd configuration class the
responsibility of iterating over the vaps _and_ increment the
user-iterator. the result is that the user's function is called
with the next vap _and_ the next element in its given list.
it is the user responsibility however to make sure that its container
has at least as the number of vaps. otherwise for_all_ap_vaps() would
increment the iterator passed the end of the user's container
tested by implementing the non iterator version of for_all_ap_vaps()
in term of the iterator version, with a dummy iterator
https://jira.prplfoundation.org/browse/PPM-249

Signed-off-by: Ran Regev <ran.regev@devalore.com>
a test that goes all over all
vaps and enables them
https://jira.prplfoundation.org/browse/PPM-249

Signed-off-by: Ran Regev <ran.regev@devalore.com>
testing the ability to iterate over the user
container and the hostapd's ap-vaps in paralel
giving the user the ability to set parametrs
based on its own container and the hostapd container
https://jira.prplfoundation.org/browse/PPM-249

Signed-off-by: Ran Regev <ran.regev@devalore.com>
rebase --autosquash -i origin/master
introduced issues that I couldn't figure out
how to fix with rebasing again.
gave up and added this fix commit.
https://jira.prplfoundation.org/browse/PPM-249

Signed-off-by: Ran Regev <ran.regev@devalore.com>
added a functionality to set or create key/value
in the header part: either string or int
added functionality and tests
https://jira.prplfoundation.org/browse/PPM-249

Signed-off-by: Ran Regev <ran.regev@devalore.com>
added a function to get a value from the head section
added functionality and unit test
also in this commit:
the variable named it_str is now called line_iter
(it is better describs its meaning)
https://jira.prplfoundation.org/browse/PPM-249

Signed-off-by: Ran Regev <ran.regev@devalore.com>
originally bss= was the only sign for
vap configuration inside the hostapd file.
this was based on intel's hostapd version.
the hostapd upstream indicates vap configuration
with interface= sign.
load() now seeks for the vap sign as set
by the user.
also in this commit:
- removed namespace config from prplmesh::hostapd.
left with only the two and class Configuration.
- clang format fixes
https://jira.prplfoundation.org/browse/PPM-249

Signed-off-by: Ran Regev <ran.regev@devalore.com>
there is a need to let the usr the ability to decide
if a given vap is an ap vap or not.
e.g.
for intel the predicate is: mode=ap
for ap stream hostapd: all vaps are ap vaps
https://jira.prplfoundation.org/browse/PPM-249

Signed-off-by: Ran Regev <ran.regev@devalore.com>
this commnit fixes all relevant comments for
#1550
https://jira.prplfoundation.org/browse/PPM-249

Signed-off-by: Ran Regev <ran.regev@devalore.com>
there is a need to let the usr the ability to decide
if a given vap is an ap vap or not.
e.g.
for intel the predicate is: mode=ap
for up stream's hostapd: all vaps are ap vaps

Signed-off-by: Ran Regev <ran.regev@devalore.com>
added prplmesh_hostapd dependency to bwl and btl
in cmake

Signed-off-by: Ran Regev <ran.regev@devalore.com>
added hostapd configuration to
update_vap_credentials()
the implementation was copied and then adopted
from dwpal implementation
(common/beerocks/bwl/dwpal/ap_wlan_hal_dwpal.cpp)
tested on Turris Omnia

Signed-off-by: Ran Regev <ran.regev@devalore.com>
this commit closes issues found in
#1550
https://jira.prplfoundation.org/browse/PPM-4
MAP-4.2.1:turris-omnia

Signed-off-by: Ran Regev <ran.regev@devalore.com>
@RanRegev RanRegev mentioned this pull request Aug 13, 2020
@RanRegev RanRegev closed this Aug 13, 2020
@RanRegev
Copy link
Collaborator Author

Replaced by #1601

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants