cregit-Linux how code gets into the kernel

Release 4.14 net/mac80211/mesh_pathtbl.c

Directory: net/mac80211
/*
 * Copyright (c) 2008, 2009 open80211s Ltd.
 * Author:     Luis Carlos Cobo <luisca@cozybit.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/etherdevice.h>
#include <linux/list.h>
#include <linux/random.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/string.h>
#include <net/mac80211.h>
#include "wme.h"
#include "ieee80211_i.h"
#include "mesh.h"

static void mesh_path_free_rcu(struct mesh_table *tbl, struct mesh_path *mpath);


static u32 mesh_table_hash(const void *addr, u32 len, u32 seed) { /* Use last four bytes of hw addr as hash index */ return jhash_1word(*(u32 *)(addr+2), seed); }

Contributors

PersonTokensPropCommitsCommitProp
Bob Copeland35100.00%1100.00%
Total35100.00%1100.00%

static const struct rhashtable_params mesh_rht_params = { .nelem_hint = 2, .automatic_shrinking = true, .key_len = ETH_ALEN, .key_offset = offsetof(struct mesh_path, dst), .head_offset = offsetof(struct mesh_path, rhash), .hashfn = mesh_table_hash, };
static inline bool mpath_expired(struct mesh_path *mpath) { return (mpath->flags & MESH_PATH_ACTIVE) && time_after(jiffies, mpath->exp_time) && !(mpath->flags & MESH_PATH_FIXED); }

Contributors

PersonTokensPropCommitsCommitProp
Johannes Berg3692.31%150.00%
Luis Carlos Cobo Rus37.69%150.00%
Total39100.00%2100.00%


static void mesh_path_rht_free(void *ptr, void *tblptr) { struct mesh_path *mpath = ptr; struct mesh_table *tbl = tblptr; mesh_path_free_rcu(tbl, mpath); }

Contributors

PersonTokensPropCommitsCommitProp
Bob Copeland2880.00%360.00%
Henning Rogge411.43%120.00%
Johannes Berg38.57%120.00%
Total35100.00%5100.00%


static struct mesh_table *mesh_table_alloc(void) { struct mesh_table *newtbl; newtbl = kmalloc(sizeof(struct mesh_table), GFP_ATOMIC); if (!newtbl) return NULL; INIT_HLIST_HEAD(&newtbl->known_gates); atomic_set(&newtbl->entries, 0); spin_lock_init(&newtbl->gates_lock); return newtbl; }

Contributors

PersonTokensPropCommitsCommitProp
Johannes Berg4975.38%125.00%
Bob Copeland1523.08%250.00%
Javier Cardona11.54%125.00%
Total65100.00%4100.00%


static void mesh_table_free(struct mesh_table *tbl) { rhashtable_free_and_destroy(&tbl->rhead, mesh_path_rht_free, tbl); kfree(tbl); }

Contributors

PersonTokensPropCommitsCommitProp
Javier Cardona2071.43%133.33%
Bob Copeland828.57%266.67%
Total28100.00%3100.00%

/** * * mesh_path_assign_nexthop - update mesh path next hop * * @mpath: mesh path to update * @sta: next hop to assign * * Locking: mpath->state_lock must be held when calling this function */
void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta) { struct sk_buff *skb; struct ieee80211_hdr *hdr; unsigned long flags; rcu_assign_pointer(mpath->next_hop, sta); spin_lock_irqsave(&mpath->frame_queue.lock, flags); skb_queue_walk(&mpath->frame_queue, skb) { hdr = (struct ieee80211_hdr *) skb->data; memcpy(hdr->addr1, sta->sta.addr, ETH_ALEN); memcpy(hdr->addr2, mpath->sdata->vif.addr, ETH_ALEN); ieee80211_mps_set_frame_flags(sta->sdata, sta, hdr); } spin_unlock_irqrestore(&mpath->frame_queue.lock, flags); }

Contributors

PersonTokensPropCommitsCommitProp
Bob Copeland9072.58%250.00%
Javier Cardona3427.42%250.00%
Total124100.00%4100.00%


static void prepare_for_gate(struct sk_buff *skb, char *dst_addr, struct mesh_path *gate_mpath) { struct ieee80211_hdr *hdr; struct ieee80211s_hdr *mshdr; int mesh_hdrlen, hdrlen; char *next_hop; hdr = (struct ieee80211_hdr *) skb->data; hdrlen = ieee80211_hdrlen(hdr->frame_control); mshdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); if (!(mshdr->flags & MESH_FLAGS_AE)) { /* size of the fixed part of the mesh header */ mesh_hdrlen = 6; /* make room for the two extended addresses */ skb_push(skb, 2 * ETH_ALEN); memmove(skb->data, hdr, hdrlen + mesh_hdrlen); hdr = (struct ieee80211_hdr *) skb->data; /* we preserve the previous mesh header and only add * the new addreses */ mshdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); mshdr->flags = MESH_FLAGS_AE_A5_A6; memcpy(mshdr->eaddr1, hdr->addr3, ETH_ALEN); memcpy(mshdr->eaddr2, hdr->addr4, ETH_ALEN); } /* update next hop */ hdr = (struct ieee80211_hdr *) skb->data; rcu_read_lock(); next_hop = rcu_dereference(gate_mpath->next_hop)->sta.addr; memcpy(hdr->addr1, next_hop, ETH_ALEN); rcu_read_unlock(); memcpy(hdr->addr2, gate_mpath->sdata->vif.addr, ETH_ALEN); memcpy(hdr->addr3, dst_addr, ETH_ALEN); }

Contributors

PersonTokensPropCommitsCommitProp
Bob Copeland18274.59%125.00%
Javier Cardona6225.41%375.00%
Total244100.00%4100.00%

/** * * mesh_path_move_to_queue - Move or copy frames from one mpath queue to another * * This function is used to transfer or copy frames from an unresolved mpath to * a gate mpath. The function also adds the Address Extension field and * updates the next hop. * * If a frame already has an Address Extension field, only the next hop and * destination addresses are updated. * * The gate mpath must be an active mpath with a valid mpath->next_hop. * * @mpath: An active mpath the frames will be sent to (i.e. the gate) * @from_mpath: The failed mpath * @copy: When true, copy all the frames to the new mpath queue. When false, * move them. */
static void mesh_path_move_to_queue(struct mesh_path *gate_mpath, struct mesh_path *from_mpath, bool copy) { struct sk_buff *skb, *fskb, *tmp; struct sk_buff_head failq; unsigned long flags; if (WARN_ON(gate_mpath == from_mpath)) return; if (WARN_ON(!gate_mpath->next_hop)) return; __skb_queue_head_init(&failq); spin_lock_irqsave(&from_mpath->frame_queue.lock, flags); skb_queue_splice_init(&from_mpath->frame_queue, &failq); spin_unlock_irqrestore(&from_mpath->frame_queue.lock, flags); skb_queue_walk_safe(&failq, fskb, tmp) { if (skb_queue_len(&gate_mpath->frame_queue) >= MESH_FRAME_QUEUE_LEN) { mpath_dbg(gate_mpath->sdata, "mpath queue full!\n"); break; } skb = skb_copy(fskb, GFP_ATOMIC); if (WARN_ON(!skb)) break; prepare_for_gate(skb, gate_mpath->dst, gate_mpath); skb_queue_tail(&gate_mpath->frame_queue, skb); if (copy) continue; __skb_unlink(fskb, &failq); kfree_skb(fskb); } mpath_dbg(gate_mpath->sdata, "Mpath queue for gate %pM has %d frames\n", gate_mpath->dst, skb_queue_len(&gate_mpath->frame_queue)); if (!copy) return; spin_lock_irqsave(&from_mpath->frame_queue.lock, flags); skb_queue_splice(&failq, &from_mpath->frame_queue); spin_unlock_irqrestore(&from_mpath->frame_queue.lock, flags); }

Contributors

PersonTokensPropCommitsCommitProp
Bob Copeland17970.75%112.50%
Javier Cardona4417.39%112.50%
Thomas Pedersen103.95%225.00%
Luis Carlos Cobo Rus83.16%112.50%
Johannes Berg62.37%225.00%
Marco Porsch62.37%112.50%
Total253100.00%8100.00%


static struct mesh_path *mpath_lookup(struct mesh_table *tbl, const u8 *dst, struct ieee80211_sub_if_data *sdata) { struct mesh_path *mpath; mpath = rhashtable_lookup_fast(&tbl->rhead, dst, mesh_rht_params); if (mpath && mpath_expired(mpath)) { spin_lock_bh(&mpath->state_lock); mpath->flags &= ~MESH_PATH_ACTIVE; spin_unlock_bh(&mpath->state_lock); } return mpath; }

Contributors

PersonTokensPropCommitsCommitProp
Bob Copeland4354.43%330.00%
Javier Cardona1518.99%220.00%
Li YanBo911.39%110.00%
Johannes Berg78.86%220.00%
Henning Rogge45.06%110.00%
Luis R. Rodriguez11.27%110.00%
Total79100.00%10100.00%

