Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 219749
b: refs/heads/master
c: e63760e
h: refs/heads/master
i:
  219747: 0dcdc31
v: v3
  • Loading branch information
Andreas Langer authored and Greg Kroah-Hartman committed Sep 5, 2010
1 parent a004bd9 commit 2af9835
Show file tree
Hide file tree
Showing 11 changed files with 417 additions and 29 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 24c76fc07b7680536fa372905f16b57a45c0d514
refs/heads/master: e63760e59542ed872f7a5b1605a46e03b879d909
55 changes: 55 additions & 0 deletions trunk/drivers/staging/batman-adv/bat_sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,58 @@ static ssize_t store_bond(struct kobject *kobj, struct attribute *attr,
return count;
}

static ssize_t show_frag(struct kobject *kobj, struct attribute *attr,
char *buff)
{
struct device *dev = to_dev(kobj->parent);
struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev));
int frag_status = atomic_read(&bat_priv->frag_enabled);

return sprintf(buff, "%s\n",
frag_status == 0 ? "disabled" : "enabled");
}

static ssize_t store_frag(struct kobject *kobj, struct attribute *attr,
char *buff, size_t count)
{
struct device *dev = to_dev(kobj->parent);
struct net_device *net_dev = to_net_dev(dev);
struct bat_priv *bat_priv = netdev_priv(net_dev);
int frag_enabled_tmp = -1;

if (((count == 2) && (buff[0] == '1')) ||
(strncmp(buff, "enable", 6) == 0))
frag_enabled_tmp = 1;

if (((count == 2) && (buff[0] == '0')) ||
(strncmp(buff, "disable", 7) == 0))
frag_enabled_tmp = 0;

if (frag_enabled_tmp < 0) {
if (buff[count - 1] == '\n')
buff[count - 1] = '\0';

bat_err(net_dev,
"Invalid parameter for 'fragmentation' setting on mesh"
"received: %s\n", buff);
return -EINVAL;
}

if (atomic_read(&bat_priv->frag_enabled) == frag_enabled_tmp)
return count;

bat_info(net_dev, "Changing fragmentation from: %s to: %s\n",
atomic_read(&bat_priv->frag_enabled) == 1 ?
"enabled" : "disabled",
frag_enabled_tmp == 1 ? "enabled" : "disabled");

atomic_set(&bat_priv->frag_enabled, (unsigned)frag_enabled_tmp);

update_min_mtu();

return count;
}

static ssize_t show_vis_mode(struct kobject *kobj, struct attribute *attr,
char *buff)
{
Expand Down Expand Up @@ -279,6 +331,7 @@ static ssize_t store_log_level(struct kobject *kobj, struct attribute *attr,
static BAT_ATTR(aggregated_ogms, S_IRUGO | S_IWUSR,
show_aggr_ogms, store_aggr_ogms);
static BAT_ATTR(bonding, S_IRUGO | S_IWUSR, show_bond, store_bond);
static BAT_ATTR(fragmentation, S_IRUGO | S_IWUSR, show_frag, store_frag);
static BAT_ATTR(vis_mode, S_IRUGO | S_IWUSR, show_vis_mode, store_vis_mode);
static BAT_ATTR(orig_interval, S_IRUGO | S_IWUSR,
show_orig_interval, store_orig_interval);
Expand All @@ -289,6 +342,7 @@ static BAT_ATTR(log_level, S_IRUGO | S_IWUSR, show_log_level, store_log_level);
static struct bat_attribute *mesh_attrs[] = {
&bat_attr_aggregated_ogms,
&bat_attr_bonding,
&bat_attr_fragmentation,
&bat_attr_vis_mode,
&bat_attr_orig_interval,
#ifdef CONFIG_BATMAN_ADV_DEBUG
Expand All @@ -308,6 +362,7 @@ int sysfs_add_meshif(struct net_device *dev)
routine as soon as we have it */
atomic_set(&bat_priv->aggregation_enabled, 1);
atomic_set(&bat_priv->bonding_enabled, 0);
atomic_set(&bat_priv->frag_enabled, 1);
atomic_set(&bat_priv->vis_mode, VIS_TYPE_CLIENT_UPDATE);
atomic_set(&bat_priv->orig_interval, 1000);
atomic_set(&bat_priv->log_level, 0);
Expand Down
34 changes: 33 additions & 1 deletion trunk/drivers/staging/batman-adv/hard-interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,11 @@ int hardif_min_mtu(void)
/* allow big frames if all devices are capable to do so
* (have MTU > 1500 + BAT_HEADER_LEN) */
int min_mtu = ETH_DATA_LEN;
/* FIXME: each batman_if will be attached to a softif */
struct bat_priv *bat_priv = netdev_priv(soft_device);

if (atomic_read(&bat_priv->frag_enabled))
goto out;

rcu_read_lock();
list_for_each_entry_rcu(batman_if, &if_list, list) {
Expand All @@ -175,7 +180,7 @@ int hardif_min_mtu(void)
min_mtu);
}
rcu_read_unlock();

out:
return min_mtu;
}

Expand Down Expand Up @@ -261,8 +266,30 @@ int hardif_enable_interface(struct batman_if *batman_if)
orig_hash_add_if(batman_if, bat_priv->num_ifaces);

atomic_set(&batman_if->seqno, 1);
atomic_set(&batman_if->frag_seqno, 1);
bat_info(soft_device, "Adding interface: %s\n", batman_if->dev);

if (atomic_read(&bat_priv->frag_enabled) && batman_if->net_dev->mtu <
ETH_DATA_LEN + BAT_HEADER_LEN)
bat_info(soft_device,
"The MTU of interface %s is too small (%i) to handle "
"the transport of batman-adv packets. Packets going "
"over this interface will be fragmented on layer2 "
"which could impact the performance. Setting the MTU "
"to %zi would solve the problem.\n",
batman_if->dev, batman_if->net_dev->mtu,
ETH_DATA_LEN + BAT_HEADER_LEN);

if (!atomic_read(&bat_priv->frag_enabled) && batman_if->net_dev->mtu <
ETH_DATA_LEN + BAT_HEADER_LEN)
bat_info(soft_device,
"The MTU of interface %s is too small (%i) to handle "
"the transport of batman-adv packets. If you experience"
" problems getting traffic through try increasing the "
"MTU to %zi.\n",
batman_if->dev, batman_if->net_dev->mtu,
ETH_DATA_LEN + BAT_HEADER_LEN);

if (hardif_is_iface_up(batman_if))
hardif_activate_interface(soft_device, bat_priv, batman_if);
else
Expand Down Expand Up @@ -495,6 +522,11 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
ret = recv_unicast_packet(skb, batman_if);
break;

/* fragmented unicast packet */
case BAT_UNICAST_FRAG:
ret = recv_ucast_frag_packet(skb, batman_if);
break;

/* broadcast packet */
case BAT_BCAST:
ret = recv_bcast_packet(skb);
Expand Down
10 changes: 10 additions & 0 deletions trunk/drivers/staging/batman-adv/originator.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "translation-table.h"
#include "routing.h"
#include "hard-interface.h"
#include "unicast.h"

static DECLARE_DELAYED_WORK(purge_orig_wq, purge_orig);

Expand Down Expand Up @@ -95,6 +96,7 @@ static void free_orig_node(void *data)
kfree(neigh_node);
}

