2009-01-26 20:51:20

by Florian Sesser

[permalink] [raw]
Subject: [RFC][RFT] mac80211 / mesh: Modularize Path Selection Protocol

Hi all!

As I mentioned some time ago on linux-wireless [1], I am trying to
extend o11s so I can include Scalable Source Routing. Towards that goal,
I first need a method to be able to exchange the used mesh path
selection protocol.

In this patch series, you can see my first approach to an API that
enables users to exchange the path selection protocol at runtime.

What I have done so far is mostly borrowing source code from
block/elevator.c for most of the registration, finding and inserting
glue code. Also, I have wrapped mesh_hwmp into an own module and written
a test module (pptest) so the module switching can be tried out. To that
end, I also have patched iw.

For completeness, I will post the patch to iw in reply to this eMail on
this list, as it is quite simple, short and affects only two files
(compared to 14 or so for the API in the kernel).

This is my first patch not only to the kernel, but to any open source
project, so please be gentle ;) I am open to suggestions for
improvement; please also remind me on any coding style or other errors
you may find.

I would be very glad if some of the experts here could review it and
give me advice on:

* If my selection of functions for the abstraction ops-struct is
somewhat sane or if I am missing critical parts (this is most important
to me)

* Which is the best location for the path selection protocol ID
(cfg80211 and iw suggest having the value in struct mesh_params. o11s
currently stores it in ieee80211_if_mesh->mesh_pp_id, which is in use at
least by mesh_matches_local. And finally it obviously needs to be stored
in the path selection protocol modules.)

Greetings from Munich!

Florian


[1] http://marc.info/?l=linux-wireless&m=122600107811517&w=2



2009-01-26 20:39:20

by Florian Sesser

[permalink] [raw]
Subject: [PATCH 6/6] mac80211: Path Selection Protocol dummy module

Can be inserted and 'used' for Path Selection
by insmodding and issuing:
iw dev <mesh-dev> set mesh_param mesh_path_selection_protocol_id 000F0F0F

Signed-off-by: Florian Sesser <[email protected]>
---
net/mac80211/Makefile | 2 +
net/mac80211/mesh_pptest.c | 71 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 73 insertions(+), 0 deletions(-)
create mode 100644 net/mac80211/mesh_pptest.c

diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile
index 796e7a6..add8ffc 100644
--- a/net/mac80211/Makefile
+++ b/net/mac80211/Makefile
@@ -42,6 +42,8 @@ ifdef CONFIG_MAC80211_MESH
obj-m += mesh_hwmp.o
endif

+obj-m += mesh_pptest.o
+
mac80211-$(CONFIG_PM) += pm.o

# objects for PID algorithm
diff --git a/net/mac80211/mesh_pptest.c b/net/mac80211/mesh_pptest.c
new file mode 100644
index 0000000..9841d2d
--- /dev/null
+++ b/net/mac80211/mesh_pptest.c
@@ -0,0 +1,71 @@
+#include <linux/init.h>
+#include <linux/module.h>
+#include "mesh.h"
+MODULE_LICENSE("GPL");
+
+static struct mesh_path_sel_algo pptest;
+
+static void pptest_path_start_discovery_fn (struct ieee80211_sub_if_data *sdata) {
+ printk(KERN_INFO "pptest: %s has been called.\n", __func__);
+}
+static int pptest_nexthop_lookup_fn (struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) {
+ printk(KERN_INFO "pptest: %s has been called.\n", __func__);
+ return 0;
+}
+static void pptest_queue_preq_fn (struct mesh_path *mpath, u8 flags) {
+ printk(KERN_INFO "pptest: %s has been called.\n", __func__);
+}
+static int pptest_path_error_tx_fn (u8 *dst, __le32 dst_dsn, u8 *ra,
+ struct ieee80211_sub_if_data *sdata) {
+ printk(KERN_INFO "pptest: %s has been called.\n", __func__);
+ return 0;
+}
+static void pptest_path_timer_fn (unsigned long data) {
+ printk(KERN_INFO "pptest: %s has been called.\n", __func__);
+}
+static void pptest_rx_path_sel_frame_fn (struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgmt *mgmt, size_t len) {
+ printk(KERN_INFO "pptest: %s has been called.\n", __func__);
+}
+static void pptest_path_sel_start_fn (struct ieee80211_if_mesh *sta) {
+ printk(KERN_INFO "pptest: %s has been called.\n", __func__);
+}
+static void pptest_path_sel_stop_fn (struct ieee80211_if_mesh *sta) {
+ printk(KERN_INFO "pptest: %s has been called.\n", __func__);
+}
+
+static struct mesh_path_sel_ops pptest_ops = {
+ .path_start_discovery_fn = &pptest_path_start_discovery_fn,
+ .nexthop_lookup_fn = &pptest_nexthop_lookup_fn,
+ .queue_preq_fn = &pptest_queue_preq_fn,
+ .path_error_tx_fn = &pptest_path_error_tx_fn,
+ .path_timer_fn = &pptest_path_timer_fn,
+ .rx_path_sel_frame_fn = &pptest_rx_path_sel_frame_fn,
+ .path_sel_start_fn = &pptest_path_sel_start_fn,
+ .path_sel_stop_fn = &pptest_path_sel_stop_fn,
+};
+
+static struct mesh_path_sel_algo pptest = {
+ .name = "mesh_pptest",
+ .id = 0x000F0F0F,
+ .ops = &pptest_ops,
+ .owner = THIS_MODULE,
+};
+
+static int __init init_mesh_pptest(void)
+{
+ /* init code here */
+ printk(KERN_ALERT "Hello, this is mesh_pptest speaking (__init)\n");
+ mesh_path_sel_algo_register(&pptest);
+ return 0;
+}
+
+static void __exit cleanup_mesh_pptest(void)
+{
+ /* cleanup code here */
+ printk(KERN_ALERT "Goodbye, this is mesh_pptest dying\n");
+ mesh_path_sel_algo_unregister(&pptest);
+}
+
+module_init(init_mesh_pptest);
+module_exit(cleanup_mesh_pptest);
--
1.5.6.5


2009-01-26 20:39:18

by Florian Sesser

[permalink] [raw]
Subject: [PATCH 1/6] mac80211: Virtualize mesh path selection ops

Struct mesh_path_sel_ops, central to the abstraction
of the Path Selection Protocol.

Signed-off-by: Florian Sesser <[email protected]>
---
net/mac80211/mesh.h | 78 +++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 75 insertions(+), 3 deletions(-)

diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index 9e064ee..a4141d8 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -169,6 +169,72 @@ struct mesh_rmc {
*/
#define MESH_PREQ_MIN_INT 10
#define MESH_DIAM_TRAVERSAL_TIME 50
+
+/* Default Path Selection, Path Metric, Congestion Control Mode */
+#define MESH_PATH_SELECTION_PROTOCOL_ID 0x000FACFF
+#define MESH_PATH_SELECTION_METRIC_ID 0x000FACFF
+#define MESH_CONGESTION_CONTROL_MODE_ID 0x000FACFF
+
+/* From mesh_hwmp.c: */
+enum mpath_frame_type {
+ MPATH_PREQ = 0,
+ MPATH_PREP,
+ MPATH_PERR
+};
+/* Function pointer typedefs for struct mesh_path_sel_ops */
+typedef void (mesh_path_start_discovery_fn) (struct ieee80211_sub_if_data *sdata);
+typedef int (mesh_nexthop_lookup_fn) (struct sk_buff *skb, struct ieee80211_sub_if_data *sdata);
+typedef void (mesh_queue_preq_fn) (struct mesh_path *mpath, u8 flags);
+typedef int (mesh_path_sel_frame_tx_fn) (enum mpath_frame_type action, u8 flags,
+ u8 *orig_addr, __le32 orig_dsn, u8 dst_flags, u8 *dst, __le32 dst_dsn, u8 *da,
+ u8 hop_count, u8 ttl, __le32 lifetime, __le32 metric, __le32 preq_id,
+ struct ieee80211_sub_if_data *sdata);
+typedef int (mesh_path_error_tx_fn) (u8 *dst, __le32 dst_dsn, u8 *ra,
+ struct ieee80211_sub_if_data *sdata);
+typedef void (mesh_path_timer_fn) (unsigned long data);
+typedef u32 (mesh_route_info_get_fn) (struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgmt *mgmt, u8 *ie);
+typedef void (mesh_rx_path_sel_frame_fn) (struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgmt *mgmt, size_t len);
+typedef void (mesh_preq_frame_process_fn) (struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgmt *mgmt, u8 *preq_elem, u32 metric);
+typedef void (mesh_prep_frame_process_fn) (struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgmt *mgmt, u8 *prep_elem, u32 metric);
+typedef void (mesh_perr_frame_process_fn) (struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgmt *mgmt, u8 *perr_elem);
+typedef void (mesh_path_sel_start_fn) (struct ieee80211_if_mesh *sta);
+typedef void (mesh_path_sel_stop_fn) (struct ieee80211_if_mesh *sta);
+struct mesh_path_sel_ops {
+ mesh_path_start_discovery_fn *path_start_discovery_fn;
+ mesh_nexthop_lookup_fn *nexthop_lookup_fn;
+ /* Needed by mesh_path_timer from mesh_pathtbl.c */
+ mesh_queue_preq_fn *queue_preq_fn;
+ /* To my surprise this seems to not be needed:
+ mesh_path_sel_frame_tx_fn *path_sel_frame_tx_fn; */
+ mesh_path_error_tx_fn *path_error_tx_fn;
+ /* Doesn't this timer belong into mesh.c? */
+ mesh_path_timer_fn *path_timer_fn;
+ mesh_rx_path_sel_frame_fn *rx_path_sel_frame_fn;
+ /* Belongs into the mesh routing protocol module
+ mesh_preq_frame_process_fn *preq_frame_process_fn;
+ mesh_prep_frame_process_fn *prep_frame_process_fn;
+ mesh_perr_frame_process_fn *perr_frame_process_fn; */
+ mesh_path_sel_start_fn *path_sel_start_fn;
+ mesh_path_sel_stop_fn *path_sel_stop_fn;
+};
+
+#define MESH_ALGO_NAME_MAX (16)
+struct mesh_path_sel_algo {
+ struct list_head list;
+ char name[MESH_ALGO_NAME_MAX];
+ u32 id;
+ struct mesh_path_sel_ops* ops;
+ struct module* owner;
+};
+
+void mesh_path_sel_algo_register (struct mesh_path_sel_algo *algo);
+void mesh_path_sel_algo_unregister (struct mesh_path_sel_algo *algo);
+
/* Paths will be refreshed if they are closer than PATH_REFRESH_TIME to their
* expiration
*/
@@ -205,6 +271,9 @@ int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr,
bool mesh_matches_local(struct ieee802_11_elems *ie,
struct ieee80211_sub_if_data *sdata);
void mesh_ids_set_default(struct ieee80211_if_mesh *mesh);
+void mesh_ids_set_pp(struct ieee80211_if_mesh *sta, u32 pp);
+void mesh_ids_set_pm(struct ieee80211_if_mesh *sta, u32 pm);
+void mesh_ids_set_cc(struct ieee80211_if_mesh *sta, u32 cc);
void mesh_mgmt_ies_add(struct sk_buff *skb,
struct ieee80211_sub_if_data *sdata);
void mesh_rmc_free(struct ieee80211_sub_if_data *sdata);
@@ -219,9 +288,9 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata);
void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata);

/* Mesh paths */
-int mesh_nexthop_lookup(struct sk_buff *skb,
- struct ieee80211_sub_if_data *sdata);
-void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata);
+struct mesh_path_sel_algo* mesh_path_sel_algo_find_by_name (const char* name);
+struct mesh_path_sel_algo* mesh_path_sel_algo_find_by_id (u32 id);
+void mesh_path_sel_algo_set (struct ieee80211_if_mesh *sta, struct mesh_path_sel_algo* algo);
struct mesh_path *mesh_path_lookup(u8 *dst,
struct ieee80211_sub_if_data *sdata);
struct mesh_path *mpp_path_lookup(u8 *dst,
@@ -293,6 +362,9 @@ static inline void mesh_path_activate(struct mesh_path *mpath)
for (i = 0; i <= x->hash_mask; i++) \
hlist_for_each_entry_rcu(node, p, &x->hash_buckets[i], list)

+/* Moved here from mesh_hwmp.c */
+#define max_preq_retries(s) (s->u.mesh.mshcfg.dot11MeshHWMPmaxPREQretries)
+
void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local);

#else
--
1.5.6.5


2009-01-27 11:19:08

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 4/6] mac80211: More small changes for modularization

Hi,

> Thanks for your comment. My intention was having a logical seperation to
> enable better discussion of my patch, which I think is pretty much of a
> monster and not yet ready for inclusion?

I've seen larger patches ;) But ok.

> What do you think about my selection of mesh_path_sel_ops and the
> storing of mesh PP/PM/CC id?
>
> If you deem it OK I would be happy to reformat the patch (into three or
> so seperatly compiling patches) and include KConfigs.

Well, you really need to run checkpatch and address (most of) its
complaints. Then you can repost and I'll take a look again.

johannes


Attachments:
signature.asc (836.00 B)
This is a digitally signed message part

2009-01-26 20:39:19

by Florian Sesser

[permalink] [raw]
Subject: [PATCH 5/6] mac80211: o11s PP api communication with userspace

Interface nl80211 and iw to enable iw changing
path selection protocols by doing something like
iw dev <mesh-dev> set mesh_param mesh_path_selection_protocol_id <id>

