summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2007-09-08 13:42:29 +0000
committerDan Williams <dcbw@redhat.com>2007-09-08 13:42:29 +0000
commitb7897b7b58d5c89a677230f17a08f6f06a307634 (patch)
tree58c3e34ba646b9d67a2f32a640beaee6e35f2f4b
parent30e6b041f7abdc2b3de49536ecdc23b3850d78fe (diff)
downloadNetworkManager-b7897b7b58d5c89a677230f17a08f6f06a307634.tar.gz
2007-09-08 Dan Williams <dcbw@redhat.com>
* src/nm-device-802-11-mesh-olpc.h src/nm-device-802-11-mesh-olpc.c - More granular mesh device control. Mesh devices may be activated with a specific channel and mesh step, and will be locked to that channel for the duration of the activation. The default is still the same (4-step activation process on all 3 channels). * src/nm-activation-request.h src/nm-activation-request.c - (nm_act_request_set_mesh_channel, nm_act_request_get_mesh_channel, nm_act_request_set_mesh_start, nm_act_request_get_mesh_start): new functions to support more granular mesh device control * src/nm-dbus-nm.c - (nm_dbus_nm_set_active_device): accept mesh channel and mesh step start parameters for mesh device activation git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/branches/nm-0-6-olpc@2770 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
-rw-r--r--ChangeLog19
-rw-r--r--src/nm-activation-request.c32
-rw-r--r--src/nm-activation-request.h5
-rw-r--r--src/nm-dbus-nm.c55
-rw-r--r--src/nm-device-802-11-mesh-olpc.c263
-rw-r--r--src/nm-device-802-11-mesh-olpc.h4
6 files changed, 254 insertions, 124 deletions
diff --git a/ChangeLog b/ChangeLog
index 54110ec9ee..bc3196d736 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2007-09-08 Dan Williams <dcbw@redhat.com>
+
+ * src/nm-device-802-11-mesh-olpc.h
+ src/nm-device-802-11-mesh-olpc.c
+ - More granular mesh device control. Mesh devices may be activated
+ with a specific channel and mesh step, and will be locked to that
+ channel for the duration of the activation. The default is still
+ the same (4-step activation process on all 3 channels).
+
+ * src/nm-activation-request.h
+ src/nm-activation-request.c
+ - (nm_act_request_set_mesh_channel, nm_act_request_get_mesh_channel,
+ nm_act_request_set_mesh_start, nm_act_request_get_mesh_start):
+ new functions to support more granular mesh device control
+
+ * src/nm-dbus-nm.c
+ - (nm_dbus_nm_set_active_device): accept mesh channel and mesh step
+ start parameters for mesh device activation
+
2007-08-30 Dan Williams <dcbw@redhat.com>
* src/nm-device-802-11-mesh-olpc.h
diff --git a/src/nm-activation-request.c b/src/nm-activation-request.c
index e563d2b3f4..81f795131b 100644
--- a/src/nm-activation-request.c
+++ b/src/nm-activation-request.c
@@ -44,6 +44,10 @@ struct NMActRequest
DBusPendingCall * user_key_pcall;
guint dhcp_timeout_wait; /* in seconds */
+
+ /* Mesh stuff */
+ guint32 mesh_channel;
+ guint32 mesh_start;
};
@@ -221,3 +225,31 @@ void nm_act_request_set_dhcp_timeout_wait (NMActRequest *req, guint seconds)
req->dhcp_timeout_wait = seconds;
}
+void nm_act_request_set_mesh_channel (NMActRequest *req, guint32 channel)
+{
+ g_return_if_fail (req != NULL);
+
+ req->mesh_channel = channel;
+}
+
+guint32 nm_act_request_get_mesh_channel (NMActRequest *req)
+{
+ g_return_if_fail (req != NULL);
+
+ return req->mesh_channel;
+}
+
+void nm_act_request_set_mesh_start (NMActRequest *req, guint32 start)
+{
+ g_return_if_fail (req != NULL);
+
+ req->mesh_start = start;
+}
+
+guint32 nm_act_request_get_mesh_start (NMActRequest *req)
+{
+ g_return_if_fail (req != NULL);
+
+ return req->mesh_start;
+}
+
diff --git a/src/nm-activation-request.h b/src/nm-activation-request.h
index 5f9f747238..89ea47e6a3 100644
--- a/src/nm-activation-request.h
+++ b/src/nm-activation-request.h
@@ -53,4 +53,9 @@ void nm_act_request_set_user_key_pending_call (NMActRequest *req, DBusPending
guint nm_act_request_get_dhcp_timeout_wait (NMActRequest *req);
void nm_act_request_set_dhcp_timeout_wait (NMActRequest *req, guint dhcp_timeout);
+void nm_act_request_set_mesh_channel (NMActRequest *req, guint32 channel);
+guint32 nm_act_request_get_mesh_channel (NMActRequest *req);
+void nm_act_request_set_mesh_start (NMActRequest *req, guint32 start);
+guint32 nm_act_request_get_mesh_start (NMActRequest *req);
+
#endif
diff --git a/src/nm-dbus-nm.c b/src/nm-dbus-nm.c
index 77edd5976a..c3555c0ea4 100644
--- a/src/nm-dbus-nm.c
+++ b/src/nm-dbus-nm.c
@@ -232,6 +232,8 @@ static DBusMessage *nm_dbus_nm_set_active_device (DBusConnection *connection, DB
NMAccessPoint * ap = NULL;
NMActRequest * req;
DBusMessageIter iter;
+ guint32 mesh_channel = G_MAXUINT32;
+ guint32 mesh_step = G_MAXUINT32;
g_return_val_if_fail (connection != NULL, NULL);
g_return_val_if_fail (message != NULL, NULL);
@@ -305,12 +307,59 @@ static DBusMessage *nm_dbus_nm_set_active_device (DBusConnection *connection, DB
}
else if (nm_device_is_802_11_mesh_olpc (dev))
{
- nm_info ("User Switch: %s", dev_path);
+ if (dbus_message_iter_next (&iter)) {
+ double freq = 0;
+
+ if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DOUBLE) {
+ nm_warning ("%s:%d (%s): Invalid argument type (frequency).",
+ __FILE__, __LINE__, __func__);
+ goto out;
+ }
+
+ /* grab frequency and accept only channels 1, 6, and 11 */
+ dbus_message_iter_get_basic (&iter, &freq);
+ if (freq == 2.412)
+ mesh_channel = 1;
+ else if (freq == 2.437)
+ mesh_channel = 6;
+ else if (freq == 2.462)
+ mesh_channel = 11;
+ else if (freq != 0) {
+ nm_warning ("%s:%d (%s): Invalid argument (frequency): %f.",
+ __FILE__, __LINE__, __func__, freq);
+ goto out;
+ }
+
+ /* Optional mesh step start */
+ if (dbus_message_iter_next (&iter)) {
+ char * step_string = NULL;
+
+ if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING) {
+ nm_warning ("%s:%d (%s): Invalid argument type (mesh step).",
+ __FILE__, __LINE__, __func__);
+ goto out;
+ }
+
+ dbus_message_iter_get_basic (&iter, &mesh_step);
+ mesh_step = nm_device_802_11_mesh_olpc_parse_mesh_step (step_string,
+ G_MAXUINT32);
+ }
+ }
+
+ nm_info ("User Switch: %s, channel %d, step %d", dev_path,
+ mesh_channel == G_MAXUINT32 ? -1 : mesh_channel,
+ mesh_step == G_MAXUINT32 ? -1 : mesh_step);
}
nm_device_deactivate (dev);
nm_schedule_state_change_signal_broadcast (data->data);
req = nm_act_request_new (data->data, dev, ap, TRUE);
+
+ if (mesh_channel != G_MAXUINT32)
+ nm_act_request_set_mesh_channel (req, mesh_channel);
+ if (mesh_step != G_MAXUINT32)
+ nm_act_request_set_mesh_start (req, mesh_step);
+
nm_policy_schedule_device_activation (req);
nm_act_request_unref (req);
@@ -320,8 +369,8 @@ static DBusMessage *nm_dbus_nm_set_active_device (DBusConnection *connection, DB
nm_warning ("Could not allocate dbus message.");
out:
- if (!reply)
- {
+ if (!reply) {
+ nm_act_request_unref (req);
reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE,
INVALID_ARGS_ERROR, INVALID_ARGS_MESSAGE);
}
diff --git a/src/nm-device-802-11-mesh-olpc.c b/src/nm-device-802-11-mesh-olpc.c
index 1ed926de40..4a323e8fcd 100644
--- a/src/nm-device-802-11-mesh-olpc.c
+++ b/src/nm-device-802-11-mesh-olpc.c
@@ -190,6 +190,8 @@ struct _NMDevice80211MeshOLPCPrivate
guint32 step; /* 1, 2, 3, or 4 from behavior description above */
guint32 default_first_step;
+ gboolean channel_locked;
+ guint32 chans_tried;
guint32 channel;
gboolean use_mesh_beacons;
@@ -358,9 +360,12 @@ nm_device_802_11_mesh_olpc_init (NMDevice80211MeshOLPC * self)
self->priv = NM_DEVICE_802_11_MESH_OLPC_GET_PRIVATE (self);
self->priv->dispose_has_run = FALSE;
self->priv->is_initialized = FALSE;
+ self->priv->capabilities = 0;
+ self->priv->assoc_timeout = NULL;
+ self->priv->wireless_event_id = 0;
+ self->priv->default_first_step = MESH_S1_SCHOOL_MPP;
}
-#if 0
guint32 get_random_channel (void)
{
GRand * rand;
@@ -378,7 +383,28 @@ guint32 get_random_channel (void)
/* Return a random channel of [1, 6, 11] */
return ((num % 3) * 5) + 1;
}
-#endif
+
+guint32
+nm_device_802_11_mesh_olpc_parse_mesh_step (const char * step_string,
+ guint32 fallback)
+{
+ guint32 step = fallback;
+
+ g_return_val_if_fail (step_string != NULL, fallback);
+
+ if (!strcmp (step_string, "school-mpp"))
+ step = MESH_S1_SCHOOL_MPP;
+ else if (!strcmp (step_string, "infra"))
+ step = MESH_S2_AP;
+ else if (!strcmp (step_string, "xo-mpp"))
+ step = MESH_S3_XO_MPP;
+ else if (!strcmp (step_string, "local"))
+ step = MESH_S4_P2P_MESH;
+ else
+ nm_warning ("Failed to parse unknown mesh step %s.", step_string);
+
+ return step;
+}
static void
real_init (NMDevice *dev)
@@ -391,31 +417,36 @@ real_init (NMDevice *dev)
char * automesh_path = NULL;
char * contents = NULL;
gboolean success = FALSE;
+ const char * iface;
self->priv->is_initialized = TRUE;
- self->priv->capabilities = 0;
- self->priv->default_first_step = MESH_S1_SCHOOL_MPP;
+ iface = nm_device_get_iface (dev);
+
success = g_file_get_contents (MESH_STEP_FILE,
&contents,
NULL,
NULL);
if (success && contents) {
contents = g_strstrip (contents);
- if (!strcmp (contents, "school-mpp")) {
- nm_info ("%s: Mesh behavior override: School Server first", nm_device_get_iface (dev));
- self->priv->default_first_step = MESH_S1_SCHOOL_MPP;
- } else if (!strcmp (contents, "infra")) {
- nm_info ("%s: Mesh behavior override: Infrastructure AP first", nm_device_get_iface (dev));
- self->priv->default_first_step = MESH_S2_AP;
- } else if (!strcmp (contents, "xo-mpp")) {
- nm_info ("%s: Mesh behavior override: XO Mesh Portal first", nm_device_get_iface (dev));
- self->priv->default_first_step = MESH_S3_XO_MPP;
- } else if (!strcmp (contents, "local")) {
- nm_info ("%s: Mesh behavior override: link-local only.", nm_device_get_iface (dev));
- self->priv->default_first_step = MESH_S4_P2P_MESH;
- } else {
- nm_info ("%s: Unknown Mesh behavior override '%s', defaulting to School Server.", nm_device_get_iface (dev), contents);
+ self->priv->default_first_step = nm_device_802_11_mesh_olpc_parse_mesh_step (contents, G_MAXUINT32);
+ switch (self->priv->default_first_step) {
+ case MESH_S1_SCHOOL_MPP:
+ nm_info ("%s: Mesh behavior override: School Server first", iface);
+ break;
+ case MESH_S2_AP:
+ nm_info ("%s: Mesh behavior override: Infrastructure AP first", iface);
+ break;
+ case MESH_S3_XO_MPP:
+ nm_info ("%s: Mesh behavior override: XO Mesh Portal first", iface);
+ break;
+ case MESH_S4_P2P_MESH:
+ nm_info ("%s: Mesh behavior override: link-local only.", iface);
+ break;
+ default:
+ nm_info ("%s: Unknown Mesh behavior override '%s', defaulting to School Server.", iface, contents);
+ self->priv->default_first_step = MESH_S1_SCHOOL_MPP;
+ break;
}
g_free (contents);
}
@@ -426,9 +457,7 @@ real_init (NMDevice *dev)
self->priv->use_mesh_beacons = TRUE;
}
- self->priv->channel = 1;
- self->priv->assoc_timeout = NULL;
- self->priv->wireless_event_id = 0;
+ self->priv->channel = get_random_channel ();
self->priv->mpp.activated_ids = g_hash_table_new (g_direct_hash,
g_direct_equal);
@@ -1499,21 +1528,50 @@ chan_to_freq (int chan)
return (double) frequency_list[chan - 1] / 1000.0;
}
+static int next_chan_table[14][4] = {
+ {-1, -1, -1, -1},
+ {1, 6, 6, -1},
+ {-1, -1, -1, -1},
+ {-1, -1, -1, -1},
+ {-1, -1, -1, -1},
+ {-1, -1, -1, -1},
+ {6, 11, 11, -1},
+ {-1, -1, -1, -1},
+ {-1, -1, -1, -1},
+ {-1, -1, -1, -1},
+ {-1, -1, -1, -1},
+ {11, 1, 1, -1},
+ {-1, -1, -1, -1},
+ {-1, -1, -1, -1}
+};
+
static int
-get_next_channel (NMDevice80211MeshOLPC * self)
+channel_failure_handler_unlocked (NMDevice80211MeshOLPC *self,
+ NMActRequest *req,
+ gboolean *reinit_state)
{
- NMAccessPointList * ap_list;
- int inc = 0;
- int ret_chan = -1;
- int next = self->priv->channel;
- gboolean fallback = FALSE;
+ gboolean fail = FALSE;
+ int next_chan = -1;
+
+ g_return_val_if_fail (self != NULL, -1);
+ g_return_val_if_fail (req != NULL, -1);
+ g_return_val_if_fail (reinit_state != NULL, -1);
switch (self->priv->step) {
case MESH_S1_SCHOOL_MPP:
- inc = 5;
- break;
case MESH_S3_XO_MPP:
- inc = 5;
+ self->priv->chans_tried++;
+nm_info ("chans tried: %d, channel %d", self->priv->chans_tried, self->priv->channel);
+ next_chan = next_chan_table[self->priv->channel][self->priv->chans_tried];
+ if (next_chan < 0) {
+ /* fail; go to next step */
+ self->priv->step++;
+ self->priv->channel = get_random_channel ();
+ }
+ break;
+ case MESH_S4_P2P_MESH:
+ fail = TRUE;
+ *reinit_state = TRUE;
break;
default:
nm_info ("%s: %s():%d unhandled step %d",
@@ -1522,102 +1580,34 @@ get_next_channel (NMDevice80211MeshOLPC * self)
__LINE__,
self->priv->step);
g_assert_not_reached ();
- goto out;
break;
}
- /* Unfortunately we can't do the mesh check reliably, because we don't
- * have good enough scan behavior in the libertas driver, so we're likely
- * to miss channels that have meshes on them. We need null packet support
- * in the firmware so that scanning can use power-save mode tricks to do
- * full scans, which it currently doesn't do.
- */
- if (!self->priv->use_mesh_beacons) {
- fallback = TRUE;
- goto out;
- }
-
- ap_list = nm_device_802_11_wireless_ap_list_get (self->priv->ethdev.dev);
- if (!ap_list) {
- nm_info ("%s: %s():%d no scan results, falling back to next channel",
- nm_device_get_iface (NM_DEVICE (self)), __func__, __LINE__);
- fallback = TRUE;
- goto out;
- }
-
- /* Find the next channel with a mesh on it */
- while ((next < CHAN_MAX) && (ret_chan < 1)) {
- NMAPListIter * iter;
- NMAccessPoint * ap;
-
- next += inc;
-
- /* Look for a mesh on this channel */
- if (!(iter = nm_ap_list_iter_new (ap_list))) {
- nm_info ("%s: %s():%d couldn't lock scan list, falling back to next channel",
- nm_device_get_iface (NM_DEVICE (self)), __func__, __LINE__);
- fallback = TRUE;
- goto out;
- }
-
- while ((ap = nm_ap_list_iter_next (iter))) {
- double freq = nm_ap_get_freq (ap);
-
- /* If there's a BSS on this channel that's mesh capable, use it */
- if ( (freq > 0)
- && (chan_to_freq (next) == freq)
- && (nm_ap_get_capabilities (ap) & NM_802_11_CAP_MESH_OLPC)) {
- ret_chan = next;
-nm_info ("%s: %s():%d found mesh on channel %d",
-nm_device_get_iface (NM_DEVICE (self)), __func__, __LINE__, ret_chan);
- break;
- }
- }
-
-if (ret_chan < 0) {
-nm_info ("%s: %s():%d no mesh on channel %d",
-nm_device_get_iface (NM_DEVICE (self)), __func__, __LINE__, next);
- nm_ap_list_iter_free (iter);
-}
- }
-
-out:
- /* If there was an error, just pick the next channel */
- if (fallback)
- ret_chan = self->priv->channel += inc;
-
- if (ret_chan > CHAN_MAX)
- ret_chan = -1;
-nm_info ("%s: returning channel %d\n", nm_device_get_iface (NM_DEVICE (self)), ret_chan);
- return ret_chan;
+ return fail ? -1 : next_chan;
}
-static void
-channel_failure_handler (NMDevice80211MeshOLPC *self,
- NMActRequest *req)
+static int
+channel_failure_handler_locked (NMDevice80211MeshOLPC *self,
+ NMActRequest *req,
+ gboolean *reinit_state)
{
- gboolean fail = FALSE;
- gboolean reinit_state = FALSE;
int next_chan = -1;
- g_return_if_fail (self != NULL);
- g_return_if_fail (req != NULL);
+ g_return_val_if_fail (self != NULL, -1);
+ g_return_val_if_fail (req != NULL, -1);
+ g_return_val_if_fail (reinit_state != NULL, -1);
switch (self->priv->step) {
case MESH_S1_SCHOOL_MPP:
- /* If the last channel we tried was 11 for school server, we failed */
- if (self->priv->channel >= 11) {
- fail = TRUE;
- break;
- }
- next_chan = get_next_channel (self);
+ self->priv->step = MESH_S3_XO_MPP;
+ next_chan = self->priv->channel;
break;
case MESH_S3_XO_MPP:
- next_chan = get_next_channel (self);
+ self->priv->step = MESH_S4_P2P_MESH;
+ next_chan = self->priv->channel;
break;
case MESH_S4_P2P_MESH:
- fail = TRUE;
- reinit_state = TRUE;
+ *reinit_state = TRUE;
break;
default:
nm_info ("%s: %s():%d unhandled step %d",
@@ -1629,15 +1619,36 @@ channel_failure_handler (NMDevice80211MeshOLPC *self,
break;
}
+ return next_chan;
+}
+
+static void
+channel_failure_handler (NMDevice80211MeshOLPC *self,
+ NMActRequest *req)
+{
+ gboolean reinit_state = FALSE;
+ int next_chan = -1;
+ guint32 old_step;
+ gboolean fail = FALSE;
+
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (req != NULL);
+
+ old_step = self->priv->step;
+
+ if (self->priv->channel_locked)
+ next_chan = channel_failure_handler_locked (self, req, &reinit_state);
+ else
+ next_chan = channel_failure_handler_unlocked (self, req, &reinit_state);
+
/* If the ethdev happened to go away or the new channel is invalid,
* break the chain
*/
-nm_info ("%s: step %d, channel %d, next channel %d\n", __func__, self->priv->step, self->priv->channel, next_chan);
- if (!self->priv->ethdev.dev || (next_chan < 1))
-{
+nm_info ("%s: step %d, channel %d, next channel %d", __func__, old_step, self->priv->channel, next_chan);
+ if (!self->priv->ethdev.dev || (next_chan < 0)) {
nm_info (" will fail");
fail = TRUE;
-}
+ }
if (fail) {
nm_info ("%s: failing activation", __func__);
@@ -1648,7 +1659,9 @@ nm_info ("%s: failing activation", __func__);
nm_device_set_active_link (NM_DEVICE (self), FALSE);
if (reinit_state) {
self->priv->step = self->priv->default_first_step;
- self->priv->channel = 1;
+ self->priv->channel = get_random_channel ();
+ self->priv->chans_tried = 0;
+ self->priv->channel_locked = FALSE;
}
} else {
nm_info ("Activation (%s/mesh) failed to find a mesh on channel %d.",
@@ -1670,9 +1683,20 @@ real_act_stage1_prepare (NMDevice *dev, NMActRequest *req)
/* If the user requested reassociation on the mesh device,
* go back to the the start of the association process.
*/
+ self->priv->channel_locked = FALSE;
+ self->priv->chans_tried = 0;
if (nm_act_request_get_user_requested (req)) {
- self->priv->step = self->priv->default_first_step;
- self->priv->channel = 1;
+ if (nm_act_request_get_mesh_start (req))
+ self->priv->step = nm_act_request_get_mesh_start (req);
+ else
+ self->priv->step = self->priv->default_first_step;
+
+ if (nm_act_request_get_mesh_channel (req)) {
+ self->priv->channel = nm_act_request_get_mesh_channel (req);
+ self->priv->channel_locked = TRUE;
+ } else {
+ self->priv->channel = get_random_channel ();
+ }
}
/* Stop being an MPP if we currently are one */
@@ -2045,9 +2069,6 @@ real_activation_failure_handler (NMDevice *dev,
NMDevice80211MeshOLPC * self = NM_DEVICE_802_11_MESH_OLPC (dev);
nm_device_set_active_link (dev, FALSE);
-
- self->priv->step++;
- self->priv->channel = 1;
}
diff --git a/src/nm-device-802-11-mesh-olpc.h b/src/nm-device-802-11-mesh-olpc.h
index 59f2ca0e26..d547b3b927 100644
--- a/src/nm-device-802-11-mesh-olpc.h
+++ b/src/nm-device-802-11-mesh-olpc.h
@@ -22,6 +22,7 @@
#ifndef NM_DEVICE_802_11_MESH_OLPC_H
#define NM_DEVICE_802_11_MESH_OLPC_H
+#include <glib.h>
#include <glib-object.h>
#include <net/ethernet.h>
@@ -74,4 +75,7 @@ void nm_get_anycast_addrs (struct NMData *data);
double nm_device_802_11_mesh_olpc_get_frequency (NMDevice80211MeshOLPC *self);
+guint32 nm_device_802_11_mesh_olpc_parse_mesh_step (const char * step_string,
+ guint32 fallback);
+
#endif /* NM_DEVICE_802_11_MESH_OLPC_H */