frag_list_free(&orig_node->frag_list);
hna_global_del_orig(orig_node, "originator timed out");

kfree(orig_node->bcast_own);
Expand Down Expand Up @@ -157,6 +159,10 @@ struct orig_node *get_orig_node(uint8_t *addr)

size = bat_priv->num_ifaces * sizeof(uint8_t);
orig_node->bcast_own_sum = kzalloc(size, GFP_ATOMIC);

INIT_LIST_HEAD(&orig_node->frag_list);
orig_node->last_frag_packet = 0;

if (!orig_node->bcast_own_sum)
goto free_bcast_own;

Expand Down Expand Up @@ -271,6 +277,10 @@ void purge_orig(struct work_struct *work)
hash_remove_bucket(orig_hash, &hashit);
free_orig_node(orig_node);
}

if (time_after(jiffies, (orig_node->last_frag_packet +
msecs_to_jiffies(FRAG_TIMEOUT))))
frag_list_free(&orig_node->frag_list);
}

spin_unlock_irqrestore(&orig_hash_lock, flags);
Expand Down
26 changes: 20 additions & 6 deletions trunk/drivers/staging/batman-adv/packet.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,15 @@

#define ETH_P_BATMAN 0x4305 /* unofficial/not registered Ethertype */

#define BAT_PACKET 0x01
#define BAT_ICMP 0x02
#define BAT_UNICAST 0x03
#define BAT_BCAST 0x04
#define BAT_VIS 0x05
#define BAT_PACKET 0x01
#define BAT_ICMP 0x02
#define BAT_UNICAST 0x03
#define BAT_BCAST 0x04
#define BAT_VIS 0x05
#define BAT_UNICAST_FRAG 0x06

/* this file is included by batctl which needs these defines */
#define COMPAT_VERSION 11
#define COMPAT_VERSION 13
#define DIRECTLINK 0x40
#define VIS_SERVER 0x20
#define PRIMARIES_FIRST_HOP 0x10
Expand All @@ -47,6 +48,9 @@
#define VIS_TYPE_SERVER_SYNC 0
#define VIS_TYPE_CLIENT_UPDATE 1

/* fragmentation defines */
#define UNI_FRAG_HEAD 0x01

struct batman_packet {
uint8_t packet_type;
uint8_t version; /* batman version field */
Expand Down Expand Up @@ -96,6 +100,16 @@ struct unicast_packet {
uint8_t ttl;
} __attribute__((packed));

struct unicast_frag_packet {
uint8_t packet_type;
uint8_t version; /* batman version field */
uint8_t dest[6];
uint8_t ttl;
uint8_t flags;
uint8_t orig[6];
uint16_t seqno;
} __attribute__((packed));

struct bcast_packet {
uint8_t packet_type;
uint8_t version; /* batman version field */
Expand Down
115 changes: 95 additions & 20 deletions trunk/drivers/staging/batman-adv/routing.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "ring_buffer.h"
#include "vis.h"
#include "aggregation.h"
#include "unicast.h"

static DECLARE_WAIT_QUEUE_HEAD(thread_wait);

Expand Down Expand Up @@ -1105,43 +1106,43 @@ struct neigh_node *find_router(struct orig_node *orig_node,
return router;
}

int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if)
static int check_unicast_packet(struct sk_buff *skb, int hdr_size)
{
struct unicast_packet *unicast_packet;
struct orig_node *orig_node;
struct neigh_node *router;
struct ethhdr *ethhdr;
struct batman_if *batman_if;
struct sk_buff *skb_old;
uint8_t dstaddr[ETH_ALEN];
int hdr_size = sizeof(struct unicast_packet);
unsigned long flags;

/* drop packet if it has not necessary minimum size */
if (skb_headlen(skb) < hdr_size)
return NET_RX_DROP;
return -1;

ethhdr = (struct ethhdr *) skb_mac_header(skb);

/* packet with unicast indication but broadcast recipient */
if (is_bcast(ethhdr->h_dest))
return NET_RX_DROP;
return -1;

/* packet with broadcast sender address */
if (is_bcast(ethhdr->h_source))
return NET_RX_DROP;
return -1;

/* not for me */
if (!is_my_mac(ethhdr->h_dest))
return NET_RX_DROP;
return -1;

unicast_packet = (struct unicast_packet *) skb->data;
return 0;
}

/* packet for me */
if (is_my_mac(unicast_packet->dest)) {
interface_rx(skb, hdr_size);
return NET_RX_SUCCESS;
}
static int route_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if,
int hdr_size)
{
struct orig_node *orig_node;
struct neigh_node *router;
struct batman_if *batman_if;
struct sk_buff *skb_old;
uint8_t dstaddr[ETH_ALEN];
unsigned long flags;
struct unicast_packet *unicast_packet =
(struct unicast_packet *) skb->data;
struct ethhdr *ethhdr = (struct ethhdr *) skb_mac_header(skb);

/* TTL exceeded */
if (unicast_packet->ttl < 2) {
Expand Down Expand Up @@ -1172,7 +1173,7 @@ int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if)
spin_unlock_irqrestore(&orig_hash_lock, flags);

/* create a copy of the skb, if needed, to modify it. */
if (!skb_clone_writable(skb, sizeof(struct unicast_packet))) {
if (!skb_clone_writable(skb, hdr_size)) {
skb_old = skb;
skb = skb_copy(skb, GFP_ATOMIC);
if (!skb)
Expand All @@ -1191,6 +1192,80 @@ int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if)
return NET_RX_SUCCESS;
}

int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if)
{
struct unicast_packet *unicast_packet;
int hdr_size = sizeof(struct unicast_packet);

if (check_unicast_packet(skb, hdr_size) < 0)
return NET_RX_DROP;

unicast_packet = (struct unicast_packet *) skb->data;

/* packet for me */
if (is_my_mac(unicast_packet->dest)) {
interface_rx(skb, hdr_size);
return NET_RX_SUCCESS;
}

return route_unicast_packet(skb, recv_if, hdr_size);
}

int recv_ucast_frag_packet(struct sk_buff *skb, struct batman_if *recv_if)
{
struct unicast_frag_packet *unicast_packet;
struct orig_node *orig_node;
struct frag_packet_list_entry *tmp_frag_entry;
int hdr_size = sizeof(struct unicast_frag_packet);
unsigned long flags;

if (check_unicast_packet(skb, hdr_size) < 0)
return NET_RX_DROP;

unicast_packet = (struct unicast_frag_packet *) skb->data;

/* packet for me */
if (is_my_mac(unicast_packet->dest)) {

spin_lock_irqsave(&orig_hash_lock, flags);
orig_node = ((struct orig_node *)
hash_find(orig_hash, unicast_packet->orig));

if (!orig_node) {
pr_warning("couldn't find orig node for "
"fragmentation\n");
spin_unlock_irqrestore(&orig_hash_lock, flags);
return NET_RX_DROP;
}

orig_node->last_frag_packet = jiffies;

if (list_empty(&orig_node->frag_list))
create_frag_buffer(&orig_node->frag_list);

tmp_frag_entry =
search_frag_packet(&orig_node->frag_list,
unicast_packet);

if (!tmp_frag_entry) {
create_frag_entry(&orig_node->frag_list, skb);
spin_unlock_irqrestore(&orig_hash_lock, flags);
return NET_RX_SUCCESS;
}

skb = merge_frag_packet(&orig_node->frag_list,
tmp_frag_entry, skb);
spin_unlock_irqrestore(&orig_hash_lock, flags);
if (!skb)
return NET_RX_DROP;

interface_rx(skb, hdr_size);
return NET_RX_SUCCESS;
}

return route_unicast_packet(skb, recv_if, hdr_size);
}

int recv_bcast_packet(struct sk_buff *skb)
{
struct orig_node *orig_node;
Expand Down
Loading

0 comments on commit 2af9835

Please sign in to comment.