/** * mesh_path_lookup - look up a path in the mesh path table * @sdata: local subif * @dst: hardware address (ETH_ALEN length) of destination * * Returns: pointer to the mesh path structure, or NULL if not found * * Locking: must be called within a read rcu section. */
struct mesh_path * mesh_path_lookup(struct ieee80211_sub_if_data *sdata, const u8 *dst) { return mpath_lookup(sdata->u.mesh.mesh_paths, dst, sdata); }

Contributors

PersonTokensPropCommitsCommitProp
Bob Copeland2678.79%250.00%
Javier Cardona618.18%125.00%
Li YanBo13.03%125.00%
Total33100.00%4100.00%


struct mesh_path * mpp_path_lookup(struct ieee80211_sub_if_data *sdata, const u8 *dst) { return mpath_lookup(sdata->u.mesh.mpp_paths, dst, sdata); }

Contributors

PersonTokensPropCommitsCommitProp
Bob Copeland2266.67%133.33%
Javier Cardona824.24%133.33%
Li YanBo39.09%133.33%
Total33100.00%3100.00%


static struct mesh_path * __mesh_path_lookup_by_idx(struct mesh_table *tbl, int idx) { int i = 0, ret; struct mesh_path *mpath = NULL; struct rhashtable_iter iter; ret = rhashtable_walk_init(&tbl->rhead, &iter, GFP_ATOMIC); if (ret) return NULL; ret = rhashtable_walk_start(&iter); if (ret && ret != -EAGAIN) goto err; while ((mpath = rhashtable_walk_next(&iter))) { if (IS_ERR(mpath) && PTR_ERR(mpath) == -EAGAIN) continue; if (IS_ERR(mpath)) break; if (i++ == idx) break; } err: rhashtable_walk_stop(&iter); rhashtable_walk_exit(&iter); if (IS_ERR(mpath) || !mpath) return NULL; if (mpath_expired(mpath)) { spin_lock_bh(&mpath->state_lock); mpath->flags &= ~MESH_PATH_ACTIVE; spin_unlock_bh(&mpath->state_lock); } return mpath; }

Contributors

PersonTokensPropCommitsCommitProp
Bob Copeland15182.07%233.33%
Javier Cardona147.61%116.67%
Luis Carlos Cobo Rus115.98%233.33%
Li YanBo84.35%116.67%
Total184100.00%6100.00%

/** * mesh_path_lookup_by_idx - look up a path in the mesh path table by its index * @idx: index * @sdata: local subif, or NULL for all entries * * Returns: pointer to the mesh path structure, or NULL if not found. * * Locking: must be called within a read rcu section. */
struct mesh_path * mesh_path_lookup_by_idx(struct ieee80211_sub_if_data *sdata, int idx) { return __mesh_path_lookup_by_idx(sdata->u.mesh.mesh_paths, idx); }

Contributors

PersonTokensPropCommitsCommitProp
Bob Copeland2068.97%133.33%
Javier Cardona724.14%133.33%
Li YanBo26.90%133.33%
Total29100.00%3100.00%

/** * mpp_path_lookup_by_idx - look up a path in the proxy path table by its index * @idx: index * @sdata: local subif, or NULL for all entries * * Returns: pointer to the proxy path structure, or NULL if not found. * * Locking: must be called within a read rcu section. */
struct mesh_path * mpp_path_lookup_by_idx(struct ieee80211_sub_if_data *sdata, int idx) { return __mesh_path_lookup_by_idx(sdata->u.mesh.mpp_paths, idx); }

Contributors

PersonTokensPropCommitsCommitProp
Bob Copeland1344.83%133.33%
Javier Cardona1241.38%133.33%
Li YanBo413.79%133.33%
Total29100.00%3100.00%

/** * mesh_path_add_gate - add the given mpath to a mesh gate to our path table * @mpath: gate path to add to table */
int mesh_path_add_gate(struct mesh_path *mpath) { struct mesh_table *tbl; int err; rcu_read_lock(); tbl = mpath->sdata->u.mesh.mesh_paths; spin_lock_bh(&mpath->state_lock); if (mpath->is_gate) { err = -EEXIST; spin_unlock_bh(&mpath->state_lock); goto err_rcu; } mpath->is_gate = true; mpath->sdata->u.mesh.num_gates++; spin_lock(&tbl->gates_lock); hlist_add_head_rcu(&mpath->gate_list, &tbl->known_gates); spin_unlock(&tbl->gates_lock); spin_unlock_bh(&mpath->state_lock); mpath_dbg(mpath->sdata, "Mesh path: Recorded new gate: %pM. %d known gates\n", mpath->dst, mpath->sdata->u.mesh.num_gates); err = 0; err_rcu: rcu_read_unlock(); return err; }

Contributors