Signed-off-by: Florian Sesser <[email protected]>
---
include/linux/nl80211.h | 10 ++++++++++
net/mac80211/cfg.c | 8 ++++++++
net/wireless/nl80211.c | 18 ++++++++++++++++++
3 files changed, 36 insertions(+), 0 deletions(-)

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 76aae3d..f8ec895 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -772,6 +772,13 @@ enum nl80211_mntr_flags {
* @NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME: The interval of time (in TUs)
* that it takes for an HWMP information element to propagate across the mesh
*
+ * @NL80211_MESHCONF_PATH_SELECTION_PROTOCOL_ID: Path Selection Protocol
+ * ID, consisting of an OUI + arbitrary 8 bit
+ *
+ * @NL80211_MESHCONF_PATH_SELECTION_METRIC_ID: Path Selection Metric ID
+ *
+ * @NL80211_MESHCONF_CONGESTION_CONTROL_MODE_ID: Congestion Control Mode ID
+ *
* @NL80211_MESHCONF_ATTR_MAX: highest possible mesh configuration attribute
*
* @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use
@@ -791,6 +798,9 @@ enum nl80211_meshconf_params {
NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
+ NL80211_MESHCONF_PATH_SELECTION_PROTOCOL_ID,
+ NL80211_MESHCONF_PATH_SELECTION_METRIC_ID,
+ NL80211_MESHCONF_CONGESTION_CONTROL_MODE_ID,

/* keep last */
__NL80211_MESHCONF_ATTR_AFTER_LAST,
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index a1a1344..5d72be9 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1085,6 +1085,14 @@ static int ieee80211_set_mesh_params(struct wiphy *wiphy,
mask))
conf->dot11MeshHWMPnetDiameterTraversalTime =
nconf->dot11MeshHWMPnetDiameterTraversalTime;
+ if (_chg_mesh_attr(NL80211_MESHCONF_PATH_SELECTION_PROTOCOL_ID, mask))
+ mesh_ids_set_pp(&sdata->u.mesh, nconf->mesh_path_selection_protocol_id);
+ if (_chg_mesh_attr(NL80211_MESHCONF_PATH_SELECTION_METRIC_ID, mask))
+ conf->mesh_path_selection_metric_id =
+ nconf->mesh_path_selection_metric_id;
+ if (_chg_mesh_attr(NL80211_MESHCONF_CONGESTION_CONTROL_MODE_ID, mask))
+ conf->mesh_congestion_control_mode_id =
+ nconf->mesh_congestion_control_mode_id;
return 0;
}

diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 09a5d0f..4736077 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1974,6 +1974,12 @@ static int nl80211_get_mesh_params(struct sk_buff *skb,
cur_params.dot11MeshHWMPpreqMinInterval);
NLA_PUT_U16(msg, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
cur_params.dot11MeshHWMPnetDiameterTraversalTime);
+ NLA_PUT_U32(msg, NL80211_MESHCONF_PATH_SELECTION_PROTOCOL_ID,
+ cur_params.mesh_path_selection_protocol_id);
+ NLA_PUT_U32(msg, NL80211_MESHCONF_PATH_SELECTION_METRIC_ID,
+ cur_params.mesh_path_selection_metric_id);
+ NLA_PUT_U32(msg, NL80211_MESHCONF_CONGESTION_CONTROL_MODE_ID,
+ cur_params.mesh_congestion_control_mode_id);
nla_nest_end(msg, pinfoattr);
genlmsg_end(msg, hdr);
err = genlmsg_unicast(msg, info->snd_pid);
@@ -2013,6 +2019,9 @@ nl80211_meshconf_params_policy[NL80211_MESHCONF_ATTR_MAX+1] __read_mostly = {
[NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT] = { .type = NLA_U32 },
[NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL] = { .type = NLA_U16 },
[NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] = { .type = NLA_U16 },
+ [NL80211_MESHCONF_PATH_SELECTION_PROTOCOL_ID] = { .type = NLA_U32 },
+ [NL80211_MESHCONF_PATH_SELECTION_METRIC_ID] = { .type = NLA_U32 },
+ [NL80211_MESHCONF_CONGESTION_CONTROL_MODE_ID] = { .type = NLA_U32 },
};

static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info)
@@ -2074,6 +2083,15 @@ static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info)
dot11MeshHWMPnetDiameterTraversalTime,
mask, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
nla_get_u16);
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, mesh_path_selection_protocol_id,
+ mask, NL80211_MESHCONF_PATH_SELECTION_PROTOCOL_ID,
+ nla_get_u32);
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, mesh_path_selection_metric_id,
+ mask, NL80211_MESHCONF_PATH_SELECTION_METRIC_ID,
+ nla_get_u32);
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, mesh_congestion_control_mode_id,
+ mask, NL80211_MESHCONF_CONGESTION_CONTROL_MODE_ID,
+ nla_get_u32);

/* Apply changes */
rtnl_lock();
--
1.5.6.5


2009-01-26 20:39:18

by Florian Sesser

[permalink] [raw]
Subject: [PATCH 3/6] mac80211: Modularized mesh_hwmp.c

Separate mesh_hwmp.c into own module, which is
loaded automatically as the default path selection
protocol.

Signed-off-by: Florian Sesser <[email protected]>
---
net/mac80211/mesh_hwmp.c | 81 +++++++++++++++++++++++++------------------
net/mac80211/mesh_pathtbl.c | 45 ++++++++++++++++++++++--
net/mac80211/tx.c | 4 ++-
3 files changed, 91 insertions(+), 39 deletions(-)

diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index 4f862b2..25c2159 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -7,12 +7,17 @@
* published by the Free Software Foundation.
*/

+#include <linux/module.h>
+#include <net/mac80211.h>
+#include "ieee80211_i.h"
#include "mesh.h"

#define TEST_FRAME_LEN 8192
#define MAX_METRIC 0xffffffff
#define ARITH_SHIFT 8

+static struct mesh_path_sel_algo mesh_path_sel_hwmp;
+
/* Number of frames buffered per destination for unresolved destinations */
#define MESH_FRAME_QUEUE_LEN 10
#define MAX_PREQ_QUEUE_LEN 64
@@ -69,16 +74,9 @@ static inline u32 u32_field_get(u8 *preq_elem, int offset, bool ae)
MSEC_TO_TU(s->u.mesh.mshcfg.dot11MeshHWMPactivePathTimeout)
#define min_preq_int_jiff(s) \
(msecs_to_jiffies(s->u.mesh.mshcfg.dot11MeshHWMPpreqMinInterval))
-#define max_preq_retries(s) (s->u.mesh.mshcfg.dot11MeshHWMPmaxPREQretries)
#define disc_timeout_jiff(s) \
msecs_to_jiffies(sdata->u.mesh.mshcfg.min_discovery_timeout)

