/** * mesh_path_start_discovery - launch a path discovery from the PREQ queue * * @sdata: local mesh subif */ 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; struct mesh_path *mpath; u8 ttl, target_flags = 0; const u8 *da; u32 lifetime; spin_lock_bh(&ifmsh->mesh_preq_queue_lock); if (!ifmsh->preq_queue_len || time_before(jiffies, ifmsh->last_preq + min_preq_int_jiff(sdata))) { spin_unlock_bh(&ifmsh->mesh_preq_queue_lock); return; } preq_node = list_first_entry(&ifmsh->preq_queue.list, struct mesh_preq_queue, list); list_del(&preq_node->list); --ifmsh->preq_queue_len; spin_unlock_bh(&ifmsh->mesh_preq_queue_lock); rcu_read_lock(); mpath = mesh_path_lookup(sdata, preq_node->dst); if (!mpath) goto enddiscovery; spin_lock_bh(&mpath->state_lock); if (mpath->flags & (MESH_PATH_DELETED | MESH_PATH_FIXED)) { spin_unlock_bh(&mpath->state_lock); goto enddiscovery; } mpath->flags &= ~MESH_PATH_REQ_QUEUED; if (preq_node->flags & PREQ_Q_F_START) { if (mpath->flags & MESH_PATH_RESOLVING) { spin_unlock_bh(&mpath->state_lock); goto enddiscovery; } else { mpath->flags &= ~MESH_PATH_RESOLVED; mpath->flags |= MESH_PATH_RESOLVING; mpath->discovery_retries = 0; mpath->discovery_timeout = disc_timeout_jiff(sdata); } } else if (!(mpath->flags & MESH_PATH_RESOLVING) || mpath->flags & MESH_PATH_RESOLVED) { mpath->flags &= ~MESH_PATH_RESOLVING; spin_unlock_bh(&mpath->state_lock); goto enddiscovery; } ifmsh->last_preq = jiffies; if (time_after(jiffies, ifmsh->last_sn_update + net_traversal_jiffies(sdata)) || time_before(jiffies, ifmsh->last_sn_update)) { ++ifmsh->sn; sdata->u.mesh.last_sn_update = jiffies; } lifetime = default_lifetime(sdata); ttl = sdata->u.mesh.mshcfg.element_ttl; if (ttl == 0) { sdata->u.mesh.mshstats.dropped_frames_ttl++; spin_unlock_bh(&mpath->state_lock); goto enddiscovery; } if (preq_node->flags & PREQ_Q_F_REFRESH) target_flags |= IEEE80211_PREQ_TO_FLAG; else target_flags &= ~IEEE80211_PREQ_TO_FLAG; spin_unlock_bh(&mpath->state_lock); da = (mpath->is_root) ? mpath->rann_snd_addr : broadcast_addr; mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->vif.addr, ifmsh->sn, target_flags, mpath->dst, mpath->sn, da, 0, ttl, lifetime, 0, ifmsh->preq_id++, sdata); mod_timer(&mpath->timer, jiffies + mpath->discovery_timeout); enddiscovery: rcu_read_unlock(); kfree(preq_node); }
/** * mesh_path_start_discovery - launch a path discovery from the PREQ queue * * @sdata: local mesh subif */ 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; struct mesh_path *mpath; u8 ttl, dst_flags; u32 lifetime; spin_lock_bh(&ifmsh->mesh_preq_queue_lock); if (!ifmsh->preq_queue_len || time_before(jiffies, ifmsh->last_preq + min_preq_int_jiff(sdata))) { spin_unlock_bh(&ifmsh->mesh_preq_queue_lock); return; } preq_node = list_first_entry(&ifmsh->preq_queue.list, struct mesh_preq_queue, list); list_del(&preq_node->list); --ifmsh->preq_queue_len; spin_unlock_bh(&ifmsh->mesh_preq_queue_lock); rcu_read_lock(); mpath = mesh_path_lookup(preq_node->dst, sdata); if (!mpath) goto enddiscovery; spin_lock_bh(&mpath->state_lock); if (preq_node->flags & PREQ_Q_F_START) { if (mpath->flags & MESH_PATH_RESOLVING) { spin_unlock_bh(&mpath->state_lock); goto enddiscovery; } else { mpath->flags &= ~MESH_PATH_RESOLVED; mpath->flags |= MESH_PATH_RESOLVING; mpath->discovery_retries = 0; mpath->discovery_timeout = disc_timeout_jiff(sdata); } } else if (!(mpath->flags & MESH_PATH_RESOLVING) || mpath->flags & MESH_PATH_RESOLVED) { mpath->flags &= ~MESH_PATH_RESOLVING; spin_unlock_bh(&mpath->state_lock); goto enddiscovery; } ifmsh->last_preq = jiffies; if (time_after(jiffies, ifmsh->last_dsn_update + net_traversal_jiffies(sdata)) || time_before(jiffies, ifmsh->last_dsn_update)) { ++ifmsh->dsn; sdata->u.mesh.last_dsn_update = jiffies; } lifetime = default_lifetime(sdata); ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; if (ttl == 0) { sdata->u.mesh.mshstats.dropped_frames_ttl++; spin_unlock_bh(&mpath->state_lock); goto enddiscovery; } if (preq_node->flags & PREQ_Q_F_REFRESH) dst_flags = MP_F_DO; else dst_flags = MP_F_RF; spin_unlock_bh(&mpath->state_lock); mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->dev->dev_addr, cpu_to_le32(ifmsh->dsn), dst_flags, mpath->dst, cpu_to_le32(mpath->dsn), sdata->dev->broadcast, 0, ttl, cpu_to_le32(lifetime), 0, cpu_to_le32(ifmsh->preq_id++), sdata); mod_timer(&mpath->timer, jiffies + mpath->discovery_timeout); enddiscovery: rcu_read_unlock(); kfree(preq_node); }
int csm_update_service(csm_service_list *services, csm_service *s, csm_ctx *ctx, int validate) { if (validate) CHECK(csm_validate_fields(ctx, s), "Service doesn't validate"); // assert(s->lifetime); long lifetime = s->lifetime; // check if service is attached to service_list CHECK(co_list_contains(services->services, (co_obj_t*)container_of(s, co_service_t, service)), "Cannot update service not in service list"); // detach s->fields from s and attach to services->service_fields if (!co_list_contains(services->service_fields, s->fields)) { co_obj_t *fields = s->fields; hattach(fields, NULL); CHECK(co_list_append(services->service_fields, fields), "Failed to add service fields to service list"); } /* Create or verify signature */ if (s->signature) CHECK(csm_verify_signature(s),"Invalid signature"); else CHECK(csm_create_signature(s),"Failed to create signature"); /* Set expiration timer on the service */ #ifdef USE_UCI long def_lifetime = default_lifetime(); if (lifetime == 0 || (def_lifetime < lifetime && def_lifetime > 0)) lifetime = def_lifetime; #endif if (lifetime > 0) { struct timeval tv; avahi_elapse_time(&tv, 1000*lifetime, 0); time_t current_time = time(NULL); // create expiration event for service s->timeout = avahi_simple_poll_get(simple_poll)->timeout_new(avahi_simple_poll_get(simple_poll), &tv, _csm_expire_service, s); /* Convert lifetime period into timestamp */ if (current_time != ((time_t)-1)) { struct tm *timestr = localtime(¤t_time); timestr->tm_sec += lifetime; current_time = mktime(timestr); char *c_time_string = ctime(¤t_time); if (c_time_string) { c_time_string[strlen(c_time_string)-1] = '\0'; /* ctime adds \n to end of time string; remove it */ s->expiration = h_strdup(c_time_string); CHECK_MEM(s->expiration); service_attach(s->expiration, s); } } } // finalize service by running update handlers csm_services_commit(services); return 1; error: return 0; }