PersonTokensPropCommitsCommitProp
Bob Copeland154100.00%3100.00%
Total154100.00%3100.00%

/** * mesh_gate_del - remove a mesh gate from the list of known gates * @tbl: table which holds our list of known gates * @mpath: gate mpath */
static void mesh_gate_del(struct mesh_table *tbl, struct mesh_path *mpath) { lockdep_assert_held(&mpath->state_lock); if (!mpath->is_gate) return; mpath->is_gate = false; spin_lock_bh(&tbl->gates_lock); hlist_del_rcu(&mpath->gate_list); mpath->sdata->u.mesh.num_gates--; spin_unlock_bh(&tbl->gates_lock); mpath_dbg(mpath->sdata, "Mesh path: Deleted gate: %pM. %d known gates\n", mpath->dst, mpath->sdata->u.mesh.num_gates); }

Contributors

PersonTokensPropCommitsCommitProp
Bob Copeland8083.33%360.00%
Li YanBo1212.50%120.00%
Johannes Berg44.17%120.00%
Total96100.00%5100.00%

/** * mesh_gate_num - number of gates known to this interface * @sdata: subif data */
int mesh_gate_num(struct ieee80211_sub_if_data *sdata) { return sdata->u.mesh.num_gates; }

Contributors

PersonTokensPropCommitsCommitProp
Bob Copeland19100.00%1100.00%
Total19100.00%1100.00%


static struct mesh_path *mesh_path_new(struct ieee80211_sub_if_data *sdata, const u8 *dst, gfp_t gfp_flags) { struct mesh_path *new_mpath; new_mpath = kzalloc(sizeof(struct mesh_path), gfp_flags); if (!new_mpath) return NULL; memcpy(new_mpath->dst, dst, ETH_ALEN); eth_broadcast_addr(new_mpath->rann_snd_addr); new_mpath->is_root = false; new_mpath->sdata = sdata; new_mpath->flags = 0; skb_queue_head_init(&new_mpath->frame_queue); new_mpath->exp_time = jiffies; spin_lock_init(&new_mpath->state_lock); setup_timer(&new_mpath->timer, mesh_path_timer, (unsigned long) new_mpath); return new_mpath; }

Contributors

PersonTokensPropCommitsCommitProp
Bob Copeland7762.10%450.00%
Li YanBo2520.16%112.50%
Javier Cardona129.68%112.50%
Ondrej Lysonek97.26%112.50%
Johannes Berg10.81%112.50%
Total124100.00%8100.00%

/** * mesh_path_add - allocate and add a new path to the mesh path table * @dst: destination address of the path (ETH_ALEN length) * @sdata: local subif * * Returns: 0 on success * * State: the initial state of the new path is set to 0 */
struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst) { struct mesh_table *tbl; struct mesh_path *mpath, *new_mpath; int ret; if (ether_addr_equal(dst, sdata->vif.addr)) /* never add ourselves as neighbours */ return ERR_PTR(-ENOTSUPP); if (is_multicast_ether_addr(dst)) return ERR_PTR(-ENOTSUPP); if (atomic_add_unless(&sdata->u.mesh.mpaths, 1, MESH_MAX_MPATHS) == 0) return ERR_PTR(-ENOSPC); new_mpath = mesh_path_new(sdata, dst, GFP_ATOMIC); if (!new_mpath) return ERR_PTR(-ENOMEM); tbl = sdata->u.mesh.mesh_paths; do { ret = rhashtable_lookup_insert_fast(&tbl->rhead, &new_mpath->rhash, mesh_rht_params); if (ret == -EEXIST) mpath = rhashtable_lookup_fast(&tbl->rhead, dst, mesh_rht_params); } while (unlikely(ret == -EEXIST && !mpath)); if (ret && ret != -EEXIST) return ERR_PTR(ret); /* At this point either new_mpath was added, or we found a * matching entry already in the table; in the latter case * free the unnecessary new entry. */ if (ret == -EEXIST) { kfree(new_mpath); new_mpath = mpath; } sdata->u.mesh.mesh_paths_generation++; return new_mpath; }

Contributors

PersonTokensPropCommitsCommitProp
Bob Copeland17676.86%222.22%
Javier Cardona2611.35%333.33%
Li YanBo156.55%111.11%
Luis Carlos Cobo Rus73.06%111.11%
Johannes Berg52.18%222.22%
Total229100.00%9100.00%


int mpp_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst, const u8 *mpp) { struct mesh_table *tbl; struct mesh_path *new_mpath; int ret; if (ether_addr_equal(dst, sdata->vif.addr)) /* never add ourselves as neighbours */ return -ENOTSUPP; if (is_multicast_ether_addr(dst)) return -ENOTSUPP; new_mpath = mesh_path_new(sdata, dst, GFP_ATOMIC); if (!new_mpath) return -ENOMEM; memcpy(new_mpath->mpp, mpp, ETH_ALEN); tbl = sdata->u.mesh.mpp_paths; ret = rhashtable_lookup_insert_fast(&tbl->rhead, &new_mpath->rhash, mesh_rht_params); sdata->u.mesh.mpp_paths_generation++; return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Luis Carlos Cobo Rus5138.64%17.69%
Bob Copeland3627.27%323.08%
Johannes Berg1712.88%430.77%
Li YanBo1511.36%17.69%
Pavel Emelyanov64.55%17.69%
Jasper Bryant-Greene43.03%17.69%
Javier Cardona21.52%17.69%
Joe Perches10.76%17.69%
Total132100.00%13100.00%

/** * mesh_plink_broken - deactivates paths and sends perr when a link breaks * * @sta: broken peer link * * This function must be called from the rate control algorithm if enough * delivery errors suggest that a peer link is no longer usable. */
void mesh_plink_broken(struct sta_info *sta) { struct ieee80211_sub_if_data *sdata = sta->sdata; struct mesh_table *tbl = sdata->u.mesh.mesh_paths; static const u8 bcast[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; struct mesh_path *mpath; struct rhashtable_iter iter; int ret; ret = rhashtable_walk_init(&tbl->rhead, &iter, GFP_ATOMIC); if (ret) return; ret = rhashtable_walk_start(&iter); if (ret && ret != -EAGAIN) goto out; while ((mpath = rhashtable_walk_next(&iter))) { if (IS_ERR(mpath) && PTR_ERR(mpath) == -EAGAIN) continue; if (IS_ERR(mpath)) break; if (rcu_access_pointer(mpath->next_hop) == sta && mpath->flags & MESH_PATH_ACTIVE && !(mpath->flags & MESH_PATH_FIXED)) { spin_lock_bh(&mpath->state_lock); mpath->flags &= ~MESH_PATH_ACTIVE; ++mpath->sn; spin_unlock_bh(&mpath->state_lock); mesh_path_error_tx(sdata, sdata->u.mesh.mshcfg.element_ttl, mpath->dst, mpath->sn, WLAN_REASON_MESH_PATH_DEST_UNREACHABLE, bcast); } } out: rhashtable_walk_stop(&iter); rhashtable_walk_exit(&iter); }

Contributors

PersonTokensPropCommitsCommitProp
Bob Copeland9539.42%215.38%
Luis Carlos Cobo Rus7932.78%17.69%
Johannes Berg3614.94%323.08%
Javier Cardona2510.37%323.08%
Rui Paulo41.66%215.38%
Chun-Yeow Yeoh10.41%17.69%
Andreea-Cristina Bernat10.41%17.69%
Total241100.00%13100.00%


static void mesh_path_free_rcu(struct mesh_table *tbl, struct mesh_path *mpath) { struct ieee80211_sub_if_data *sdata = mpath->sdata; spin_lock_bh(&mpath->state_lock); mpath->flags |= MESH_PATH_RESOLVING | MESH_PATH_DELETED; mesh_gate_del(tbl, mpath); spin_unlock_bh(&mpath->state_lock); del_timer_sync(&mpath->timer); atomic_dec(&sdata->u.mesh.mpaths); atomic_dec(&tbl->entries); kfree_rcu(mpath, rcu); }

Contributors

PersonTokensPropCommitsCommitProp
Javier Cardona5257.14%120.00%
Johannes Berg2021.98%120.00%
Bob Copeland1920.88%360.00%
Total91100.00%5100.00%


static void __mesh_path_del(struct mesh_table *tbl, struct mesh_path *mpath) { rhashtable_remove_fast(&tbl->rhead, &mpath->rhash, mesh_rht_params); mesh_path_free_rcu(tbl, mpath); }

Contributors

PersonTokensPropCommitsCommitProp
Bob Copeland3797.37%150.00%
Javier Cardona12.63%150.00%
Total38100.00%2100.00%

/** * mesh_path_flush_by_nexthop - Deletes mesh paths if their next hop matches * * @sta: mesh peer to match * * RCU notes: this function is called when a mesh plink transitions from * PLINK_ESTAB to any other state, since PLINK_ESTAB state is the only one that * allows path creation. This will happen before the sta can be freed (because * sta_info_destroy() calls this) so any reader in a rcu read block will be * protected against the plink disappearing. */
void mesh_path_flush_by_nexthop(struct sta_info *sta) { struct ieee80211_sub_if_data *sdata = sta->sdata; struct mesh_table *tbl = sdata->u.mesh.mesh_paths; struct mesh_path *mpath; struct rhashtable_iter iter; int ret; ret = rhashtable_walk_init(&tbl->rhead, &iter, GFP_ATOMIC); if (ret) return; ret = rhashtable_walk_start(&iter); if (ret && ret != -EAGAIN) goto out; while ((mpath = rhashtable_walk_next(&iter))) { if (IS_ERR(mpath) && PTR_ERR(mpath) == -EAGAIN) continue; if (IS_ERR(mpath)) break; if (rcu_access_pointer(mpath->next_hop) == sta) __mesh_path_del(tbl, mpath); } out: rhashtable_walk_stop(&iter); rhashtable_walk_exit(&iter); }

Contributors

PersonTokensPropCommitsCommitProp
Bob Copeland9461.04%225.00%
Luis Carlos Cobo Rus4025.97%225.00%
Johannes Berg106.49%112.50%
Javier Cardona95.84%225.00%
Andreea-Cristina Bernat10.65%112.50%
Total154100.00%8100.00%


static void mpp_flush_by_proxy(struct ieee80211_sub_if_data *sdata, const u8 *proxy) { struct mesh_table *tbl = sdata->u.mesh.mpp_paths; struct mesh_path *mpath; struct rhashtable_iter iter; int ret; ret = rhashtable_walk_init(&tbl->rhead, &iter, GFP_ATOMIC); if (ret) return; ret = rhashtable_walk_start(&iter); if (ret && ret != -EAGAIN) goto out; while ((mpath = rhashtable_walk_next(&iter))) { if (IS_ERR(mpath) && PTR_ERR(mpath) == -EAGAIN) continue; if (IS_ERR(mpath)) break; if (ether_addr_equal(mpath->mpp, proxy)) __mesh_path_del(tbl, mpath); } out: rhashtable_walk_stop(&iter); rhashtable_walk_exit(&iter); }

Contributors

PersonTokensPropCommitsCommitProp
Bob Copeland8858.28%266.67%
Henning Rogge6341.72%133.33%
Total151100.00%3100.00%


static void table_flush_by_iface(struct mesh_table *tbl) { struct mesh_path *mpath; struct rhashtable_iter iter; int ret; ret = rhashtable_walk_init(&tbl->rhead, &iter, GFP_ATOMIC); if (ret) return; ret = rhashtable_walk_start(&iter); if (ret && ret != -EAGAIN) goto out; while ((mpath = rhashtable_walk_next(&iter))) { if (IS_ERR(mpath) && PTR_ERR(mpath) == -EAGAIN) continue; if (IS_ERR(mpath)) break; __mesh_path_del(tbl, mpath); } out: rhashtable_walk_stop(&iter); rhashtable_walk_exit(&iter); }

Contributors

PersonTokensPropCommitsCommitProp
Bob Copeland8267.21%116.67%
Luis Carlos Cobo Rus2419.67%116.67%
Javier Cardona1310.66%350.00%
Johannes Berg32.46%116.67%
Total122100.00%6100.00%

/** * mesh_path_flush_by_iface - Deletes all mesh paths associated with a given iface * * This function deletes both mesh paths as well as mesh portal paths. * * @sdata: interface data to match * */
void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata) { table_flush_by_iface(sdata->u.mesh.mesh_paths); table_flush_by_iface(sdata->u.mesh.mpp_paths); }

Contributors

PersonTokensPropCommitsCommitProp
Bob Copeland1650.00%233.33%
Luis Carlos Cobo Rus1134.38%233.33%
Javier Cardona515.62%233.33%
Total32100.00%6100.00%

/** * table_path_del - delete a path from the mesh or mpp table * * @tbl: mesh or mpp path table * @sdata: local subif * @addr: dst address (ETH_ALEN length) * * Returns: 0 if successful */
static int table_path_del(struct mesh_table *tbl, struct ieee80211_sub_if_data *sdata, const u8 *addr) { struct mesh_path *mpath; rcu_read_lock(); mpath = rhashtable_lookup_fast(&tbl->rhead, addr, mesh_rht_params); if (!mpath) { rcu_read_unlock(); return -ENXIO; } __mesh_path_del(tbl, mpath); rcu_read_unlock(); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Luis Carlos Cobo Rus3042.86%114.29%
Bob Copeland1825.71%114.29%
Henning Rogge1420.00%228.57%
Johannes Berg68.57%228.57%
Jasper Bryant-Greene22.86%114.29%
Total70100.00%7100.00%

/** * mesh_path_del - delete a mesh path from the table * * @addr: dst address (ETH_ALEN length) * @sdata: local subif * * Returns: 0 if successful */
int mesh_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr) { int err; /* flush relevant mpp entries first */ mpp_flush_by_proxy(sdata, addr); err = table_path_del(sdata->u.mesh.mesh_paths, sdata, addr); sdata->u.mesh.mesh_paths_generation++; return err; }

Contributors

PersonTokensPropCommitsCommitProp
Henning Rogge3563.64%250.00%
Bob Copeland2036.36%250.00%
Total55100.00%4100.00%

/** * mesh_path_tx_pending - sends pending frames in a mesh path queue * * @mpath: mesh path to activate * * Locking: the state_lock of the mpath structure must NOT be held when calling * this function. */
void mesh_path_tx_pending(struct mesh_path *mpath) { if (mpath->flags & MESH_PATH_ACTIVE) ieee80211_add_pending_skbs(mpath->sdata->local, &mpath->frame_queue); }

Contributors

PersonTokensPropCommitsCommitProp
Luis Carlos Cobo Rus2062.50%150.00%
Javier Cardona1237.50%150.00%
Total32100.00%2100.00%

/** * mesh_path_send_to_gates - sends pending frames to all known mesh gates * * @mpath: mesh path whose queue will be emptied * * If there is only one gate, the frames are transferred from the failed mpath * queue to that gate's queue. If there are more than one gates, the frames * are copied from each gate to the next. After frames are copied, the * mpath queues are emptied onto the transmission queue. */
int mesh_path_send_to_gates(struct mesh_path *mpath) { struct ieee80211_sub_if_data *sdata = mpath->sdata; struct mesh_table *tbl; struct mesh_path *from_mpath = mpath; struct mesh_path *gate; bool copy = false; tbl = sdata->u.mesh.mesh_paths; rcu_read_lock(); hlist_for_each_entry_rcu(gate, &tbl->known_gates, gate_list) { if (gate->flags & MESH_PATH_ACTIVE) { mpath_dbg(sdata, "Forwarding to %pM\n", gate->dst); mesh_path_move_to_queue(gate, from_mpath, copy); from_mpath = gate; copy = true; } else { mpath_dbg(sdata, "Not forwarding to %pM (flags %#x)\n", gate->dst, gate->flags); } } hlist_for_each_entry_rcu(gate, &tbl->known_gates, gate_list) { mpath_dbg(sdata, "Sending to %pM\n", gate->dst); mesh_path_tx_pending(gate); } rcu_read_unlock(); return (from_mpath == mpath) ? -EHOSTUNREACH : 0; }

Contributors

PersonTokensPropCommitsCommitProp
Javier Cardona13684.47%114.29%
Bob Copeland1710.56%457.14%
Johannes Berg84.97%228.57%
Total161100.00%7100.00%

/** * mesh_path_discard_frame - discard a frame whose path could not be resolved * * @skb: frame to discard * @sdata: network subif the frame was to be sent through * * Locking: the function must me called within a rcu_read_lock region */
void mesh_path_discard_frame(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) { kfree_skb(skb); sdata->u.mesh.mshstats.dropped_frames_no_route++; }

Contributors

PersonTokensPropCommitsCommitProp
Luis Carlos Cobo Rus2477.42%125.00%
Johannes Berg516.13%250.00%
Jasper Bryant-Greene26.45%125.00%
Total31100.00%4100.00%

/** * mesh_path_flush_pending - free the pending queue of a mesh path * * @mpath: mesh path whose queue has to be freed * * Locking: the function must me called within a rcu_read_lock region */
void mesh_path_flush_pending(struct mesh_path *mpath) { struct sk_buff *skb; while ((skb = skb_dequeue(&mpath->frame_queue)) != NULL) mesh_path_discard_frame(mpath->sdata, skb); }

Contributors

PersonTokensPropCommitsCommitProp
Luis Carlos Cobo Rus3587.50%125.00%
Javier Cardona25.00%125.00%
Johannes Berg25.00%125.00%
Jasper Bryant-Greene12.50%125.00%
Total40100.00%4100.00%

/** * mesh_path_fix_nexthop - force a specific next hop for a mesh path * * @mpath: the mesh path to modify * @next_hop: the next hop to force * * Locking: this function must be called holding mpath->state_lock */
void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop) { spin_lock_bh(&mpath->state_lock); mesh_path_assign_nexthop(mpath, next_hop); mpath->sn = 0xffff; mpath->metric = 0; mpath->hop_count = 0; mpath->exp_time = 0; mpath->flags = MESH_PATH_FIXED | MESH_PATH_SN_VALID; mesh_path_activate(mpath); spin_unlock_bh(&mpath->state_lock); ewma_mesh_fail_avg_init(&next_hop->mesh->fail_avg); /* init it at a low value - 0 start is tricky */ ewma_mesh_fail_avg_add(&next_hop->mesh->fail_avg, 1); mesh_path_tx_pending(mpath); }

