Commit a230e033 authored by David S. Miller's avatar David S. Miller

Merge tag 'batman-adv-for-davem' of git://git.open-mesh.org/linux-merge

Included changes:
- reduce broadcast overhead on non-lossy wired links
- fix typos in kernel doc
- use eth_hdr() when possible
- use netdev_allock_skb_ip_align() and don't deal with NET_IP_ALIGN
- change VID semantic in the BLA component
- other minor cleanups and code refactoring
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents cbb963de 6715fd3f
......@@ -32,7 +32,6 @@ batman-adv-y += icmp_socket.o
batman-adv-y += main.o
batman-adv-$(CONFIG_BATMAN_ADV_NC) += network-coding.o
batman-adv-y += originator.o
batman-adv-y += ring_buffer.o
batman-adv-y += routing.o
batman-adv-y += send.o
batman-adv-y += soft-interface.o
......
......@@ -19,7 +19,6 @@
#include "main.h"
#include "translation-table.h"
#include "ring_buffer.h"
#include "originator.h"
#include "routing.h"
#include "gateway_common.h"
......@@ -29,16 +28,57 @@
#include "bat_algo.h"
#include "network-coding.h"
/**
* batadv_ring_buffer_set - update the ring buffer with the given value
* @lq_recv: pointer to the ring buffer
* @lq_index: index to store the value at
* @value: value to store in the ring buffer
*/
static void batadv_ring_buffer_set(uint8_t lq_recv[], uint8_t *lq_index,
uint8_t value)
{
lq_recv[*lq_index] = value;
*lq_index = (*lq_index + 1) % BATADV_TQ_GLOBAL_WINDOW_SIZE;
}
/**
* batadv_ring_buffer_set - compute the average of all non-zero values stored
* in the given ring buffer
* @lq_recv: pointer to the ring buffer
*
* Returns computed average value.
*/
static uint8_t batadv_ring_buffer_avg(const uint8_t lq_recv[])
{
const uint8_t *ptr;
uint16_t count = 0, i = 0, sum = 0;
ptr = lq_recv;
while (i < BATADV_TQ_GLOBAL_WINDOW_SIZE) {
if (*ptr != 0) {
count++;
sum += *ptr;
}
i++;
ptr++;
}
if (count == 0)
return 0;
return (uint8_t)(sum / count);
}
static struct batadv_neigh_node *
batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface,
const uint8_t *neigh_addr,
struct batadv_orig_node *orig_node,
struct batadv_orig_node *orig_neigh, __be32 seqno)
struct batadv_orig_node *orig_neigh)
{
struct batadv_neigh_node *neigh_node;
neigh_node = batadv_neigh_node_new(hard_iface, neigh_addr,
ntohl(seqno));
neigh_node = batadv_neigh_node_new(hard_iface, neigh_addr);
if (!neigh_node)
goto out;
......@@ -413,18 +453,16 @@ static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff,
else
skb_size = packet_len;
skb_size += ETH_HLEN + NET_IP_ALIGN;
skb_size += ETH_HLEN;
forw_packet_aggr->skb = dev_alloc_skb(skb_size);
forw_packet_aggr->skb = netdev_alloc_skb_ip_align(NULL, skb_size);
if (!forw_packet_aggr->skb) {
if (!own_packet)
atomic_inc(&bat_priv->batman_queue_left);
kfree(forw_packet_aggr);
goto out;
}
skb_reserve(forw_packet_aggr->skb, ETH_HLEN + NET_IP_ALIGN);
INIT_HLIST_NODE(&forw_packet_aggr->list);
skb_reserve(forw_packet_aggr->skb, ETH_HLEN);
skb_buff = skb_put(forw_packet_aggr->skb, packet_len);
forw_packet_aggr->packet_len = packet_len;
......@@ -590,6 +628,41 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node,
if_incoming, 0, batadv_iv_ogm_fwd_send_time());
}
/**
* batadv_iv_ogm_slide_own_bcast_window - bitshift own OGM broadcast windows for
* the given interface
* @hard_iface: the interface for which the windows have to be shifted
*/
static void
batadv_iv_ogm_slide_own_bcast_window(struct batadv_hard_iface *hard_iface)
{
struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
struct batadv_hashtable *hash = bat_priv->orig_hash;
struct hlist_head *head;
struct batadv_orig_node *orig_node;
unsigned long *word;
uint32_t i;
size_t word_index;
uint8_t *w;
for (i = 0; i < hash->size; i++) {
head = &hash->table[i];
rcu_read_lock();
hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
spin_lock_bh(&orig_node->ogm_cnt_lock);
word_index = hard_iface->if_num * BATADV_NUM_WORDS;
word = &(orig_node->bcast_own[word_index]);
batadv_bit_get_packet(bat_priv, word, 1, 0);
w = &orig_node->bcast_own_sum[hard_iface->if_num];
*w = bitmap_weight(word, BATADV_TQ_LOCAL_WINDOW_SIZE);
spin_unlock_bh(&orig_node->ogm_cnt_lock);
}
rcu_read_unlock();
}
}
static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
{
struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
......@@ -634,7 +707,7 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
batadv_ogm_packet->gw_flags = BATADV_NO_FLAGS;
}
batadv_slide_own_bcast_window(hard_iface);
batadv_iv_ogm_slide_own_bcast_window(hard_iface);
batadv_iv_ogm_queue_add(bat_priv, hard_iface->bat_iv.ogm_buff,
hard_iface->bat_iv.ogm_buff_len, hard_iface, 1,
batadv_iv_ogm_emit_send_time(bat_priv));
......@@ -670,7 +743,7 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
if (batadv_compare_eth(neigh_addr, ethhdr->h_source) &&
tmp_neigh_node->if_incoming == if_incoming &&
atomic_inc_not_zero(&tmp_neigh_node->refcount)) {
if (neigh_node)
if (WARN(neigh_node, "too many matching neigh_nodes"))
batadv_neigh_node_free_ref(neigh_node);
neigh_node = tmp_neigh_node;
continue;
......@@ -696,8 +769,7 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
ethhdr->h_source,
orig_node, orig_tmp,
batadv_ogm_packet->seqno);
orig_node, orig_tmp);
batadv_orig_node_free_ref(orig_tmp);
if (!neigh_node)
......@@ -829,8 +901,7 @@ static int batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
orig_neigh_node->orig,
orig_neigh_node,
orig_neigh_node,
batadv_ogm_packet->seqno);
orig_neigh_node);
if (!neigh_node)
goto out;
......@@ -991,7 +1062,7 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
struct batadv_neigh_node *orig_neigh_router = NULL;
int has_directlink_flag;
int is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0;
int is_broadcast = 0, is_bidirect;
int is_bidirect;
bool is_single_hop_neigh = false;
bool is_from_best_next_hop = false;
int is_duplicate, sameseq, simlar_ttl;
......@@ -1054,19 +1125,9 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
if (batadv_compare_eth(batadv_ogm_packet->prev_sender,
hard_iface->net_dev->dev_addr))
is_my_oldorig = 1;
if (is_broadcast_ether_addr(ethhdr->h_source))
is_broadcast = 1;
}
rcu_read_unlock();
if (batadv_ogm_packet->header.version != BATADV_COMPAT_VERSION) {
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
"Drop packet: incompatible batman version (%i)\n",
batadv_ogm_packet->header.version);
return;
}
if (is_my_addr) {
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
"Drop packet: received my own broadcast (sender: %pM)\n",
......@@ -1074,13 +1135,6 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
return;
}
if (is_broadcast) {
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
"Drop packet: ignoring all packets with broadcast source addr (sender: %pM)\n",
ethhdr->h_source);
return;
}
if (is_my_orig) {
unsigned long *word;
int offset;
......@@ -1288,7 +1342,7 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb,
skb->len + ETH_HLEN);
packet_len = skb_headlen(skb);
ethhdr = (struct ethhdr *)skb_mac_header(skb);
ethhdr = eth_hdr(skb);
packet_buff = skb->data;
batadv_ogm_packet = (struct batadv_ogm_packet *)packet_buff;
......
This diff is collapsed.
......@@ -21,9 +21,10 @@
#define _NET_BATMAN_ADV_BLA_H_
#ifdef CONFIG_BATMAN_ADV_BLA
int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid,
bool is_bcast);
int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid);
int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb,
unsigned short vid, bool is_bcast);
int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb,
unsigned short vid);
int batadv_bla_is_backbone_gw(struct sk_buff *skb,
struct batadv_orig_node *orig_node, int hdr_size);
int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset);
......@@ -42,13 +43,14 @@ void batadv_bla_free(struct batadv_priv *bat_priv);
#else /* ifdef CONFIG_BATMAN_ADV_BLA */
static inline int batadv_bla_rx(struct batadv_priv *bat_priv,
struct sk_buff *skb, short vid, bool is_bcast)
struct sk_buff *skb, unsigned short vid,
bool is_bcast)
{
return 0;
}
static inline int batadv_bla_tx(struct batadv_priv *bat_priv,
struct sk_buff *skb, short vid)
struct sk_buff *skb, unsigned short vid)
{
return 0;
}
......
This diff is collapsed.
......@@ -117,6 +117,58 @@ static int batadv_is_valid_iface(const struct net_device *net_dev)
return 1;
}
/**
* batadv_is_wifi_netdev - check if the given net_device struct is a wifi
* interface
* @net_device: the device to check
*
* Returns true if the net device is a 802.11 wireless device, false otherwise.
*/
static bool batadv_is_wifi_netdev(struct net_device *net_device)
{
#ifdef CONFIG_WIRELESS_EXT
/* pre-cfg80211 drivers have to implement WEXT, so it is possible to
* check for wireless_handlers != NULL
*/
if (net_device->wireless_handlers)
return true;
#endif
/* cfg80211 drivers have to set ieee80211_ptr */
if (net_device->ieee80211_ptr)
return true;
return false;
}
/**
* batadv_is_wifi_iface - check if the given interface represented by ifindex
* is a wifi interface
* @ifindex: interface index to check
*
* Returns true if the interface represented by ifindex is a 802.11 wireless
* device, false otherwise.
*/
bool batadv_is_wifi_iface(int ifindex)
{
struct net_device *net_device = NULL;
bool ret = false;
if (ifindex == BATADV_NULL_IFINDEX)
goto out;
net_device = dev_get_by_index(&init_net, ifindex);
if (!net_device)
goto out;
ret = batadv_is_wifi_netdev(net_device);
out:
if (net_device)
dev_put(net_device);
return ret;
}
static struct batadv_hard_iface *
batadv_hardif_get_active(const struct net_device *soft_iface)
{
......@@ -525,7 +577,7 @@ batadv_hardif_add_interface(struct net_device *net_dev)
dev_hold(net_dev);
hard_iface = kmalloc(sizeof(*hard_iface), GFP_ATOMIC);
hard_iface = kzalloc(sizeof(*hard_iface), GFP_ATOMIC);
if (!hard_iface)
goto release_dev;
......@@ -541,18 +593,16 @@ batadv_hardif_add_interface(struct net_device *net_dev)
INIT_WORK(&hard_iface->cleanup_work,
batadv_hardif_remove_interface_finish);
hard_iface->num_bcasts = BATADV_NUM_BCASTS_DEFAULT;
if (batadv_is_wifi_netdev(net_dev))
hard_iface->num_bcasts = BATADV_NUM_BCASTS_WIRELESS;
/* extra reference for return */
atomic_set(&hard_iface->refcount, 2);
batadv_check_known_mac_addr(hard_iface->net_dev);
list_add_tail_rcu(&hard_iface->list, &batadv_hardif_list);
/* This can't be called via a bat_priv callback because
* we have no bat_priv yet.
*/
atomic_set(&hard_iface->bat_iv.ogm_seqno, 1);
hard_iface->bat_iv.ogm_buff = NULL;
return hard_iface;
free_if:
......@@ -657,38 +707,6 @@ static int batadv_hard_if_event(struct notifier_block *this,
return NOTIFY_DONE;
}
/* This function returns true if the interface represented by ifindex is a
* 802.11 wireless device
*/
bool batadv_is_wifi_iface(int ifindex)
{
struct net_device *net_device = NULL;
bool ret = false;
if (ifindex == BATADV_NULL_IFINDEX)
goto out;
net_device = dev_get_by_index(&init_net, ifindex);
if (!net_device)
goto out;
#ifdef CONFIG_WIRELESS_EXT
/* pre-cfg80211 drivers have to implement WEXT, so it is possible to
* check for wireless_handlers != NULL
*/
if (net_device->wireless_handlers)
ret = true;
else
#endif
/* cfg80211 drivers have to set ieee80211_ptr */
if (net_device->ieee80211_ptr)
ret = true;
out:
if (net_device)
dev_put(net_device);
return ret;
}
struct notifier_block batadv_hard_if_notifier = {
.notifier_call = batadv_hard_if_event,
};
......@@ -177,13 +177,13 @@ static ssize_t batadv_socket_write(struct file *file, const char __user *buff,
if (len >= sizeof(struct batadv_icmp_packet_rr))
packet_len = sizeof(struct batadv_icmp_packet_rr);
skb = dev_alloc_skb(packet_len + ETH_HLEN + NET_IP_ALIGN);
skb = netdev_alloc_skb_ip_align(NULL, packet_len + ETH_HLEN);
if (!skb) {
len = -ENOMEM;
goto out;
}
skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
skb_reserve(skb, ETH_HLEN);
icmp_packet = (struct batadv_icmp_packet_rr *)skb_put(skb, packet_len);
if (copy_from_user(icmp_packet, buff, packet_len)) {
......
......@@ -26,7 +26,7 @@
#define BATADV_DRIVER_DEVICE "batman-adv"
#ifndef BATADV_SOURCE_VERSION
#define BATADV_SOURCE_VERSION "2013.2.0"
#define BATADV_SOURCE_VERSION "2013.3.0"
#endif
/* B.A.T.M.A.N. parameters */
......@@ -76,6 +76,11 @@
#define BATADV_LOG_BUF_LEN 8192 /* has to be a power of 2 */
/* number of packets to send for broadcasts on different interface types */
#define BATADV_NUM_BCASTS_DEFAULT 1
#define BATADV_NUM_BCASTS_WIRELESS 3
#define BATADV_NUM_BCASTS_MAX 3
/* msecs after which an ARP_REQUEST is sent in broadcast as fallback */
#define ARP_REQ_DELAY 250
/* numbers of originator to contact for any PUT/GET DHT operation */
......@@ -157,6 +162,17 @@ enum batadv_uev_type {
#include <linux/seq_file.h>
#include "types.h"
/**
* batadv_vlan_flags - flags for the four MSB of any vlan ID field
* @BATADV_VLAN_HAS_TAG: whether the field contains a valid vlan tag or not
*/
enum batadv_vlan_flags {
BATADV_VLAN_HAS_TAG = BIT(15),
};
#define BATADV_PRINT_VID(vid) (vid & BATADV_VLAN_HAS_TAG ? \
(int)(vid & VLAN_VID_MASK) : -1)
extern char batadv_routing_algo[];
extern struct list_head batadv_hardif_list;
......
......@@ -1245,7 +1245,7 @@ static void batadv_nc_skb_store_before_coding(struct batadv_priv *bat_priv,
return;
/* Set the mac header as if we actually sent the packet uncoded */
ethhdr = (struct ethhdr *)skb_mac_header(skb);
ethhdr = eth_hdr(skb);
memcpy(ethhdr->h_source, ethhdr->h_dest, ETH_ALEN);
memcpy(ethhdr->h_dest, eth_dst_new, ETH_ALEN);
......@@ -1359,18 +1359,17 @@ static bool batadv_nc_skb_add_to_path(struct sk_buff *skb,
* buffer
* @skb: data skb to forward
* @neigh_node: next hop to forward packet to
* @ethhdr: pointer to the ethernet header inside the skb
*
* Returns true if the skb was consumed (encoded packet sent) or false otherwise
*/
bool batadv_nc_skb_forward(struct sk_buff *skb,
struct batadv_neigh_node *neigh_node,
struct ethhdr *ethhdr)
struct batadv_neigh_node *neigh_node)
{
const struct net_device *netdev = neigh_node->if_incoming->soft_iface;
struct batadv_priv *bat_priv = netdev_priv(netdev);
struct batadv_unicast_packet *packet;
struct batadv_nc_path *nc_path;
struct ethhdr *ethhdr = eth_hdr(skb);
__be32 packet_id;
u8 *payload;
......@@ -1423,7 +1422,7 @@ void batadv_nc_skb_store_for_decoding(struct batadv_priv *bat_priv,
{
struct batadv_unicast_packet *packet;
struct batadv_nc_path *nc_path;
struct ethhdr *ethhdr = (struct ethhdr *)skb_mac_header(skb);
struct ethhdr *ethhdr = eth_hdr(skb);
__be32 packet_id;
u8 *payload;
......@@ -1482,7 +1481,7 @@ void batadv_nc_skb_store_for_decoding(struct batadv_priv *bat_priv,
void batadv_nc_skb_store_sniffed_unicast(struct batadv_priv *bat_priv,
struct sk_buff *skb)
{
struct ethhdr *ethhdr = (struct ethhdr *)skb_mac_header(skb);
struct ethhdr *ethhdr = eth_hdr(skb);
if (batadv_is_my_mac(bat_priv, ethhdr->h_dest))
return;
......@@ -1533,7 +1532,7 @@ batadv_nc_skb_decode_packet(struct batadv_priv *bat_priv, struct sk_buff *skb,
skb_reset_network_header(skb);
/* Reconstruct original mac header */
ethhdr = (struct ethhdr *)skb_mac_header(skb);
ethhdr = eth_hdr(skb);
memcpy(ethhdr, &ethhdr_tmp, sizeof(*ethhdr));
/* Select the correct unicast header information based on the location
......@@ -1677,7 +1676,7 @@ static int batadv_nc_recv_coded_packet(struct sk_buff *skb,
return NET_RX_DROP;
coded_packet = (struct batadv_coded_packet *)skb->data;
ethhdr = (struct ethhdr *)skb_mac_header(skb);
ethhdr = eth_hdr(skb);
/* Verify frame is destined for us */
if (!batadv_is_my_mac(bat_priv, ethhdr->h_dest) &&
......@@ -1763,6 +1762,13 @@ int batadv_nc_nodes_seq_print_text(struct seq_file *seq, void *offset)
/* For each orig_node in this bin */
rcu_read_lock();
hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
/* no need to print the orig node if it does not have
* network coding neighbors
*/
if (list_empty(&orig_node->in_coding_list) &&
list_empty(&orig_node->out_coding_list))
continue;
seq_printf(seq, "Node: %pM\n", orig_node->orig);
seq_puts(seq, " Ingoing: ");
......
......@@ -36,8 +36,7 @@ void batadv_nc_purge_orig(struct batadv_priv *bat_priv,
void batadv_nc_init_bat_priv(struct batadv_priv *bat_priv);
void batadv_nc_init_orig(struct batadv_orig_node *orig_node);
bool batadv_nc_skb_forward(struct sk_buff *skb,
struct batadv_neigh_node *neigh_node,
struct ethhdr *ethhdr);
struct batadv_neigh_node *neigh_node);
void batadv_nc_skb_store_for_decoding(struct batadv_priv *bat_priv,
struct sk_buff *skb);
void batadv_nc_skb_store_sniffed_unicast(struct batadv_priv *bat_priv,
......@@ -87,8 +86,7 @@ static inline void batadv_nc_init_orig(struct batadv_orig_node *orig_node)
}
static inline bool batadv_nc_skb_forward(struct sk_buff *skb,
struct batadv_neigh_node *neigh_node,
struct ethhdr *ethhdr)
struct batadv_neigh_node *neigh_node)
{
return false;
}
......
......@@ -92,7 +92,7 @@ batadv_orig_node_get_router(struct batadv_orig_node *orig_node)
struct batadv_neigh_node *
batadv_neigh_node_new(struct batadv_hard_iface *hard_iface,
const uint8_t *neigh_addr, uint32_t seqno)
const uint8_t *neigh_addr)
{
struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
struct batadv_neigh_node *neigh_node;
......@@ -110,8 +110,8 @@ batadv_neigh_node_new(struct batadv_hard_iface *hard_iface,
atomic_set(&neigh_node->refcount, 2);
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
"Creating new neighbor %pM, initial seqno %d\n",
neigh_addr, seqno);
"Creating new neighbor %pM on interface %s\n", neigh_addr,
hard_iface->net_dev->name);
out:
return neigh_node;
......
......@@ -31,7 +31,7 @@ struct batadv_orig_node *batadv_get_orig_node(struct batadv_priv *bat_priv,
const uint8_t *addr);
struct batadv_neigh_node *
batadv_neigh_node_new(struct batadv_hard_iface *hard_iface,
const uint8_t *neigh_addr, uint32_t seqno);
const uint8_t *neigh_addr);
void batadv_neigh_node_free_ref(struct batadv_neigh_node *neigh_node);
struct batadv_neigh_node *
batadv_orig_node_get_router(struct batadv_orig_node *orig_node);
......
/* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors:
*
* Marek Lindner
*
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA
*/
#include "main.h"
#include "ring_buffer.h"
void batadv_ring_buffer_set(uint8_t lq_recv[], uint8_t *lq_index,
uint8_t value)
{
lq_recv[*lq_index] = value;
*lq_index = (*lq_index + 1) % BATADV_TQ_GLOBAL_WINDOW_SIZE;
}
uint8_t batadv_ring_buffer_avg(const uint8_t lq_recv[])
{
const uint8_t *ptr;
uint16_t count = 0, i = 0, sum = 0;
ptr = lq_recv;
while (i < BATADV_TQ_GLOBAL_WINDOW_SIZE) {
if (*ptr != 0) {
count++;
sum += *ptr;
}
i++;
ptr++;
}
if (count == 0)
return 0;
return (uint8_t)(sum / count);
}
/* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors:
*
* Marek Lindner
*
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA
*/
#ifndef _NET_BATMAN_ADV_RING_BUFFER_H_
#define _NET_BATMAN_ADV_RING_BUFFER_H_
void batadv_ring_buffer_set(uint8_t lq_recv[], uint8_t *lq_index,
uint8_t value);
uint8_t batadv_ring_buffer_avg(const uint8_t lq_recv[]);
#endif /* _NET_BATMAN_ADV_RING_BUFFER_H_ */
......@@ -34,35 +34,6 @@
static int batadv_route_unicast_packet(struct sk_buff *skb,
struct batadv_hard_iface *recv_if);
void batadv_slide_own_bcast_window(struct batadv_hard_iface *hard_iface)
{
struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
struct batadv_hashtable *hash = bat_priv->orig_hash;
struct hlist_head *head;
struct batadv_orig_node *orig_node;
unsigned long *word;
uint32_t i;
size_t word_index;
uint8_t *w;
for (i = 0; i < hash->size; i++) {
head = &hash->table[i];
rcu_read_lock();
hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
spin_lock_bh(&orig_node->ogm_cnt_lock);
word_index = hard_iface->if_num * BATADV_NUM_WORDS;
word = &(orig_node->bcast_own[word_index]);
batadv_bit_get_packet(bat_priv, word, 1, 0);
w = &orig_node->bcast_own_sum[hard_iface->if_num];
*w = bitmap_weight(word, BATADV_TQ_LOCAL_WINDOW_SIZE);
spin_unlock_bh(&orig_node->ogm_cnt_lock);
}
rcu_read_unlock();
}
}
static void _batadv_update_route(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig_node,
struct batadv_neigh_node *neigh_node)
......@@ -256,7 +227,7 @@ bool batadv_check_management_packet(struct sk_buff *skb,
if (unlikely(!pskb_may_pull(skb, header_len)))
return false;
ethhdr = (struct ethhdr *)skb_mac_header(skb);
ethhdr = eth_hdr(skb);
/* packet with broadcast indication but unicast recipient */
if (!is_broadcast_ether_addr(ethhdr->h_dest))
......@@ -314,7 +285,7 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv,
icmp_packet->msg_type = BATADV_ECHO_REPLY;
icmp_packet->header.ttl = BATADV_TTL;
if (batadv_send_skb_to_orig(skb, orig_node, NULL))
if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP)
ret = NET_RX_SUCCESS;
out:
......@@ -362,7 +333,7 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
icmp_packet->msg_type = BATADV_TTL_EXCEEDED;
icmp_packet->header.ttl = BATADV_TTL;
if (batadv_send_skb_to_orig(skb, orig_node, NULL))
if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP)
ret = NET_RX_SUCCESS;
out:
......@@ -392,7 +363,7 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
if (unlikely(!pskb_may_pull(skb, hdr_size)))
goto out;
ethhdr = (struct ethhdr *)skb_mac_header(skb);
ethhdr = eth_hdr(skb);
/* packet with unicast indication but broadcast recipient */
if (is_broadcast_ether_addr(ethhdr->h_dest))
......@@ -439,7 +410,7 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
icmp_packet->header.ttl--;
/* route it */
if (batadv_send_skb_to_orig(skb, orig_node, recv_if))
if (batadv_send_skb_to_orig(skb, orig_node, recv_if) != NET_XMIT_DROP)
ret = NET_RX_SUCCESS;
out:
......@@ -569,7 +540,7 @@ static int batadv_check_unicast_packet(struct batadv_priv *bat_priv,
if (unlikely(!pskb_may_pull(skb, hdr_size)))
return -ENODATA;
ethhdr = (struct ethhdr *)skb_mac_header(skb);
ethhdr = eth_hdr(skb);
/* packet with unicast indication but broadcast recipient */
if (is_broadcast_ether_addr(ethhdr->h_dest))
......@@ -803,8 +774,8 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
struct batadv_orig_node *orig_node = NULL;
struct batadv_neigh_node *neigh_node = NULL;
struct batadv_unicast_packet *unicast_packet;
struct ethhdr *ethhdr = (struct ethhdr *)skb_mac_header(skb);
int ret = NET_RX_DROP;
struct ethhdr *ethhdr = eth_hdr(skb);
int res, ret = NET_RX_DROP;
struct sk_buff *new_skb;
unicast_packet = (struct batadv_unicast_packet *)skb->data;
......@@ -864,16 +835,19 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
/* decrement ttl */
unicast_packet->header.ttl--;
/* network code packet if possible */
if (batadv_nc_skb_forward(skb, neigh_node, ethhdr)) {
ret = NET_RX_SUCCESS;
} else if (batadv_send_skb_to_orig(skb, orig_node, recv_if)) {
ret = NET_RX_SUCCESS;
res = batadv_send_skb_to_orig(skb, orig_node, recv_if);
/* Update stats counter */
/* translate transmit result into receive result */
if (res == NET_XMIT_SUCCESS) {
/* skb was transmitted and consumed */
batadv_inc_counter(bat_priv, BATADV_CNT_FORWARD);
batadv_add_counter(bat_priv, BATADV_CNT_FORWARD_BYTES,
skb->len + ETH_HLEN);
ret = NET_RX_SUCCESS;
} else if (res == NET_XMIT_POLICED) {
/* skb was buffered and consumed */
ret = NET_RX_SUCCESS;
}
out:
......@@ -1165,7 +1139,7 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,
if (unlikely(!pskb_may_pull(skb, hdr_size)))
goto out;
ethhdr = (struct ethhdr *)skb_mac_header(skb);
ethhdr = eth_hdr(skb);
/* packet with broadcast indication but unicast recipient */
if (!is_broadcast_ether_addr(ethhdr->h_dest))
......@@ -1265,7 +1239,7 @@ int batadv_recv_vis_packet(struct sk_buff *skb,
return NET_RX_DROP;
vis_packet = (struct batadv_vis_packet *)skb->data;
ethhdr = (struct ethhdr *)skb_mac_header(skb);
ethhdr = eth_hdr(skb);
/* not for me */
if (!batadv_is_my_mac(bat_priv, ethhdr->h_dest))
......
......@@ -20,7 +20,6 @@
#ifndef _NET_BATMAN_ADV_ROUTING_H_
#define _NET_BATMAN_ADV_ROUTING_H_
void batadv_slide_own_bcast_window(struct batadv_hard_iface *hard_iface);
bool batadv_check_management_packet(struct sk_buff *skb,
struct batadv_hard_iface *hard_iface,
int header_len);
......
......@@ -61,7 +61,7 @@ int batadv_send_skb_packet(struct sk_buff *skb,
skb_reset_mac_header(skb);
ethhdr = (struct ethhdr *)skb_mac_header(skb);
ethhdr = eth_hdr(skb);
memcpy(ethhdr->h_source, hard_iface->net_dev->dev_addr, ETH_ALEN);
memcpy(ethhdr->h_dest, dst_addr, ETH_ALEN);
ethhdr->h_proto = __constant_htons(ETH_P_BATMAN);
......@@ -96,26 +96,37 @@ int batadv_send_skb_packet(struct sk_buff *skb,
* host, NULL can be passed as recv_if and no interface alternating is
* attempted.
*
* Returns TRUE on success; FALSE otherwise.
* Returns NET_XMIT_SUCCESS on success, NET_XMIT_DROP on failure, or
* NET_XMIT_POLICED if the skb is buffered for later transmit.
*/
bool batadv_send_skb_to_orig(struct sk_buff *skb,
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 = NET_XMIT_DROP;
/* batadv_find_router() increases neigh_nodes refcount if found. */
neigh_node = batadv_find_router(bat_priv, orig_node, recv_if);
if (!neigh_node)
return false;
return ret;
/* route it */
batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
/* 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 = NET_XMIT_POLICED;
} else {
batadv_send_skb_packet(skb, neigh_node->if_incoming,
neigh_node->addr);
ret = NET_XMIT_SUCCESS;
}
batadv_neigh_node_free_ref(neigh_node);
return true;
return ret;
}
void batadv_schedule_bat_ogm(struct batadv_hard_iface *hard_iface)
......@@ -152,8 +163,6 @@ _batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv,
struct batadv_forw_packet *forw_packet,
unsigned long send_time)
{
INIT_HLIST_NODE(&forw_packet->list);
/* 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);
......@@ -260,6 +269,9 @@ static void batadv_send_outstanding_bcast_packet(struct work_struct *work)
if (hard_iface->soft_iface != soft_iface)
continue;
if (forw_packet->num_packets >= hard_iface->num_bcasts)
continue;
/* send a copy of the saved skb */
skb1 = skb_clone(forw_packet->skb, GFP_ATOMIC);
if (skb1)
......@@ -271,7 +283,7 @@ static void batadv_send_outstanding_bcast_packet(struct work_struct *work)
forw_packet->num_packets++;
/* if we still have some more bcasts to send */
if (forw_packet->num_packets < 3) {
if (forw_packet->num_packets < BATADV_NUM_BCASTS_MAX) {
_batadv_add_bcast_packet_to_list(bat_priv, forw_packet,
msecs_to_jiffies(5));
return;
......
......@@ -23,7 +23,7 @@
int batadv_send_skb_packet(struct sk_buff *skb,
struct batadv_hard_iface *hard_iface,
const uint8_t *dst_addr);
bool batadv_send_skb_to_orig(struct sk_buff *skb,
int batadv_send_skb_to_orig(struct sk_buff *skb,
struct batadv_orig_node *orig_node,
struct batadv_hard_iface *recv_if);
void batadv_schedule_bat_ogm(struct batadv_hard_iface *hard_iface);
......
......@@ -154,7 +154,7 @@ static int batadv_interface_tx(struct sk_buff *skb,
0x00, 0x00};
unsigned int header_len = 0;
int data_len = skb->len, ret;
short vid __maybe_unused = -1;
unsigned short vid __maybe_unused = BATADV_NO_FLAGS;
bool do_bcast = false;
uint32_t seqno;
unsigned long brd_delay = 1;
......@@ -303,7 +303,7 @@ void batadv_interface_rx(struct net_device *soft_iface,
struct ethhdr *ethhdr;
struct vlan_ethhdr *vhdr;
struct batadv_header *batadv_header = (struct batadv_header *)skb->data;
short vid __maybe_unused = -1;
unsigned short vid __maybe_unused = BATADV_NO_FLAGS;
__be16 ethertype = __constant_htons(ETH_P_BATMAN);
bool is_bcast;
......@@ -316,7 +316,7 @@ void batadv_interface_rx(struct net_device *soft_iface,
skb_pull_rcsum(skb, hdr_size);
skb_reset_mac_header(skb);
ethhdr = (struct ethhdr *)skb_mac_header(skb);
ethhdr = eth_hdr(skb);
switch (ntohs(ethhdr->h_proto)) {
case ETH_P_8021Q:
......
......@@ -163,10 +163,19 @@ batadv_tt_orig_list_entry_free_ref(struct batadv_tt_orig_list_entry *orig_entry)
call_rcu(&orig_entry->rcu, batadv_tt_orig_list_entry_free_rcu);
}
/**
* batadv_tt_local_event - store a local TT event (ADD/DEL)
* @bat_priv: the bat priv with all the soft interface information
* @tt_local_entry: the TT entry involved in the event
* @event_flags: flags to store in the event structure
*/
static void batadv_tt_local_event(struct batadv_priv *bat_priv,
const uint8_t *addr, uint8_t flags)
struct batadv_tt_local_entry *tt_local_entry,
uint8_t event_flags)
{
struct batadv_tt_change_node *tt_change_node, *entry, *safe;
struct batadv_tt_common_entry *common = &tt_local_entry->common;
uint8_t flags = common->flags | event_flags;
bool event_removed = false;
bool del_op_requested, del_op_entry;
......@@ -176,7 +185,7 @@ static void batadv_tt_local_event(struct batadv_priv *bat_priv,
return;
tt_change_node->change.flags = flags;
memcpy(tt_change_node->change.addr, addr, ETH_ALEN);
memcpy(tt_change_node->change.addr, common->addr, ETH_ALEN);
del_op_requested = flags & BATADV_TT_CLIENT_DEL;
......@@ -184,7 +193,7 @@ static void batadv_tt_local_event(struct batadv_priv *bat_priv,
spin_lock_bh(&bat_priv->tt.changes_list_lock);
list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list,
list) {
if (!batadv_compare_eth(entry->change.addr, addr))
if (!batadv_compare_eth(entry->change.addr, common->addr))
continue;
/* DEL+ADD in the same orig interval have no effect and can be
......@@ -332,7 +341,7 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
}
add_event:
batadv_tt_local_event(bat_priv, addr, tt_local->common.flags);
batadv_tt_local_event(bat_priv, tt_local, BATADV_NO_FLAGS);
check_roaming:
/* Check whether it is a roaming, but don't do anything if the roaming
......@@ -529,8 +538,7 @@ batadv_tt_local_set_pending(struct batadv_priv *bat_priv,
struct batadv_tt_local_entry *tt_local_entry,
uint16_t flags, const char *message)
{
batadv_tt_local_event(bat_priv, tt_local_entry->common.addr,
tt_local_entry->common.flags | flags);
batadv_tt_local_event(bat_priv, tt_local_entry, flags);
/* The local client has to be marked as "pending to be removed" but has
* to be kept in the table in order to send it in a full table
......@@ -584,8 +592,7 @@ uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv,
/* if this client has been added right now, it is possible to
* immediately purge it
*/
batadv_tt_local_event(bat_priv, tt_local_entry->common.addr,
curr_flags | BATADV_TT_CLIENT_DEL);
batadv_tt_local_event(bat_priv, tt_local_entry, BATADV_TT_CLIENT_DEL);
hlist_del_rcu(&tt_local_entry->common.hash_entry);
batadv_tt_local_entry_free_ref(tt_local_entry);
......@@ -791,10 +798,25 @@ batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global,
batadv_tt_orig_list_entry_free_ref(orig_entry);
}
/* caller must hold orig_node refcount */
/**
* batadv_tt_global_add - add a new TT global entry or update an existing one
* @bat_priv: the bat priv with all the soft interface information
* @orig_node: the originator announcing the client
* @tt_addr: the mac address of the non-mesh client
* @flags: TT flags that have to be set for this non-mesh client
* @ttvn: the tt version number ever announcing this non-mesh client
*
* Add a new TT global entry for the given originator. If the entry already
* exists add a new reference to the given originator (a global entry can have
* references to multiple originators) and adjust the flags attribute to reflect
* the function argument.
* If a TT local entry exists for this non-mesh client remove it.
*
* The caller must hold orig_node refcount.
*/
int batadv_tt_global_add(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig_node,
const unsigned char *tt_addr, uint8_t flags,
const unsigned char *tt_addr, uint16_t flags,
uint8_t ttvn)
{
struct batadv_tt_global_entry *tt_global_entry;
......@@ -1600,11 +1622,11 @@ batadv_tt_response_fill_table(uint16_t tt_len, uint8_t ttvn,
tt_tot = tt_len / sizeof(struct batadv_tt_change);
len = tt_query_size + tt_len;
skb = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN);
skb = netdev_alloc_skb_ip_align(NULL, len + ETH_HLEN);
if (!skb)
goto out;
skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
skb_reserve(skb, ETH_HLEN);
tt_response = (struct batadv_tt_query_packet *)skb_put(skb, len);
tt_response->ttvn = ttvn;
......@@ -1665,11 +1687,11 @@ static int batadv_send_tt_request(struct batadv_priv *bat_priv,
if (!tt_req_node)
goto out;
skb = dev_alloc_skb(sizeof(*tt_request) + ETH_HLEN + NET_IP_ALIGN);
skb = netdev_alloc_skb_ip_align(NULL, sizeof(*tt_request) + ETH_HLEN);
if (!skb)
goto out;
skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
skb_reserve(skb, ETH_HLEN);
tt_req_len = sizeof(*tt_request);
tt_request = (struct batadv_tt_query_packet *)skb_put(skb, tt_req_len);
......@@ -1691,7 +1713,7 @@ static int batadv_send_tt_request(struct batadv_priv *bat_priv,
batadv_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_TX);
if (batadv_send_skb_to_orig(skb, dst_orig_node, NULL))
if (batadv_send_skb_to_orig(skb, dst_orig_node, NULL) != NET_XMIT_DROP)
ret = 0;
out:
......@@ -1715,7 +1737,7 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv,
struct batadv_orig_node *req_dst_orig_node;
struct batadv_orig_node *res_dst_orig_node = NULL;
uint8_t orig_ttvn, req_ttvn, ttvn;
int ret = false;
int res, ret = false;
unsigned char *tt_buff;
bool full_table;
uint16_t tt_len, tt_tot;
......@@ -1762,11 +1784,11 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv,
tt_tot = tt_len / sizeof(struct batadv_tt_change);
len = sizeof(*tt_response) + tt_len;
skb = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN);
skb = netdev_alloc_skb_ip_align(NULL, len + ETH_HLEN);
if (!skb)
goto unlock;
skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
skb_reserve(skb, ETH_HLEN);
packet_pos = skb_put(skb, len);
tt_response = (struct batadv_tt_query_packet *)packet_pos;
tt_response->ttvn = req_ttvn;
......@@ -1810,8 +1832,10 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv,
batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX);
if (batadv_send_skb_to_orig(skb, res_dst_orig_node, NULL))
res = batadv_send_skb_to_orig(skb, res_dst_orig_node, NULL);
if (res != NET_XMIT_DROP)
ret = true;
goto out;
unlock:
......@@ -1878,11 +1902,11 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
tt_tot = tt_len / sizeof(struct batadv_tt_change);
len = sizeof(*tt_response) + tt_len;
skb = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN);
skb = netdev_alloc_skb_ip_align(NULL, len + ETH_HLEN);
if (!skb)
goto unlock;
skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
skb_reserve(skb, ETH_HLEN);
packet_pos = skb_put(skb, len);
tt_response = (struct batadv_tt_query_packet *)packet_pos;
tt_response->ttvn = req_ttvn;
......@@ -1925,7 +1949,7 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX);
if (batadv_send_skb_to_orig(skb, orig_node, NULL))
if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP)
ret = true;
goto out;
......@@ -2212,11 +2236,11 @@ static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client,
if (!batadv_tt_check_roam_count(bat_priv, client))
goto out;
skb = dev_alloc_skb(sizeof(*roam_adv_packet) + ETH_HLEN + NET_IP_ALIGN);
skb = netdev_alloc_skb_ip_align(NULL, len + ETH_HLEN);
if (!skb)
goto out;
skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
skb_reserve(skb, ETH_HLEN);
roam_adv_packet = (struct batadv_roam_adv_packet *)skb_put(skb, len);
......@@ -2238,7 +2262,7 @@ static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client,
batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_TX);
if (batadv_send_skb_to_orig(skb, orig_node, NULL))
if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP)
ret = 0;
out:
......
......@@ -33,7 +33,7 @@ void batadv_tt_global_add_orig(struct batadv_priv *bat_priv,
const unsigned char *tt_buff, int tt_buff_len);
int batadv_tt_global_add(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig_node,
const unsigned char *addr, uint8_t flags,
const unsigned char *addr, uint16_t flags,
uint8_t ttvn);
int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset);
void batadv_tt_global_del_orig(struct batadv_priv *bat_priv,
......
......@@ -61,6 +61,7 @@ struct batadv_hard_iface_bat_iv {
* @if_status: status of the interface for batman-adv
* @net_dev: pointer to the net_device
* @frag_seqno: last fragment sequence number sent by this interface
* @num_bcasts: number of payload re-broadcasts on this interface (ARQ)
* @hardif_obj: kobject of the per interface sysfs "mesh" directory
* @refcount: number of contexts the object is used
* @batman_adv_ptype: packet type describing packets that should be processed by
......@@ -76,6 +77,7 @@ struct batadv_hard_iface {
char if_status;
struct net_device *net_dev;
atomic_t frag_seqno;
uint8_t num_bcasts;
struct kobject *hardif_obj;
atomic_t refcount;
struct packet_type batman_adv_ptype;
......@@ -640,7 +642,7 @@ struct batadv_socket_packet {
#ifdef CONFIG_BATMAN_ADV_BLA
struct batadv_bla_backbone_gw {
uint8_t orig[ETH_ALEN];
short vid;
unsigned short vid;
struct hlist_node hash_entry;
struct batadv_priv *bat_priv;
unsigned long lasttime;
......@@ -663,7 +665,7 @@ struct batadv_bla_backbone_gw {
*/
struct batadv_bla_claim {
uint8_t addr[ETH_ALEN];
short vid;
unsigned short vid;
struct batadv_bla_backbone_gw *backbone_gw;
unsigned long lasttime;
struct hlist_node hash_entry;
......
......@@ -464,7 +464,7 @@ int batadv_unicast_generic_send_skb(struct batadv_priv *bat_priv,
goto out;
}
if (batadv_send_skb_to_orig(skb, orig_node, NULL))
if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP)
ret = 0;
out:
......
......@@ -392,12 +392,12 @@ batadv_add_packet(struct batadv_priv *bat_priv,
return NULL;
len = sizeof(*packet) + vis_info_len;
info->skb_packet = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN);
info->skb_packet = netdev_alloc_skb_ip_align(NULL, len + ETH_HLEN);
if (!info->skb_packet) {
kfree(info);
return NULL;
}
skb_reserve(info->skb_packet, ETH_HLEN + NET_IP_ALIGN);
skb_reserve(info->skb_packet, ETH_HLEN);
packet = (struct batadv_vis_packet *)skb_put(info->skb_packet, len);
kref_init(&info->refcount);
......@@ -697,7 +697,7 @@ static void batadv_broadcast_vis_packet(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig_node;
struct batadv_vis_packet *packet;
struct sk_buff *skb;
uint32_t i;
uint32_t i, res;
packet = (struct batadv_vis_packet *)info->skb_packet->data;
......@@ -724,7 +724,8 @@ static void batadv_broadcast_vis_packet(struct batadv_priv *bat_priv,
if (!skb)
continue;
if (!batadv_send_skb_to_orig(skb, orig_node, NULL))
res = batadv_send_skb_to_orig(skb, orig_node, NULL);
if (res == NET_XMIT_DROP)
kfree_skb(skb);
}
rcu_read_unlock();
......@@ -748,7 +749,7 @@ static void batadv_unicast_vis_packet(struct batadv_priv *bat_priv,
if (!skb)
goto out;
if (!batadv_send_skb_to_orig(skb, orig_node, NULL))
if (batadv_send_skb_to_orig(skb, orig_node, NULL) == NET_XMIT_DROP)
kfree_skb(skb);
out:
......@@ -854,13 +855,13 @@ int batadv_vis_init(struct batadv_priv *bat_priv)
if (!bat_priv->vis.my_info)
goto err;
len = sizeof(*packet) + BATADV_MAX_VIS_PACKET_SIZE;
len += ETH_HLEN + NET_IP_ALIGN;
bat_priv->vis.my_info->skb_packet = dev_alloc_skb(len);
len = sizeof(*packet) + BATADV_MAX_VIS_PACKET_SIZE + ETH_HLEN;
bat_priv->vis.my_info->skb_packet = netdev_alloc_skb_ip_align(NULL,
len);
if (!bat_priv->vis.my_info->skb_packet)
goto free_info;
skb_reserve(bat_priv->vis.my_info->skb_packet, ETH_HLEN + NET_IP_ALIGN);
skb_reserve(bat_priv->vis.my_info->skb_packet, ETH_HLEN);
tmp_skb = bat_priv->vis.my_info->skb_packet;
packet = (struct batadv_vis_packet *)skb_put(tmp_skb, sizeof(*packet));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment