cregit-Linux how code gets into the kernel

Release 4.8 net/batman-adv/send.c

Directory: net/batman-adv
/* Copyright (C) 2007-2016  B.A.T.M.A.N. contributors:
 *
 * Marek Lindner, Simon Wunderlich
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of version 2 of the GNU General Public
 * License as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 */

#include "send.h"
#include "main.h"

#include <linux/atomic.h>
#include <linux/byteorder/generic.h>
#include <linux/errno.h>
#include <linux/etherdevice.h>
#include <linux/fs.h>
#include <linux/if.h>
#include <linux/if_ether.h>
#include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/kref.h>
#include <linux/list.h>
#include <linux/netdevice.h>
#include <linux/printk.h>
#include <linux/rculist.h>
#include <linux/rcupdate.h>
#include <linux/skbuff.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/stddef.h>
#include <linux/workqueue.h>

#include "distributed-arp-table.h"
#include "fragmentation.h"
#include "gateway_client.h"
#include "hard-interface.h"
#include "log.h"
#include "network-coding.h"
#include "originator.h"
#include "routing.h"
#include "soft-interface.h"
#include "translation-table.h"

static void batadv_send_outstanding_bcast_packet(struct work_struct *work);

/**
 * batadv_send_skb_packet - send an already prepared packet
 * @skb: the packet to send
 * @hard_iface: the interface to use to send the broadcast packet
 * @dst_addr: the payload destination
 *
 * Send out an already prepared packet to the given neighbor or broadcast it
 * using the specified interface. Either hard_iface or neigh_node must be not
 * NULL.
 * If neigh_node is NULL, then the packet is broadcasted using hard_iface,
 * otherwise it is sent as unicast to the given neighbor.
 *
 * Return: NET_TX_DROP in case of error or the result of dev_queue_xmit(skb)
 * otherwise
 */

int batadv_send_skb_packet(struct sk_buff *skb, struct batadv_hard_iface *hard_iface, const u8 *dst_addr) { struct batadv_priv *bat_priv; struct ethhdr *ethhdr; int ret; bat_priv = netdev_priv(hard_iface->soft_iface); if (hard_iface->if_status != BATADV_IF_ACTIVE) goto send_skb_err; if (unlikely(!hard_iface->net_dev)) goto send_skb_err; if (!(hard_iface->net_dev->flags & IFF_UP)) { pr_warn("Interface %s is not up - can't send packet via that interface!\n", hard_iface->net_dev->name); goto send_skb_err; } /* push to the ethernet header. */ if (batadv_skb_head_push(skb, ETH_HLEN) < 0) goto send_skb_err; skb_reset_mac_header(skb); ethhdr = eth_hdr(skb); ether_addr_copy(ethhdr->h_source, hard_iface->net_dev->dev_addr); ether_addr_copy(ethhdr->h_dest, dst_addr); ethhdr->h_proto = htons(ETH_P_BATMAN); skb_set_network_header(skb, ETH_HLEN); skb->protocol = htons(ETH_P_BATMAN); skb->dev = hard_iface->net_dev; /* Save a clone of the skb to use when decoding coded packets */ batadv_nc_skb_store_for_decoding(bat_priv, skb); /* dev_queue_xmit() returns a negative result on error. However on * congestion and traffic shaping, it drops and returns NET_XMIT_DROP * (which is > 0). This will not be treated as an error. * * a negative value cannot be returned because it could be interepreted * as not consumed skb by callers of batadv_send_skb_to_orig. */ ret = dev_queue_xmit(skb); if (ret < 0) ret = NET_XMIT_DROP; return ret; send_skb_err: kfree_skb(skb); return NET_XMIT_DROP; }

Contributors

PersonTokensPropCommitsCommitProp
sven eckelmannsven eckelmann16074.07%950.00%
antonio quartulliantonio quartulli3616.67%738.89%
martin hundebollmartin hundeboll136.02%15.56%
marek lindnermarek lindner73.24%15.56%
Total216100.00%18100.00%


int batadv_send_broadcast_skb(struct sk_buff *skb, struct batadv_hard_iface *hard_iface) { return batadv_send_skb_packet(skb, hard_iface, batadv_broadcast_addr); }

Contributors

