diff options
author | Dan Williams <dcbw@redhat.com> | 2007-09-08 13:42:29 +0000 |
---|---|---|
committer | Dan Williams <dcbw@redhat.com> | 2007-09-08 13:42:29 +0000 |
commit | b7897b7b58d5c89a677230f17a08f6f06a307634 (patch) | |
tree | 58c3e34ba646b9d67a2f32a640beaee6e35f2f4b | |
parent | 30e6b041f7abdc2b3de49536ecdc23b3850d78fe (diff) | |
download | NetworkManager-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-- | ChangeLog | 19 | ||||
-rw-r--r-- | src/nm-activation-request.c | 32 | ||||
-rw-r--r-- | src/nm-activation-request.h | 5 | ||||
-rw-r--r-- | src/nm-dbus-nm.c | 55 | ||||
-rw-r--r-- | src/nm-device-802-11-mesh-olpc.c | 263 | ||||
-rw-r--r-- | src/nm-device-802-11-mesh-olpc.h | 4 |
6 files changed, 254 insertions, 124 deletions
@@ -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 */ |