-enum mpath_frame_type {
- MPATH_PREQ = 0,
- MPATH_PREP,
- MPATH_PERR
-};
-
static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
u8 *orig_addr, __le32 orig_dsn, u8 dst_flags, u8 *dst,
__le32 dst_dsn, u8 *da, u8 hop_count, u8 ttl, __le32 lifetime,
@@ -679,7 +677,7 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
*
* @sdata: local mesh subif
*/
-void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata)
+static void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
struct mesh_preq_queue *preq_node;
@@ -769,7 +767,7 @@ enddiscovery:
* sent when the path is resolved. This means the caller must not free the skb
* in this case.
*/
-int mesh_nexthop_lookup(struct sk_buff *skb,
+static int mesh_nexthop_lookup(struct sk_buff *skb,
struct ieee80211_sub_if_data *sdata)
{
struct sk_buff *skb_to_free = NULL;
@@ -827,32 +825,47 @@ endlookup:
return err;
}

-void mesh_path_timer(unsigned long data)
+static void hwmp_start (struct ieee80211_if_mesh *sta) {
+ /* init variables etc */
+}
+
+static void hwmp_stop (struct ieee80211_if_mesh *sta) {
+ /* finish, clean up */
+}
+
+static struct mesh_path_sel_ops mesh_path_sel_hwmp_ops = {
+ .path_start_discovery_fn = &mesh_path_start_discovery,
+ .nexthop_lookup_fn = &mesh_nexthop_lookup,
+ .path_error_tx_fn = &mesh_path_error_tx,
+ .path_timer_fn = &mesh_path_timer,
+ .queue_preq_fn = &mesh_queue_preq,
+ .rx_path_sel_frame_fn = &mesh_rx_path_sel_frame,
+ .path_sel_start_fn = &hwmp_start,
+ .path_sel_stop_fn = &hwmp_stop,
+};
+
+static struct mesh_path_sel_algo mesh_path_sel_hwmp = {
+ .name = "mesh_hwmp",
+ .id = 0x000FACFF,
+ .ops = &mesh_path_sel_hwmp_ops,
+ .owner = THIS_MODULE,
+};
+
+static int __init init_mesh_hwmp(void)
{
- struct ieee80211_sub_if_data *sdata;
- struct mesh_path *mpath;
+ /* init code here */
+ mesh_path_sel_algo_register(&mesh_path_sel_hwmp);

- rcu_read_lock();
- mpath = (struct mesh_path *) data;
- mpath = rcu_dereference(mpath);
- if (!mpath)
- goto endmpathtimer;
- spin_lock_bh(&mpath->state_lock);
- sdata = mpath->sdata;
- if (mpath->flags & MESH_PATH_RESOLVED ||
- (!(mpath->flags & MESH_PATH_RESOLVING)))
- mpath->flags &= ~(MESH_PATH_RESOLVING | MESH_PATH_RESOLVED);
- else if (mpath->discovery_retries < max_preq_retries(sdata)) {
- ++mpath->discovery_retries;
- mpath->discovery_timeout *= 2;
- mesh_queue_preq(mpath, 0);
- } else {
- mpath->flags = 0;
- mpath->exp_time = jiffies;
- mesh_path_flush_pending(mpath);
- }
+ return 0;
+}

- spin_unlock_bh(&mpath->state_lock);
-endmpathtimer:
- rcu_read_unlock();
+static void __exit cleanup_mesh_hwmp(void)
+{
+ /* cleanup code here */
+ mesh_path_sel_algo_unregister(&mesh_path_sel_hwmp);
}
+
+MODULE_LICENSE("GPL");
+module_init(init_mesh_hwmp);
+module_exit(cleanup_mesh_hwmp);
+
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index 3c72557..c1f01fe 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -26,7 +26,7 @@
time_after(jiffies, mpath->exp_time) && \
!(mpath->flags & MESH_PATH_FIXED))

-struct mpath_node {
+ struct mpath_node {
struct hlist_node list;
struct rcu_head rcu;
/* This indirection allows two different tables to point to the same
@@ -57,6 +57,7 @@ void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta)
{
rcu_assign_pointer(mpath->next_hop, sta);
}
+EXPORT_SYMBOL(mesh_path_assign_nexthop);


/**
@@ -94,6 +95,7 @@ struct mesh_path *mesh_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata)
}
return NULL;
}
+EXPORT_SYMBOL(mesh_path_lookup);

struct mesh_path *mpp_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata)
{
@@ -253,7 +255,7 @@ err_path_alloc:
atomic_dec(&sdata->u.mesh.mpaths);
return err;
}
-
+EXPORT_SYMBOL(mesh_path_add);

int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
{
@@ -366,7 +368,7 @@ void mesh_plink_broken(struct sta_info *sta)
mpath->flags &= ~MESH_PATH_ACTIVE;
++mpath->dsn;
spin_unlock_bh(&mpath->state_lock);
- mesh_path_error_tx(mpath->dst,
+ sdata->u.mesh.mesh_pp->ops->path_error_tx_fn(mpath->dst,
cpu_to_le32(mpath->dsn),
sdata->dev->broadcast, sdata);
} else
@@ -484,6 +486,7 @@ void mesh_path_tx_pending(struct mesh_path *mpath)
(mpath->flags & MESH_PATH_ACTIVE))
dev_queue_xmit(skb);
}
+EXPORT_SYMBOL(mesh_path_tx_pending);

/**
* mesh_path_discard_frame - discard a frame whose path could not be resolved
@@ -511,12 +514,13 @@ void mesh_path_discard_frame(struct sk_buff *skb,
mpath = mesh_path_lookup(da, sdata);
if (mpath)
dsn = ++mpath->dsn;
- mesh_path_error_tx(skb->data, cpu_to_le32(dsn), ra, sdata);
+ sdata->u.mesh.mesh_pp->ops->path_error_tx_fn(skb->data, cpu_to_le32(dsn), ra, sdata);
}

kfree_skb(skb);
sdata->u.mesh.mshstats.dropped_frames_no_route++;
}
+EXPORT_SYMBOL(mesh_path_discard_frame);

/**
* mesh_path_flush_pending - free the pending queue of a mesh path
@@ -637,3 +641,36 @@ void mesh_pathtbl_unregister(void)
mesh_table_free(mesh_paths, true);
mesh_table_free(mpp_paths, true);
}
+
+/* Moved here from mesh_hwmp.c: */
+void mesh_path_timer(unsigned long data)
+{
+ struct ieee80211_sub_if_data *sdata;
+ struct mesh_path *mpath;
+
+ rcu_read_lock();
+ mpath = (struct mesh_path *) data;
+ mpath = rcu_dereference(mpath);
+ if (!mpath)
+ goto endmpathtimer;
+ spin_lock_bh(&mpath->state_lock);
+ sdata = mpath->sdata;
+ if (mpath->flags & MESH_PATH_RESOLVED ||
+ (!(mpath->flags & MESH_PATH_RESOLVING)))
+ mpath->flags &= ~(MESH_PATH_RESOLVING | MESH_PATH_RESOLVED);
+ else if (mpath->discovery_retries < max_preq_retries(sdata)) {
+ ++mpath->discovery_retries;
+ mpath->discovery_timeout *= 2;
+ sdata->u.mesh.mesh_pp->ops->queue_preq_fn(mpath, 0);
+ } else {
+ mpath->flags = 0;
+ mpath->exp_time = jiffies;
+ mesh_path_flush_pending(mpath);
+ }
+
+ spin_unlock_bh(&mpath->state_lock);
+endmpathtimer:
+ rcu_read_unlock();
+}
+EXPORT_SYMBOL(mesh_path_timer);
+
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 7b013fb..a486c87 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1351,11 +1351,13 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
ieee80211_is_data(hdr->frame_control)) {
if (is_multicast_ether_addr(hdr->addr3))
memcpy(hdr->addr1, hdr->addr3, ETH_ALEN);
+#ifdef CONFIG_MAC80211_MESH
else
- if (mesh_nexthop_lookup(skb, osdata)) {
+ if (osdata->u.mesh.mesh_pp->ops->nexthop_lookup_fn(skb, osdata)) {
dev_put(odev);
return 0;
}
+#endif
if (memcmp(odev->dev_addr, hdr->addr4, ETH_ALEN) != 0)
IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.mesh,
fwded_frames);
--
1.5.6.5


2009-01-26 20:39:18

by Florian Sesser

[permalink] [raw]
Subject: [PATCH 2/6] mac80211: Registration of path selection protocols

(Un)registering of path selection protocols
and some other functions for supporting the
change of PP at runtime.

Signed-off-by: Florian Sesser <[email protected]>
---
net/mac80211/mesh.c | 162 +++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 158 insertions(+), 4 deletions(-)

diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 8a1fcae..c0aaabd 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -9,6 +9,7 @@
*/

#include <asm/unaligned.h>
+#include <linux/module.h>
#include "ieee80211_i.h"
#include "mesh.h"

@@ -23,6 +24,8 @@

int mesh_allocated;
static struct kmem_cache *rm_cache;
+static DEFINE_SPINLOCK(path_sel_list_lock);
+static LIST_HEAD(mesh_path_sel_algo_list);

void ieee80211s_init(void)
{
@@ -112,14 +115,149 @@ void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata)
ieee80211_mesh_housekeeping_timer((unsigned long) sdata);
}

+struct mesh_path_sel_algo* mesh_path_sel_algo_find_by_name (const char* name)
+{
+ struct mesh_path_sel_algo *a;
+
+ list_for_each_entry(a, &mesh_path_sel_algo_list, list) {
+ if (!strcmp(a->name, name))
+ return a;
+ }
+
+ return NULL;
+}
+EXPORT_SYMBOL(mesh_path_sel_algo_find_by_name);
+
+struct mesh_path_sel_algo* mesh_path_sel_algo_find_by_id (u32 id)
+{
+ struct mesh_path_sel_algo *a;
+
+ list_for_each_entry(a, &mesh_path_sel_algo_list, list) {
+ if (a->id == id)
+ return a;
+ }
+
+ return NULL;
+}
+EXPORT_SYMBOL(mesh_path_sel_algo_find_by_id);
+
+static struct mesh_path_sel_algo* mesh_path_sel_algo_load(const char *name)
+{
+ struct mesh_path_sel_algo *a;
+ spin_lock(&path_sel_list_lock);
+ a = mesh_path_sel_algo_find_by_name(name);
+ if (!a) {
+ spin_unlock(&path_sel_list_lock);
+ request_module("%s", name);
+ spin_lock(&path_sel_list_lock);
+ a = mesh_path_sel_algo_find_by_name(name);
+ }
+
+ if (a && !try_module_get(a->owner))
+ a = NULL;
+ spin_unlock(&path_sel_list_lock);
+ return a;
+}
+
+void mesh_path_sel_algo_set (struct ieee80211_if_mesh *sta, struct mesh_path_sel_algo* algo)
+{
+ /* first, check if algo has been properly registered */
+ if (mesh_path_sel_algo_find_by_name(algo->name)) {
+
+ if (!sta->mesh_pp) {
+ /* set all three locations (duh): */
+ /* this connects an interface to its mesh pp algo */
+ sta->mesh_pp = algo;
+ /* this is used to compare mesh configs (see mesh_matches_local) */
+ memcpy(sta->mesh_pp_id, &(algo->id), 4);
+ /* this is used by the nl80211 layer */
+ sta->mshcfg.mesh_path_selection_protocol_id = algo->id;
+
+ printk(KERN_INFO "Initial mesh path selection algorithm %s / %08X.\n", algo->name, algo->id);
+ return;
+ }
+
+ if (sta->mesh_pp == algo) {
+ printk(KERN_INFO "Mesh path selection algorithm %s / %08X already active.\n", algo->name, algo->id);
+ return;
+ }
+
+ printk(KERN_INFO "Stopping mesh path selection algorithm %s / %08X ...\n", sta->mesh_pp->name, sta->mesh_pp->id);
+ sta->mesh_pp->ops->path_sel_stop_fn(sta);
+
+ sta->mesh_pp = algo;
+ memcpy(sta->mesh_pp_id, &algo->id, 4);
+ printk(KERN_INFO "Chosen mesh path selection algorithm %s / %08X.\n", sta->mesh_pp->name, sta->mesh_pp->id);
+
+ printk(KERN_INFO "Starting mesh path selection algorithm %s / %08X ...\n", sta->mesh_pp->name, sta->mesh_pp->id);
+ sta->mesh_pp->ops->path_sel_start_fn(sta);
+ }
+}
+EXPORT_SYMBOL(mesh_path_sel_algo_set);
+
+void mesh_path_sel_algo_register (struct mesh_path_sel_algo* algo)
+{
+ /* Sanity checks */
+ BUG_ON(!algo->ops->path_start_discovery_fn);
+ BUG_ON(!algo->ops->nexthop_lookup_fn);
+ BUG_ON(!algo->ops->path_error_tx_fn);
+ BUG_ON(!algo->ops->path_timer_fn);
+ BUG_ON(!algo->ops->queue_preq_fn);
+ BUG_ON(!algo->ops->rx_path_sel_frame_fn);
+ BUG_ON(!algo->ops->path_sel_start_fn);
+ BUG_ON(!algo->ops->path_sel_stop_fn);
+
+ spin_lock(&path_sel_list_lock);
+ if (!mesh_path_sel_algo_find_by_name(algo->name)) {
+ list_add_tail(&algo->list, &mesh_path_sel_algo_list);
+ spin_unlock(&path_sel_list_lock);
+ printk(KERN_INFO "Mesh path selection algorithm %s / %08X registered.\n", algo->name, algo->id);
+ } else {
+ spin_unlock(&path_sel_list_lock);
+ printk(KERN_WARNING "Error: Couldn't register mesh path selection algorithm %s / %08X.\n", algo->name, algo->id);
+ }
+}
+EXPORT_SYMBOL(mesh_path_sel_algo_register);
+
+void mesh_path_sel_algo_unregister (struct mesh_path_sel_algo *algo) {
+ if (mesh_path_sel_algo_find_by_name(algo->name)) {
+ list_del(&algo->list);
+ printk(KERN_INFO "Mesh path selection algorithm %s / %08X unregistered.\n", algo->name, algo->id);
+ } else {
+ printk(KERN_WARNING "Error: Couldn't unregister mesh path selection algorithm %s / %08X.\n", algo->name, algo->id);
+ }
+}
+EXPORT_SYMBOL(mesh_path_sel_algo_unregister);
+
void mesh_ids_set_default(struct ieee80211_if_mesh *sta)
{
- u8 def_id[4] = {0x00, 0x0F, 0xAC, 0xff};
+ u8 def_id[4] = {0x00, 0x0F, 0xAC, 0xFF};

memcpy(sta->mesh_pp_id, def_id, 4);
memcpy(sta->mesh_pm_id, def_id, 4);
memcpy(sta->mesh_cc_id, def_id, 4);
}
+/* Set path selection protocol ID: OUI followed by arbitrary 2 bytes */
+void mesh_ids_set_pp(struct ieee80211_if_mesh *sta, u32 pp)
+{
+ struct mesh_path_sel_algo *nalgo = mesh_path_sel_algo_find_by_id(pp);
+
+ if(nalgo) {
+ mesh_path_sel_algo_set(sta, nalgo);
+ } else {
+ printk(KERN_WARNING "Could not find mesh path selection protocol with ID %08X.\n", pp);
+ }
+}
+/* Set path selection metric ID: OUI followed by arbitrary 2 bytes */
+void mesh_ids_set_pm(struct ieee80211_if_mesh *sta, u32 pm)
+{
+ memcpy(sta->mesh_pm_id, &pm, 4);
+}
+/* Set congestion control mode ID: OUI followed by arbitrary 2 bytes */
+void mesh_ids_set_cc(struct ieee80211_if_mesh *sta, u32 cc)
+{
+ memcpy(sta->mesh_cc_id, &cc, 4);
+}

int mesh_rmc_init(struct ieee80211_sub_if_data *sdata)
{
@@ -246,7 +384,7 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
memcpy(pos, sdata->u.mesh.mesh_pp_id, 4);
pos += 4;

- /* Active path selection metric ID */
+ /* Active path selection metric ID */
memcpy(pos, sdata->u.mesh.mesh_pm_id, 4);
pos += 4;

@@ -444,6 +582,16 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
queue_work(local->hw.workqueue, &ifmsh->work);
ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON |
IEEE80211_IFCC_BEACON_ENABLED);
+
+ /* Register default path selection algorithm */
+ if (!ifmsh->mesh_pp) {
+ if(!(ifmsh->mesh_pp = mesh_path_sel_algo_find_by_name("mesh_hwmp"))) {
+ if (!(ifmsh->mesh_pp = mesh_path_sel_algo_load("mesh_hwmp"))) {
+ printk(KERN_WARNING "Could not load mesh_hwmp, aborting.\n");
+ ieee80211_stop_mesh(sdata);
+ }
+ }
+ }
}

void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
@@ -523,7 +671,7 @@ static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata,
mesh_rx_plink_frame(sdata, mgmt, len, rx_status);
break;
case MESH_PATH_SEL_CATEGORY:
- mesh_rx_path_sel_frame(sdata, mgmt, len);
+ sdata->u.mesh.mesh_pp->ops->rx_path_sel_frame_fn(sdata, mgmt, len);
break;
}
}
@@ -576,7 +724,7 @@ static void ieee80211_mesh_work(struct work_struct *work)
if (ifmsh->preq_queue_len &&
time_after(jiffies,
ifmsh->last_preq + msecs_to_jiffies(ifmsh->mshcfg.dot11MeshHWMPpreqMinInterval)))
- mesh_path_start_discovery(sdata);
+ ifmsh->mesh_pp->ops->path_start_discovery_fn(sdata);

if (ifmsh->housekeeping)
ieee80211_mesh_housekeeping(sdata, ifmsh);
@@ -617,6 +765,12 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata)
MESH_PREQ_MIN_INT;
ifmsh->mshcfg.dot11MeshHWMPnetDiameterTraversalTime =
MESH_DIAM_TRAVERSAL_TIME;
+ ifmsh->mshcfg.mesh_path_selection_protocol_id =
+ MESH_PATH_SELECTION_PROTOCOL_ID;
+ ifmsh->mshcfg.mesh_path_selection_metric_id =
+ MESH_PATH_SELECTION_METRIC_ID;
+ ifmsh->mshcfg.mesh_congestion_control_mode_id =
+ MESH_CONGESTION_CONTROL_MODE_ID;
ifmsh->mshcfg.dot11MeshHWMPmaxPREQretries =
MESH_MAX_PREQ_RETRIES;
ifmsh->mshcfg.path_refresh_time =
--
1.5.6.5


2009-01-27 11:22:22

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 4/6] mac80211: More small changes for modularization

On Tue, 2009-01-27 at 12:15 +0100, Florian Sesser wrote:
> Hi!
>
> Thanks for your comment. My intention was having a logical seperation to
> enable better discussion of my patch, which I think is pretty much of a
> monster and not yet ready for inclusion?
>
> What do you think about my selection of mesh_path_sel_ops and the
> storing of mesh PP/PM/CC id?
>
> If you deem it OK I would be happy to reformat the patch (into three or
> so seperatly compiling patches) and include KConfigs.

I also see a lot of EXPORT_SYMBOLs that should not be necessary, but I
need to look through it in more detail. I think your layering may be
broken in some parts. Why, for example, do you need to look up path
selection algorithms by name?

I also think you should wrap things like

osdata->u.mesh.mesh_pp->ops->nexthop_lookup_fn

into small static inlines that can go away if only one algorithm is
built in, for example.

johannes


Attachments:
signature.asc (836.00 B)
This is a digitally signed message part

2009-01-26 20:37:35

by Florian Sesser

[permalink] [raw]
Subject: [PATCH 1/1] Added capability to get/set individual mesh IDs

This allows the setting of
* Path selection protocol ID
* Path selection metric ID
* Congestion control mode ID

Signed-off-by: Florian Sesser <[email protected]>
---
mesh.c | 29 +++++++++++++++++++++++++++++
nl80211.h | 3 +++
2 files changed, 32 insertions(+), 0 deletions(-)

diff --git a/mesh.c b/mesh.c
index f663363..e790175 100644
--- a/mesh.c
+++ b/mesh.c
@@ -93,6 +93,18 @@ static uint32_t _parse_u32(const char *str, _any *ret)
return 0;
}

+static uint32_t _parse_hex_u32(const char *str, _any *ret)
+{
+ char *endptr = NULL;
+ long long int v = strtoll(str, &endptr, 16);
+ if (*endptr != '\0')
+ return 0xffffffff;
+ if ((v < 0) || (v > 0xffffffff))
+ return 0xffffffff;
+ ret->u.as_32 = (uint32_t)v;
+ return 0;
+}
+
static void _print_u8(struct nlattr *a)
{
printf("%d", nla_get_u8(a));
@@ -123,6 +135,11 @@ static void _print_u32_in_TUs(struct nlattr *a)
printf("%d TUs", nla_get_u32(a));
}

+void _print_u32_as_hex(struct nlattr *a)
+{
+ printf("%08X", nla_get_u32(a));
+}
+
/* The current mesh parameters */
const static struct mesh_param_descr _mesh_param_descrs[] =
{
@@ -165,6 +182,15 @@ const static struct mesh_param_descr _mesh_param_descrs[] =
{"mesh_hwmp_net_diameter_traversal_time",
NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
_my_nla_put_u16, _parse_u16, _print_u16_in_TUs},
+ {"mesh_path_selection_protocol_id",
+ NL80211_MESHCONF_PATH_SELECTION_PROTOCOL_ID,
+ _my_nla_put_u32, _parse_hex_u32, _print_u32_as_hex},
+ {"mesh_path_selection_metric_id",
+ NL80211_MESHCONF_PATH_SELECTION_METRIC_ID,
+ _my_nla_put_u32, _parse_hex_u32, _print_u32_as_hex},
+ {"mesh_congestion_control_mode_id",
+ NL80211_MESHCONF_CONGESTION_CONTROL_MODE_ID,
+ _my_nla_put_u32, _parse_hex_u32, _print_u32_as_hex},
};

