cregit-Linux how code gets into the kernel

Release 4.11 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 Copeland13956.97%111.11%
Javier Cardona8635.25%444.44%
Johannes Berg93.69%222.22%
Luis Carlos Cobo Rus93.69%111.11%
Thomas Pedersen10.41%111.11%
Total244100.00%9100.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 Copeland18773.91%337.50%
Li YanBo2811.07%112.50%
Henning Rogge197.51%112.50%
Javier Cardona176.72%112.50%
Johannes Berg20.79%225.00%
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 Copeland5164.56%233.33%
Luis Carlos Cobo Rus1012.66%233.33%
Javier Cardona1012.66%116.67%
Li YanBo810.13%116.67%
Total79100.00%6100.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 Copeland2369.70%133.33%
Javier Cardona824.24%133.33%
Li YanBo26.06%133.33%
Total33100.00%3100.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 Copeland1751.52%133.33%
Javier Cardona1236.36%133.33%
Li YanBo412.12%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 Copeland184100.00%2100.00%
Total184100.00%2100.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 Copeland2172.41%250.00%
Li YanBo724.14%125.00%
Johannes Berg13.45%125.00%
Total29100.00%4100.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 Copeland2275.86%133.33%
Javier Cardona620.69%133.33%
Li YanBo13.45%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 Copeland13084.42%457.14%
Li YanBo2214.29%114.29%
Johannes Berg21.30%228.57%
Total154100.00%7100.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 Copeland6365.62%342.86%
Li YanBo2020.83%114.29%
Javier Cardona1111.46%114.29%
Johannes Berg22.08%228.57%
Total96100.00%7100.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%2100.00%
Total19100.00%2100.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->timer.data = (unsigned long) new_mpath; new_mpath->timer.function = mesh_path_timer; new_mpath->exp_time = jiffies; spin_lock_init(&new_mpath->state_lock); init_timer(&new_mpath->timer); return new_mpath; }

Contributors

PersonTokensPropCommitsCommitProp
Bob Copeland12088.24%360.00%
Javier Cardona107.35%120.00%
Johannes Berg64.41%120.00%
Total136100.00%5100.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 Copeland18078.60%225.00%
Javier Cardona2410.48%337.50%
Li YanBo166.99%112.50%
Luis Carlos Cobo Rus73.06%112.50%
Johannes Berg20.87%112.50%
Total229100.00%8100.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%18.33%
Bob Copeland3728.03%325.00%
Johannes Berg1712.88%325.00%
Li YanBo1511.36%18.33%
Pavel Emelyanov64.55%18.33%
Jasper Bryant-Greene43.03%18.33%
Joe Perches10.76%18.33%
Javier Cardona10.76%18.33%
Total132100.00%12100.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 Copeland9662.34%222.22%
Luis Carlos Cobo Rus3824.68%222.22%
Johannes Berg106.49%111.11%
Javier Cardona95.84%333.33%
Andreea-Cristina Bernat10.65%111.11%
Total154100.00%9100.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 Copeland8872.13%120.00%
Luis Carlos Cobo Rus2016.39%120.00%
Javier Cardona129.84%240.00%
Johannes Berg21.64%120.00%
Total122100.00%5100.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