PersonTokensPropCommitsCommitProp
antonio quartulliantonio quartulli25100.00%1100.00%
Total25100.00%1100.00%


int batadv_send_unicast_skb(struct sk_buff *skb, struct batadv_neigh_node *neigh) { #ifdef CONFIG_BATMAN_ADV_BATMAN_V struct batadv_hardif_neigh_node *hardif_neigh; #endif int ret; ret = batadv_send_skb_packet(skb, neigh->if_incoming, neigh->addr); #ifdef CONFIG_BATMAN_ADV_BATMAN_V hardif_neigh = batadv_hardif_neigh_get(neigh->if_incoming, neigh->addr); if ((hardif_neigh) && (ret != NET_XMIT_DROP)) hardif_neigh->bat_v.last_unicast_tx = jiffies; if (hardif_neigh) batadv_hardif_neigh_put(hardif_neigh); #endif return ret; }

Contributors

PersonTokensPropCommitsCommitProp
antonio quartulliantonio quartulli93100.00%1100.00%
Total93100.00%1100.00%

/** * batadv_send_skb_to_orig - Lookup next-hop and transmit skb. * @skb: Packet to be transmitted. * @orig_node: Final destination of the packet. * @recv_if: Interface used when receiving the packet (can be NULL). * * Looks up the best next-hop towards the passed originator and passes the * skb on for preparation of MAC header. If the packet originated from this * host, NULL can be passed as recv_if and no interface alternating is * attempted. * * Return: -1 on failure (and the skb is not consumed), -EINPROGRESS if the * skb is buffered for later transmit or the NET_XMIT status returned by the * lower routine if the packet has been passed down. * * If the returning value is not -1 the skb has been consumed. */
int batadv_send_skb_to_orig(struct sk_buff *skb, struct batadv_orig_node *orig_node, struct batadv_hard_iface *recv_if) { struct batadv_priv *bat_priv = orig_node->bat_priv; struct batadv_neigh_node *neigh_node; int ret = -1; /* batadv_find_router() increases neigh_nodes refcount if found. */ neigh_node = batadv_find_router(bat_priv, orig_node, recv_if); if (!neigh_node) goto out; /* Check if the skb is too large to send in one piece and fragment * it if needed. */ if (atomic_read(&bat_priv->fragmentation) && skb->len > neigh_node->if_incoming->net_dev->mtu) { /* Fragment and send packet. */ ret = batadv_frag_send_packet(skb, orig_node, neigh_node); goto out; } /* try to network code the packet, if it is received on an interface * (i.e. being forwarded). If the packet originates from this node or if * network coding fails, then send the packet as usual. */ if (recv_if && batadv_nc_skb_forward(skb, neigh_node)) ret = -EINPROGRESS; else ret = batadv_send_unicast_skb(skb, neigh_node); out: if (neigh_node) batadv_neigh_node_put(neigh_node); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
martin hundebollmartin hundeboll13192.91%342.86%
antonio quartulliantonio quartulli74.96%228.57%
florian westphalflorian westphal21.42%114.29%
sven eckelmannsven eckelmann10.71%114.29%
Total141100.00%7100.00%

/** * batadv_send_skb_push_fill_unicast - extend the buffer and initialize the * common fields for unicast packets * @skb: the skb carrying the unicast header to initialize * @hdr_size: amount of bytes to push at the beginning of the skb * @orig_node: the destination node * * Return: false if the buffer extension was not possible or true otherwise. */
static bool batadv_send_skb_push_fill_unicast(struct sk_buff *skb, int hdr_size, struct batadv_orig_node *orig_node) { struct batadv_unicast_packet *unicast_packet; u8 ttvn = (u8)atomic_read(&orig_node->last_ttvn); if (batadv_skb_head_push(skb, hdr_size) < 0) return false; unicast_packet = (struct batadv_unicast_packet *)skb->data; unicast_packet->version = BATADV_COMPAT_VERSION; /* batman packet type: unicast */ unicast_packet->packet_type = BATADV_UNICAST; /* set unicast ttl */ unicast_packet->ttl = BATADV_TTL; /* copy the destination for faster routing */ ether_addr_copy(unicast_packet->dest, orig_node->orig); /* set the destination tt version number */ unicast_packet->ttvn = ttvn; return true; }

Contributors

PersonTokensPropCommitsCommitProp
martin hundebollmartin hundeboll10297.14%133.33%
sven eckelmannsven eckelmann21.90%133.33%
antonio quartulliantonio quartulli10.95%133.33%
Total105100.00%3100.00%

/** * batadv_send_skb_prepare_unicast - encapsulate an skb with a unicast header * @skb: the skb containing the payload to encapsulate * @orig_node: the destination node * * Return: false if the payload could not be encapsulated or true otherwise. */
static bool batadv_send_skb_prepare_unicast(struct sk_buff *skb, struct batadv_orig_node *orig_node) { size_t uni_size = sizeof(struct batadv_unicast_packet); return batadv_send_skb_push_fill_unicast(skb, uni_size, orig_node); }

Contributors

PersonTokensPropCommitsCommitProp
martin hundebollmartin hundeboll35100.00%1100.00%
Total35100.00%1100.00%

/** * batadv_send_skb_prepare_unicast_4addr - encapsulate an skb with a * unicast 4addr header * @bat_priv: the bat priv with all the soft interface information * @skb: the skb containing the payload to encapsulate * @orig: the destination node * @packet_subtype: the unicast 4addr packet subtype to use * * Return: false if the payload could not be encapsulated or true otherwise. */
bool batadv_send_skb_prepare_unicast_4addr(struct batadv_priv *bat_priv, struct sk_buff *skb, struct batadv_orig_node *orig, int packet_subtype) { struct batadv_hard_iface *primary_if; struct batadv_unicast_4addr_packet *uc_4addr_packet; bool ret = false; primary_if = batadv_primary_if_get_selected(bat_priv); if (!primary_if) goto out; /* Pull the header space and fill the unicast_packet substructure. * We can do that because the first member of the uc_4addr_packet * is of type struct unicast_packet */ if (!batadv_send_skb_push_fill_unicast(skb, sizeof(*uc_4addr_packet), orig)) goto out; uc_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data; uc_4addr_packet->u.packet_type = BATADV_UNICAST_4ADDR; ether_addr_copy(uc_4addr_packet->src, primary_if->net_dev->dev_addr); uc_4addr_packet->subtype = packet_subtype; uc_4addr_packet->reserved = 0; ret = true; out: if (primary_if) batadv_hardif_put(primary_if); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
martin hundebollmartin hundeboll13398.52%133.33%
sven eckelmannsven eckelmann10.74%133.33%
antonio quartulliantonio quartulli10.74%133.33%
Total135100.00%3100.00%

/** * batadv_send_skb_unicast - encapsulate and send an skb via unicast * @bat_priv: the bat priv with all the soft interface information * @skb: payload to send * @packet_type: the batman unicast packet type to use * @packet_subtype: the unicast 4addr packet subtype (only relevant for unicast * 4addr packets) * @orig_node: the originator to send the packet to * @vid: the vid to be used to search the translation table * * Wrap the given skb into a batman-adv unicast or unicast-4addr header * depending on whether BATADV_UNICAST or BATADV_UNICAST_4ADDR was supplied * as packet_type. Then send this frame to the given orig_node and release a * reference to this orig_node. * * Return: NET_XMIT_DROP in case of error or NET_XMIT_SUCCESS otherwise. */
int batadv_send_skb_unicast(struct batadv_priv *bat_priv, struct sk_buff *skb, int packet_type, int packet_subtype, struct batadv_orig_node *orig_node, unsigned short vid) { struct batadv_unicast_packet *unicast_packet; struct ethhdr *ethhdr; int res, ret = NET_XMIT_DROP; if (!orig_node) goto out; switch (packet_type) { case BATADV_UNICAST: if (!batadv_send_skb_prepare_unicast(skb, orig_node)) goto out; break; case BATADV_UNICAST_4ADDR: if (!batadv_send_skb_prepare_unicast_4addr(bat_priv, skb, orig_node, packet_subtype)) goto out; break; default: /* this function supports UNICAST and UNICAST_4ADDR only. It * should never be invoked with any other packet type */ goto out; } /* skb->data might have been reallocated by * batadv_send_skb_prepare_unicast{,_4addr}() */ ethhdr = eth_hdr(skb); unicast_packet = (struct batadv_unicast_packet *)skb->data; /* inform the destination node that we are still missing a correct route * for this client. The destination will receive this packet and will * try to reroute it because the ttvn contained in the header is less * than the current one */ if (batadv_tt_global_client_is_roaming(bat_priv, ethhdr->h_dest, vid)) unicast_packet->ttvn = unicast_packet->ttvn - 1; res = batadv_send_skb_to_orig(skb, orig_node, NULL); if (res != -1) ret = NET_XMIT_SUCCESS; out: if (orig_node) batadv_orig_node_put(orig_node); if (ret == NET_XMIT_DROP) kfree_skb(skb); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
martin hundebollmartin hundeboll14172.68%110.00%
antonio quartulliantonio quartulli3819.59%550.00%
linus lussinglinus lussing136.70%220.00%
simon wunderlichsimon wunderlich10.52%110.00%
sven eckelmannsven eckelmann10.52%110.00%
Total194100.00%10100.00%

/** * batadv_send_skb_via_tt_generic - send an skb via TT lookup * @bat_priv: the bat priv with all the soft interface information * @skb: payload to send * @packet_type: the batman unicast packet type to use * @packet_subtype: the unicast 4addr packet subtype (only relevant for unicast * 4addr packets) * @dst_hint: can be used to override the destination contained in the skb * @vid: the vid to be used to search the translation table * * Look up the recipient node for the destination address in the ethernet * header via the translation table. Wrap the given skb into a batman-adv * unicast or unicast-4addr header depending on whether BATADV_UNICAST or * BATADV_UNICAST_4ADDR was supplied as packet_type. Then send this frame * to the according destination node. * * Return: NET_XMIT_DROP in case of error or NET_XMIT_SUCCESS otherwise. */
int batadv_send_skb_via_tt_generic(struct batadv_priv *bat_priv, struct sk_buff *skb, int packet_type, int packet_subtype, u8 *dst_hint, unsigned short vid) { struct ethhdr *ethhdr = (struct ethhdr *)skb->data; struct batadv_orig_node *orig_node; u8 *src, *dst; src = ethhdr->h_source; dst = ethhdr->h_dest; /* if we got an hint! let's send the packet to this client (if any) */ if (dst_hint) { src = NULL; dst = dst_hint; } orig_node = batadv_transtable_search(bat_priv, src, dst, vid); return batadv_send_skb_unicast(bat_priv, skb, packet_type, packet_subtype, orig_node, vid); }

Contributors

PersonTokensPropCommitsCommitProp
linus lussinglinus lussing7163.96%133.33%
antonio quartulliantonio quartulli3834.23%133.33%
sven eckelmannsven eckelmann21.80%133.33%
Total111100.00%3100.00%

/** * batadv_send_skb_via_gw - send an skb via gateway lookup * @bat_priv: the bat priv with all the soft interface information * @skb: payload to send * @vid: the vid to be used to search the translation table * * Look up the currently selected gateway. Wrap the given skb into a batman-adv * unicast header and send this frame to this gateway node. * * Return: NET_XMIT_DROP in case of error or NET_XMIT_SUCCESS otherwise. */
int batadv_send_skb_via_gw(struct batadv_priv *bat_priv, struct sk_buff *skb, unsigned short vid) { struct batadv_orig_node *orig_node; orig_node = batadv_gw_get_selected_orig(bat_priv); return batadv_send_skb_unicast(bat_priv, skb, BATADV_UNICAST_4ADDR, BATADV_P_DATA, orig_node, vid); }

Contributors

PersonTokensPropCommitsCommitProp
linus lussinglinus lussing4595.74%150.00%
sven eckelmannsven eckelmann24.26%150.00%
Total47100.00%2100.00%


void batadv_forw_packet_free(struct batadv_forw_packet *forw_packet) { kfree_skb(forw_packet->skb); if (forw_packet->if_incoming) batadv_hardif_put(forw_packet->if_incoming); if (forw_packet->if_outgoing) batadv_hardif_put(forw_packet->if_outgoing); kfree(forw_packet); }

Contributors

PersonTokensPropCommitsCommitProp
sven eckelmannsven eckelmann3675.00%583.33%
simon wunderlichsimon wunderlich1225.00%116.67%
Total48100.00%6100.00%


static void _batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv, struct batadv_forw_packet *forw_packet, unsigned long send_time) { /* add new packet to packet list */ spin_lock_bh(&bat_priv->forw_bcast_list_lock); hlist_add_head(&forw_packet->list, &bat_priv->forw_bcast_list); spin_unlock_bh(&bat_priv->forw_bcast_list_lock); /* start timer for this packet */ queue_delayed_work(batadv_event_workqueue, &forw_packet->delayed_work, send_time); }

Contributors

PersonTokensPropCommitsCommitProp
sven eckelmannsven eckelmann63100.00%4100.00%
Total63100.00%4100.00%

/** * batadv_add_bcast_packet_to_list - queue broadcast packet for multiple sends * @bat_priv: the bat priv with all the soft interface information * @skb: broadcast packet to add * @delay: number of jiffies to wait before sending * * add a broadcast packet to the queue and setup timers. broadcast packets * are sent multiple times to increase probability for being received. * * The skb is not consumed, so the caller should make sure that the * skb is freed. * * Return: NETDEV_TX_OK on success and NETDEV_TX_BUSY on errors. */
int batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv, const struct sk_buff *skb, unsigned long delay) { struct batadv_hard_iface *primary_if = NULL; struct batadv_forw_packet *forw_packet; struct batadv_bcast_packet *bcast_packet; struct sk_buff *newskb; if (!batadv_atomic_dec_not_zero(&bat_priv->bcast_queue_left)) { batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "bcast packet queue full\n"); goto out; } primary_if = batadv_primary_if_get_selected(bat_priv); if (!primary_if) goto out_and_inc; forw_packet = kmalloc(sizeof(*forw_packet), GFP_ATOMIC); if (!forw_packet) goto out_and_inc; newskb = skb_copy(skb, GFP_ATOMIC); if (!newskb) goto packet_free; /* as we have a copy now, it is safe to decrease the TTL */ bcast_packet = (struct batadv_bcast_packet *)newskb->data; bcast_packet->ttl--; skb_reset_mac_header(newskb); forw_packet->skb = newskb; forw_packet->if_incoming = primary_if; forw_packet->if_outgoing = NULL; /* how often did we send the bcast packet ? */ forw_packet->num_packets = 0; INIT_DELAYED_WORK(&forw_packet->delayed_work, batadv_send_outstanding_bcast_packet); _batadv_add_bcast_packet_to_list(bat_priv, forw_packet, delay); return NETDEV_TX_OK; packet_free: kfree(forw_packet); out_and_inc: atomic_inc(&bat_priv->bcast_queue_left); out: if (primary_if) batadv_hardif_put(primary_if); return NETDEV_TX_BUSY; }

Contributors

PersonTokensPropCommitsCommitProp
sven eckelmannsven eckelmann17880.91%1270.59%
marek lindnermarek lindner219.55%211.76%
antonio quartulliantonio quartulli156.82%211.76%
simon wunderlichsimon wunderlich62.73%15.88%
Total220100.00%17100.00%


static void batadv_send_outstanding_bcast_packet(struct work_struct *work) { struct batadv_hard_iface *hard_iface; struct delayed_work *delayed_work; struct batadv_forw_packet *forw_packet; struct sk_buff *skb1; struct net_device *soft_iface; struct batadv_priv *bat_priv; delayed_work = to_delayed_work(work); forw_packet = container_of(delayed_work, struct batadv_forw_packet, delayed_work); soft_iface = forw_packet->if_incoming->soft_iface; bat_priv = netdev_priv(soft_iface); spin_lock_bh(&bat_priv->forw_bcast_list_lock); hlist_del(&forw_packet->list); spin_unlock_bh(&bat_priv->forw_bcast_list_lock); if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING) goto out; if (batadv_dat_drop_broadcast_packet(bat_priv, forw_packet)) goto out; /* rebroadcast packet */ rcu_read_lock(); list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) { if (hard_iface->soft_iface != soft_iface) continue; if (forw_packet->num_packets >= hard_iface->num_bcasts) continue; if (!kref_get_unless_zero(&hard_iface->refcount)) continue; /* send a copy of the saved skb */ skb1 = skb_clone(forw_packet->skb, GFP_ATOMIC); if (skb1) batadv_send_broadcast_skb(skb1, hard_iface); batadv_hardif_put(hard_iface); } rcu_read_unlock(); forw_packet->num_packets++; /* if we still have some more bcasts to send */ if (forw_packet->num_packets < BATADV_NUM_BCASTS_MAX) { _batadv_add_bcast_packet_to_list(bat_priv, forw_packet, msecs_to_jiffies(5)); return; } out: batadv_forw_packet_free(forw_packet); atomic_inc(&bat_priv->bcast_queue_left); }

Contributors

PersonTokensPropCommitsCommitProp
sven eckelmannsven eckelmann21486.64%753.85%
antonio quartulliantonio quartulli135.26%215.38%
matthias schiffermatthias schiffer124.86%17.69%
marek lindnermarek lindner72.83%215.38%
geliang tanggeliang tang10.40%17.69%
Total247100.00%13100.00%


void batadv_purge_outstanding_packets(struct batadv_priv *bat_priv, const struct batadv_hard_iface *hard_iface) { struct batadv_forw_packet *forw_packet; struct hlist_node *safe_tmp_node; bool pending; if (hard_iface) batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "purge_outstanding_packets(): %s\n", hard_iface->net_dev->name); else batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "purge_outstanding_packets()\n"); /* free bcast list */ spin_lock_bh(&bat_priv->forw_bcast_list_lock); hlist_for_each_entry_safe(forw_packet, safe_tmp_node, &bat_priv->forw_bcast_list, list) { /* if purge_outstanding_packets() was called with an argument * we delete only packets belonging to the given interface */ if ((hard_iface) && (forw_packet->if_incoming != hard_iface) && (forw_packet->if_outgoing != hard_iface)) continue; spin_unlock_bh(&bat_priv->forw_bcast_list_lock); /* batadv_send_outstanding_bcast_packet() will lock the list to * delete the item from the list */ pending = cancel_delayed_work_sync(&forw_packet->delayed_work); spin_lock_bh(&bat_priv->forw_bcast_list_lock); if (pending) { hlist_del(&forw_packet->list); if (!forw_packet->own) atomic_inc(&bat_priv->bcast_queue_left); batadv_forw_packet_free(forw_packet); } } spin_unlock_bh(&bat_priv->forw_bcast_list_lock); /* free batman packet list */ spin_lock_bh(&bat_priv->forw_bat_list_lock); hlist_for_each_entry_safe(forw_packet, safe_tmp_node, &bat_priv->forw_bat_list, list) { /* if purge_outstanding_packets() was called with an argument * we delete only packets belonging to the given interface */ if ((hard_iface) && (forw_packet->if_incoming != hard_iface) && (forw_packet->if_outgoing != hard_iface)) continue; spin_unlock_bh(&bat_priv->forw_bat_list_lock); /* send_outstanding_bat_packet() will lock the list to * delete the item from the list */ pending = cancel_delayed_work_sync(&forw_packet->delayed_work); spin_lock_bh(&bat_priv->forw_bat_list_lock); if (pending) { hlist_del(&forw_packet->list); if (!forw_packet->own) atomic_inc(&bat_priv->batman_queue_left); batadv_forw_packet_free(forw_packet); } } spin_unlock_bh(&bat_priv->forw_bat_list_lock); }

Contributors

PersonTokensPropCommitsCommitProp
sven eckelmannsven eckelmann23381.47%969.23%
linus lussinglinus lussing3010.49%17.69%
simon wunderlichsimon wunderlich165.59%215.38%
marek lindnermarek lindner72.45%17.69%
Total286100.00%13100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
sven eckelmannsven eckelmann99247.65%3147.69%
martin hundebollmartin hundeboll56126.95%57.69%
antonio quartulliantonio quartulli27613.26%1523.08%
linus lussinglinus lussing1617.73%46.15%
marek lindnermarek lindner422.02%46.15%
simon wunderlichsimon wunderlich351.68%34.62%
matthias schiffermatthias schiffer120.58%11.54%
florian westphalflorian westphal20.10%11.54%
geliang tanggeliang tang10.05%11.54%
Total2082100.00%65100.00%
Directory: net/batman-adv
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.