static void print_all_mesh_param_descr(void)
@@ -187,6 +213,9 @@ static const struct mesh_param_descr* find_mesh_param(int argc, char **argv,
if (argc < 1) {
printf("You must specify which mesh parameter to %s.\n",
action_name);
+ printf("Mesh_param must be one of: ");
+ print_all_mesh_param_descr();
+ printf("\n");
return NULL;
}

diff --git a/nl80211.h b/nl80211.h
index e86ed59..db0fe93 100644
--- a/nl80211.h
+++ b/nl80211.h
@@ -765,6 +765,9 @@ enum nl80211_meshconf_params {
NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
+ NL80211_MESHCONF_PATH_SELECTION_PROTOCOL_ID,
+ NL80211_MESHCONF_PATH_SELECTION_METRIC_ID,
+ NL80211_MESHCONF_CONGESTION_CONTROL_MODE_ID,

/* keep last */
__NL80211_MESHCONF_ATTR_AFTER_LAST,
--
1.5.6.5


2009-01-26 20:39:19

by Florian Sesser

[permalink] [raw]
Subject: [PATCH 4/6] mac80211: More small changes for modularization

Some rather small changes in various files.
After this patch, i was able to do a clean compile.

Signed-off-by: Florian Sesser <[email protected]>
---
include/net/cfg80211.h | 4 ++++
net/mac80211/Makefile | 8 ++++++--
net/mac80211/ieee80211_i.h | 5 +++++
net/mac80211/sta_info.c | 1 +
net/mac80211/util.c | 2 ++
5 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index dd1fd51..83eb2a1 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -458,6 +458,10 @@ struct mesh_config {
u32 dot11MeshHWMPactivePathTimeout;
u16 dot11MeshHWMPpreqMinInterval;
u16 dot11MeshHWMPnetDiameterTraversalTime;
+ /* Mesh IDs */
+ u32 mesh_path_selection_protocol_id;
+ u32 mesh_path_selection_metric_id;
+ u32 mesh_congestion_control_mode_id;
};

/**
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile
index 58c94bb..796e7a6 100644
--- a/net/mac80211/Makefile
+++ b/net/mac80211/Makefile
@@ -35,8 +35,12 @@ mac80211-$(CONFIG_MAC80211_DEBUGFS) += \
mac80211-$(CONFIG_MAC80211_MESH) += \
mesh.o \
mesh_pathtbl.o \
- mesh_plink.o \
- mesh_hwmp.o
+ mesh_plink.o
+
+# HWMP routing is a requirement for 80211s
+ifdef CONFIG_MAC80211_MESH
+obj-m += mesh_hwmp.o
+endif

mac80211-$(CONFIG_PM) += pm.o

diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index eaf3603..5490ba1 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -365,6 +365,8 @@ struct ieee80211_if_mesh {
u8 mesh_pm_id[4];
/* Congestion Control Mode Identifier */
u8 mesh_cc_id[4];
+ /* Active Path Selection Protocol */
+ struct mesh_path_sel_algo* mesh_pp;
/* Local mesh Destination Sequence Number */
u32 dsn;
/* Last used PREQ ID */
@@ -534,6 +536,9 @@ struct ieee80211_sub_if_data {
struct dentry *dot11MeshHWMPmaxPREQretries;
struct dentry *path_refresh_time;
struct dentry *min_discovery_timeout;
+ struct dentry *mesh_path_selection_protocol_id;
+ struct dentry *mesh_path_selection_metric_id;
+ struct dentry *mesh_congestion_mode_control_id;
} mesh_config;
#endif

diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 10c5539..b10d754 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -105,6 +105,7 @@ struct sta_info *sta_info_get(struct ieee80211_local *local, const u8 *addr)
}
return sta;
}
+EXPORT_SYMBOL(sta_info_get);

struct sta_info *sta_info_get_by_idx(struct ieee80211_local *local, int idx,
struct net_device *dev)
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 73c7d73..c579606 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -674,6 +674,7 @@ void ieee802_11_parse_elems(u8 *start, size_t len,
pos += elen;
}
}
+EXPORT_SYMBOL(ieee802_11_parse_elems);

void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata)
{
@@ -714,6 +715,7 @@ void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,

dev_queue_xmit(skb);
}
+EXPORT_SYMBOL(ieee80211_tx_skb);

int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freqMHz)
{
--
1.5.6.5


2009-01-26 21:16:41

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 4/6] mac80211: More small changes for modularization

On Mon, 2009-01-26 at 21:39 +0100, Florian Sesser wrote:
> Some rather small changes in various files.
> After this patch, i was able to do a clean compile.

You need to ensure that after _every_ single patch.

johannes


Attachments:
signature.asc (836.00 B)
This is a digitally signed message part

2009-01-26 21:19:26

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 6/6] mac80211: Path Selection Protocol dummy module

On Mon, 2009-01-26 at 21:39 +0100, Florian Sesser wrote:
> Can be inserted and 'used' for Path Selection
> by insmodding and issuing:
> iw dev <mesh-dev> set mesh_param mesh_path_selection_protocol_id 000F0F0F
>
> Signed-off-by: Florian Sesser <[email protected]>
> ---
> net/mac80211/Makefile | 2 +
> net/mac80211/mesh_pptest.c | 71 ++++++++++++++++++++++++++++++++++++++++++++

Kconfig?

johannes


Attachments:
signature.asc (836.00 B)
This is a digitally signed message part

2009-01-26 21:20:08

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 3/6] mac80211: Modularized mesh_hwmp.c

On Mon, 2009-01-26 at 21:39 +0100, Florian Sesser wrote:
> Separate mesh_hwmp.c into own module, which is
> loaded automatically as the default path selection
> protocol.

Let's keep that built-in so it doesn't all break all the time. Kconfig
too. Cf. rate control.

johannes


Attachments:
signature.asc (836.00 B)
This is a digitally signed message part

2009-01-27 11:16:03

by Florian Sesser

[permalink] [raw]
Subject: Re: [PATCH 4/6] mac80211: More small changes for modularization

Hi!

Thanks for your comment. My intention was having a logical seperation to
enable better discussion of my patch, which I think is pretty much of a
monster and not yet ready for inclusion?

What do you think about my selection of mesh_path_sel_ops and the
storing of mesh PP/PM/CC id?

If you deem it OK I would be happy to reformat the patch (into three or
so seperatly compiling patches) and include KConfigs.

Thanks,

Florian


Johannes Berg wrote:
> On Mon, 2009-01-26 at 21:39 +0100, Florian Sesser wrote:
>> Some rather small changes in various files.
>> After this patch, i was able to do a clean compile.
>
> You need to ensure that after _every_ single patch.
>
> johannes

2009-01-27 09:33:30

by Rami Rosen

[permalink] [raw]
Subject: Re: [PATCH 1/6] mac80211: Virtualize mesh path selection ops

Hello,

A little comment:

Maybe it is better to omit from the patch the remark :
/* From mesh_hwmp.c: */
(which appears twice)
and add to the changelog an item like this:

-Moved mpath_frame_type enum definition and max_preq_retries() macro
definition from mesh_hwmp.c to mesh.h.


Regards,
Rami Rosen