Contributors

PersonTokensPropCommitsCommitProp
Luis Carlos Cobo Rus7673.79%125.00%
Rajkumar Manoharan2322.33%125.00%
Thomas Pedersen32.91%125.00%
Rui Paulo10.97%125.00%
Total103100.00%4100.00%


int mesh_pathtbl_init(struct ieee80211_sub_if_data *sdata) { struct mesh_table *tbl_path, *tbl_mpp; int ret; tbl_path = mesh_table_alloc(); if (!tbl_path) return -ENOMEM; tbl_mpp = mesh_table_alloc(); if (!tbl_mpp) { ret = -ENOMEM; goto free_path; } rhashtable_init(&tbl_path->rhead, &mesh_rht_params); rhashtable_init(&tbl_mpp->rhead, &mesh_rht_params); sdata->u.mesh.mesh_paths = tbl_path; sdata->u.mesh.mpp_paths = tbl_mpp; return 0; free_path: mesh_table_free(tbl_path); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Bob Copeland4742.73%228.57%
Dan Carpenter2421.82%114.29%
Luis Carlos Cobo Rus1513.64%114.29%
Johannes Berg1513.64%114.29%
Javier Cardona65.45%114.29%
Li YanBo32.73%114.29%
Total110100.00%7100.00%


static void mesh_path_tbl_expire(struct ieee80211_sub_if_data *sdata, struct mesh_table *tbl) { struct mesh_path *mpath; struct rhashtable_iter iter; int ret; ret = rhashtable_walk_init(&tbl->rhead, &iter, GFP_KERNEL); if (ret) return; ret = rhashtable_walk_start(&iter); if (ret && ret != -EAGAIN) goto out; while ((mpath = rhashtable_walk_next(&iter))) { if (IS_ERR(mpath) && PTR_ERR(mpath) == -EAGAIN) continue; if (IS_ERR(mpath)) break; if ((!(mpath->flags & MESH_PATH_RESOLVING)) && (!(mpath->flags & MESH_PATH_FIXED)) && time_after(jiffies, mpath->exp_time + MESH_PATH_EXPIRE)) __mesh_path_del(tbl, mpath); } out: rhashtable_walk_stop(&iter); rhashtable_walk_exit(&iter); }

Contributors

PersonTokensPropCommitsCommitProp
Bob Copeland8753.70%233.33%
Luis Carlos Cobo Rus6238.27%116.67%
Henning Rogge63.70%116.67%
Johannes Berg53.09%116.67%
Jasper Bryant-Greene21.23%116.67%
Total162100.00%6100.00%


void mesh_path_expire(struct ieee80211_sub_if_data *sdata) { mesh_path_tbl_expire(sdata, sdata->u.mesh.mesh_paths); mesh_path_tbl_expire(sdata, sdata->u.mesh.mpp_paths); }

Contributors

PersonTokensPropCommitsCommitProp
Bob Copeland2569.44%150.00%
Henning Rogge1130.56%150.00%
Total36100.00%2100.00%


void mesh_pathtbl_unregister(struct ieee80211_sub_if_data *sdata) { mesh_table_free(sdata->u.mesh.mesh_paths); mesh_table_free(sdata->u.mesh.mpp_paths); }

Contributors

PersonTokensPropCommitsCommitProp
Bob Copeland1650.00%133.33%
Luis Carlos Cobo Rus1134.38%133.33%
Li YanBo515.62%133.33%
Total32100.00%3100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
Bob Copeland209055.88%710.94%
Luis Carlos Cobo Rus53414.28%34.69%
Javier Cardona52814.12%1523.44%
Johannes Berg2386.36%1421.88%
Henning Rogge1383.69%46.25%
Li YanBo1022.73%11.56%
Dan Carpenter240.64%11.56%
Rajkumar Manoharan230.61%11.56%
Thomas Pedersen140.37%46.25%
Jasper Bryant-Greene110.29%11.56%
Ondrej Lysonek90.24%11.56%
Pavel Emelyanov60.16%11.56%
Rui Paulo60.16%34.69%
Marco Porsch60.16%11.56%
Tejun Heo30.08%11.56%
Andreea-Cristina Bernat20.05%11.56%
Ben Hutchings20.05%11.56%
Luis R. Rodriguez10.03%11.56%
Chun-Yeow Yeoh10.03%11.56%
Joe Perches10.03%11.56%
Lucas De Marchi10.03%11.56%
Total3740100.00%64100.00%
Directory: net/mac80211
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.