On Mon, Jan 26, 2009 at 10:39 PM, Florian Sesser
<[email protected]> wrote:
> Struct mesh_path_sel_ops, central to the abstraction
> of the Path Selection Protocol.
>
> Signed-off-by: Florian Sesser <[email protected]>
> ---
> net/mac80211/mesh.h | 78 +++++++++++++++++++++++++++++++++++++++++++++++++--
> 1 files changed, 75 insertions(+), 3 deletions(-)
>
> diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
> index 9e064ee..a4141d8 100644
> --- a/net/mac80211/mesh.h
> +++ b/net/mac80211/mesh.h
> @@ -169,6 +169,72 @@ struct mesh_rmc {
> */
> #define MESH_PREQ_MIN_INT 10
> #define MESH_DIAM_TRAVERSAL_TIME 50
> +
> +/* Default Path Selection, Path Metric, Congestion Control Mode */
> +#define MESH_PATH_SELECTION_PROTOCOL_ID 0x000FACFF
> +#define MESH_PATH_SELECTION_METRIC_ID 0x000FACFF
> +#define MESH_CONGESTION_CONTROL_MODE_ID 0x000FACFF
> +
> +/* From mesh_hwmp.c: */
> +enum mpath_frame_type {
> + MPATH_PREQ = 0,
> + MPATH_PREP,
> + MPATH_PERR
> +};
> +/* Function pointer typedefs for struct mesh_path_sel_ops */
> +typedef void (mesh_path_start_discovery_fn) (struct ieee80211_sub_if_data *sdata);
> +typedef int (mesh_nexthop_lookup_fn) (struct sk_buff *skb, struct ieee80211_sub_if_data *sdata);
> +typedef void (mesh_queue_preq_fn) (struct mesh_path *mpath, u8 flags);
> +typedef int (mesh_path_sel_frame_tx_fn) (enum mpath_frame_type action, u8 flags,
> + u8 *orig_addr, __le32 orig_dsn, u8 dst_flags, u8 *dst, __le32 dst_dsn, u8 *da,
> + u8 hop_count, u8 ttl, __le32 lifetime, __le32 metric, __le32 preq_id,
> + struct ieee80211_sub_if_data *sdata);
> +typedef int (mesh_path_error_tx_fn) (u8 *dst, __le32 dst_dsn, u8 *ra,
> + struct ieee80211_sub_if_data *sdata);
> +typedef void (mesh_path_timer_fn) (unsigned long data);
> +typedef u32 (mesh_route_info_get_fn) (struct ieee80211_sub_if_data *sdata,
> + struct ieee80211_mgmt *mgmt, u8 *ie);
> +typedef void (mesh_rx_path_sel_frame_fn) (struct ieee80211_sub_if_data *sdata,
> + struct ieee80211_mgmt *mgmt, size_t len);
> +typedef void (mesh_preq_frame_process_fn) (struct ieee80211_sub_if_data *sdata,
> + struct ieee80211_mgmt *mgmt, u8 *preq_elem, u32 metric);
> +typedef void (mesh_prep_frame_process_fn) (struct ieee80211_sub_if_data *sdata,
> + struct ieee80211_mgmt *mgmt, u8 *prep_elem, u32 metric);
> +typedef void (mesh_perr_frame_process_fn) (struct ieee80211_sub_if_data *sdata,
> + struct ieee80211_mgmt *mgmt, u8 *perr_elem);
> +typedef void (mesh_path_sel_start_fn) (struct ieee80211_if_mesh *sta);
> +typedef void (mesh_path_sel_stop_fn) (struct ieee80211_if_mesh *sta);
> +struct mesh_path_sel_ops {
> + mesh_path_start_discovery_fn *path_start_discovery_fn;
> + mesh_nexthop_lookup_fn *nexthop_lookup_fn;
> + /* Needed by mesh_path_timer from mesh_pathtbl.c */
> + mesh_queue_preq_fn *queue_preq_fn;
> + /* To my surprise this seems to not be needed:
> + mesh_path_sel_frame_tx_fn *path_sel_frame_tx_fn; */
> + mesh_path_error_tx_fn *path_error_tx_fn;
> + /* Doesn't this timer belong into mesh.c? */
> + mesh_path_timer_fn *path_timer_fn;
> + mesh_rx_path_sel_frame_fn *rx_path_sel_frame_fn;
> + /* Belongs into the mesh routing protocol module
> + mesh_preq_frame_process_fn *preq_frame_process_fn;
> + mesh_prep_frame_process_fn *prep_frame_process_fn;
> + mesh_perr_frame_process_fn *perr_frame_process_fn; */
> + mesh_path_sel_start_fn *path_sel_start_fn;
> + mesh_path_sel_stop_fn *path_sel_stop_fn;
> +};
> +
> +#define MESH_ALGO_NAME_MAX (16)
> +struct mesh_path_sel_algo {
> + struct list_head list;
> + char name[MESH_ALGO_NAME_MAX];
> + u32 id;
> + struct mesh_path_sel_ops* ops;
> + struct module* owner;
> +};
> +
> +void mesh_path_sel_algo_register (struct mesh_path_sel_algo *algo);
> +void mesh_path_sel_algo_unregister (struct mesh_path_sel_algo *algo);
> +
> /* Paths will be refreshed if they are closer than PATH_REFRESH_TIME to their
> * expiration
> */
> @@ -205,6 +271,9 @@ int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr,
> bool mesh_matches_local(struct ieee802_11_elems *ie,
> struct ieee80211_sub_if_data *sdata);
> void mesh_ids_set_default(struct ieee80211_if_mesh *mesh);
> +void mesh_ids_set_pp(struct ieee80211_if_mesh *sta, u32 pp);
> +void mesh_ids_set_pm(struct ieee80211_if_mesh *sta, u32 pm);
> +void mesh_ids_set_cc(struct ieee80211_if_mesh *sta, u32 cc);
> void mesh_mgmt_ies_add(struct sk_buff *skb,
> struct ieee80211_sub_if_data *sdata);
> void mesh_rmc_free(struct ieee80211_sub_if_data *sdata);
> @@ -219,9 +288,9 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata);
> void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata);
>
> /* Mesh paths */
> -int mesh_nexthop_lookup(struct sk_buff *skb,
> - struct ieee80211_sub_if_data *sdata);
> -void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata);
> +struct mesh_path_sel_algo* mesh_path_sel_algo_find_by_name (const char* name);
> +struct mesh_path_sel_algo* mesh_path_sel_algo_find_by_id (u32 id);
> +void mesh_path_sel_algo_set (struct ieee80211_if_mesh *sta, struct mesh_path_sel_algo* algo);
> struct mesh_path *mesh_path_lookup(u8 *dst,
> struct ieee80211_sub_if_data *sdata);
> struct mesh_path *mpp_path_lookup(u8 *dst,
> @@ -293,6 +362,9 @@ static inline void mesh_path_activate(struct mesh_path *mpath)
> for (i = 0; i <= x->hash_mask; i++) \
> hlist_for_each_entry_rcu(node, p, &x->hash_buckets[i], list)
>
> +/* Moved here from mesh_hwmp.c */
> +#define max_preq_retries(s) (s->u.mesh.mshcfg.dot11MeshHWMPmaxPREQretries)
> +
> void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local);
>
> #else
> --
> 1.5.6.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>

2009-01-26 21:09:34

by Johannes Berg

[permalink] [raw]
Subject: Re: [RFC][RFT] mac80211 / mesh: Modularize Path Selection Protocol

On Mon, 2009-01-26 at 21:22 +0100, Florian Sesser wrote:

> This is my first patch not only to the kernel, but to any open source
> project, so please be gentle ;) I am open to suggestions for
> improvement; please also remind me on any coding style or other errors
> you may find.

If you haven't seen it,
http://wireless.kernel.org/en/developers/Documentation/SubmittingPatches
contains some useful hints. I'll look over your patches later.

johannes


Attachments:
signature.asc (836.00 B)
This is a digitally signed message part