PATCH fragmentation of unicast packets
If fragmentation is on, the mtu of the bat interface will be set to 1500 and bigger packets will be splitted in two parts. The receiver stores the packets in a buffer list for each originator, which will be created with the first fragmented packet. For this handling i added a sequenznumber and the orig address to the unicast_packet definition.
regards,
Andreas
--- batman-adv/Makefile.kbuild | 2 +- batman-adv/bat_sysfs.c | 55 ++++++++++++++++ batman-adv/fragmentation.c | 148 +++++++++++++++++++++++++++++++++++++++++++ batman-adv/fragmentation.h | 34 ++++++++++ batman-adv/hard-interface.c | 15 ++++- batman-adv/originator.c | 13 ++++ batman-adv/packet.h | 7 ++ batman-adv/routing.c | 35 ++++++++++ batman-adv/soft-interface.c | 88 ++++++++++++++++++++++---- batman-adv/types.h | 9 +++ 10 files changed, 390 insertions(+), 16 deletions(-) create mode 100644 batman-adv/fragmentation.c create mode 100644 batman-adv/fragmentation.h
batman-adv/Makefile.kbuild +0 -1
@@ -32,4 +32,4 @@ EXTRA_CFLAGS += -DREVISION_VERSION=\"$(REVISION)\" endif obj-m += batman-adv.o -batman-adv-objs := main.o bat_debugfs.o bat_sysfs.o send.o routing.o soft-interface.o
icmp_socket.o translation-table.o bitarray.o hash.o ring_buffer.o vis.o hard-interface.o aggregation.o originator.o gateway_common.o gateway_client.o $(shell [ "2" -eq "$(VERSION)" ] 2>&- && [ "6" -eq "$(PATCHLEVEL)" ] 2>&- && [ "$(SUBLEVEL)" -le "28" ] 2>&- && echo bat_printk.o) +batman-adv-objs := main.o bat_debugfs.o bat_sysfs.o send.o routing.o soft-interface.o icmp_socket.o translation-table.o bitarray.o hash.o ring_buffer.o vis.o hard-interface.o aggregation.o originator.o gateway_common.o gateway_client.o fragmentation.o $(shell [ "2" -eq "$(VERSION)" ] 2>&- && [ "6" -eq "$(PATCHLEVEL)" ] 2>&- && [ "$(SUBLEVEL)" -le "28" ] 2>&- && echo bat_printk.o) diff --git a/batman-adv/bat_sysfs.c b/batman-adv/bat_sysfs.c index 68ce453..74d388a 100644 --- a/batman-adv/bat_sysfs.c +++ b/batman-adv/bat_sysfs.c @@ -136,6 +136,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';
+
+ printk(KERN_ERR "batman-adv:Invalid parameter for 'frag' setting on mesh %s
received: %s\n",
+ net_dev->name, buff);
+ return -EINVAL;
+ }
+
+ if (atomic_read(&bat_priv->frag_enabled) == frag_enabled_tmp)
+ return count;
+
+ printk(KERN_INFO "batman-adv:Changing frag from: %s to: %s on mesh: %s\n",
+ atomic_read(&bat_priv->frag_enabled) == 1 ? + "enabled" : "disabled", + frag_enabled_tmp == 1 ? "enabled" : "disabled", + net_dev->name);
+
+ 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)
{
@@ -279,6 +331,7 @@ static ssize_t store_orig_interval(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(gw_mode, S_IRUGO | S_IWUSR, show_gw_mode, store_gw_mode);
static BAT_ATTR(orig_interval, S_IRUGO | S_IWUSR,
@@ -287,6 +340,7 @@ static BAT_ATTR(orig_interval, S_IRUGO | S_IWUSR,
static struct bat_attribute *mesh_attrs[] = {
&bat_attr_aggregated_ogms,
&bat_attr_bonding,
+ &bat_attr_fragmentation,
&bat_attr_vis_mode,
&bat_attr_gw_mode,
&bat_attr_orig_interval,
@@ -304,6 +358,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, 0);
atomic_set(&bat_priv->vis_mode, VIS_TYPE_CLIENT_UPDATE); atomic_set(&bat_priv->gw_mode, GW_MODE_OFF);
atomic_set(&bat_priv->gw_class, 0);
batman-adv/fragmentation.c new file +148 -0
148 lines not on this page · raw message
batman-adv/fragmentation.h new file +34 -0
@@ -0,0 +1,34 @@ +/* +* Copyright (C) 2007-2010 B.A.T.M.A.N. contributors: +* +* Andreas Langer +* +* 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 +* +*/ + +#define FRAG_TIMEOUT 60000/* purge frag list entrys after time in ms */ +#define FRAG_BUFFER_SIZE 6/* number of list elements in buffer */ +#define FRAG_MAX_SEQ 65535 + +extern struct sk_buff *merge_frag_packet (struct list_head *head, +struct frag_packet_list_entry *tfp, +struct sk_buff *skb); + +extern void create_frag_entry (struct list_head *head,struct sk_buff *skb); +extern void create_frag_buffer (struct list_head *head); +extern struct frag_packet_list_entry *search_frag_packet (struct list_head *head, +struct unicast_packet *up); +extern void frag_list_free (struct list_head *head);
batman-adv/hard-interface.c +12 -3
@@ -168,13 +168,20 @@ 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);rcu_read_lock ();list_for_each_entry_rcu (batman_if, &if_list, list) {if ((batman_if->if_status ==IF_ACTIVE ) || - (batman_if->if_status ==IF_TO_BE_ACTIVATED )) - min_mtu =MIN (batman_if->net_dev->mtu -BAT_HEADER_LEN , - min_mtu); + (batman_if->if_status ==IF_TO_BE_ACTIVATED )) { + +if (atomic_read (&bat_priv->frag_enabled)) + min_mtu =MIN (batman_if->net_dev->mtu, min_mtu); +else + min_mtu =MIN (batman_if->net_dev->mtu - +BAT_HEADER_LEN , min_mtu); + } }rcu_read_unlock ();
@@ -189,6 +196,7 @@ void update_min_mtu(void) min_mtu =hardif_min_mtu ();if (soft_device->mtu != min_mtu) soft_device->mtu = min_mtu; + } static void hardif_activate_interface(struct bat_priv *bat_priv,
@@ -268,6 +276,7 @@ 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 );printk (KERN_INFO "batman-adv:Adding interface: %s\n" , batman_if->dev);if (hardif_is_iface_up (batman_if))
batman-adv/originator.c +13 -0
@@ -29,6 +29,7 @@#include "compat.h" #include "gateway_client.h" #include "hard-interface.h" +#include "fragmentation.h" static DECLARE_DELAYED_WORK(purge_orig_wq, purge_orig);
@@ -58,6 +59,7 @@ err:return 0 ; } +struct neigh_node *create_neighbor (struct orig_node *orig_node,struct orig_node *orig_neigh_node,uint8_t *neigh,struct batman_if *if_incoming)
@@ -94,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);
@@ -155,6 +158,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;
@@ -269,6 +276,12 @@ 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);
batman-adv/packet.h +7 -0
@@ -47,6 +47,10 @@#define VIS_TYPE_SERVER_SYNC 0#define VIS_TYPE_CLIENT_UPDATE 1 +/* fragmentation defines */ +#define UNI_IS_FRAG 0x01 +#define UNI_FRAG_HEAD 0x02 +struct batman_packet {uint8_t packet_type;uint8_t version;/* batman version field */
@@ -95,7 +99,10 @@ struct unicast_packet {uint8_t packet_type;uint8_t version;/* batman version field */ uint8_t dest[6 ]; +uint8_t orig[6 ];uint8_t ttl; +uint8_t flags; +uint16_t seqno; } __attribute__((packed));struct bcast_packet {
batman-adv/routing.c +35 -0
@@ -34,6 +34,7 @@#include "aggregation.h" #include "compat.h" #include "gateway_client.h" +#include "fragmentation.h" static DECLARE_WAIT_QUEUE_HEAD (thread_wait);
@@ -1100,6 +1101,7 @@ int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if)struct ethhdr *ethhdr;struct batman_if *batman_if;struct sk_buff *skb_old; +struct frag_packet_list_entry *tmp_frag_entry;uint8_t dstaddr[ETH_ALEN ];int hdr_size =sizeof (struct unicast_packet );unsigned long flags;
@@ -1126,6 +1128,39 @@ int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if)/* packet for me */ if (is_my_mac (unicast_packet->dest)) { + +/* check if unicast packet fragmented */ + +if (unicast_packet->flags &UNI_IS_FRAG ) { + +/* TODO: spinlock ??? */ + orig_node = ((struct orig_node *) +hash_find (orig_hash, unicast_packet->orig)); + +if (!orig_node) { +printk (KERN_WARNING +"frag: couldn't find orig node\n" ); +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); +return NET_RX_SUCCESS ; + } + + skb =merge_frag_packet (&orig_node->frag_list, + tmp_frag_entry, skb); + } +interface_rx (skb, hdr_size);return NET_RX_SUCCESS ; }
batman-adv/soft-interface.c +76 -12
122 lines not on this page · raw message
batman-adv/types.h +9 -0
@@ -43,6 +43,7 @@ struct batman_if {char addr_str[ETH_STR_LEN ];struct net_device *net_dev;atomic_t seqno; +atomic_t frag_seqno;unsigned char *packet_buff;int packet_len;struct kobject *hardif_obj;
@@ -84,6 +85,8 @@ struct orig_node {TYPE_OF_WORD bcast_bits[NUM_WORDS ];uint32_t last_bcast_seqno;struct list_head neigh_list; +struct list_head frag_list; +unsigned long last_frag_packet;struct {uint8_t candidates;struct neigh_node *selected;
@@ -120,6 +123,7 @@ struct bat_priv {struct net_device_stats stats;atomic_t aggregation_enabled;atomic_t bonding_enabled; +atomic_t frag_enabled;atomic_t vis_mode;atomic_t gw_mode;atomic_t gw_class;
@@ -184,4 +188,9 @@ struct if_list_entry { struct hlist_node list; }; +struct frag_packet_list_entry { +struct list_head list; +uint16_t seqno; +struct sk_buff *skb; +};#endif /* _NET_BATMAN_ADV_TYPES_H_ */
Signature · 1 line
1.7.0.4
Quoted 10 lines · Andreas Langer
If fragmentation is on, the mtu of the bat interface will be set to 1500 and bigger packets will be splitted in two parts. The receiver stores the packets in a buffer list for each originator, which will be created with the first fragmented packet. For this handling i added a sequenznumber and the orig address to the
unicast_packetdefinition.regards,
AndreasSigned-off-by Andreas Langer <an.langer at gmx.de>
This patch cannot be applied because the mailer added automatically wordwraps. Either find a way to forbid such a behavior for your mailer or try to use git-send-email. There are explanations how you do that can be found at
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=Documentation/email-clients.txt
And please try to check your patches with checkpatch.pl from the linux sources. You will notice that you've removed a newline after the function bat_set_rx_csum. This is important because we try to submit those patches to the mainline linux kernel.
There are also other styling changes I don't understand. For example a newline before create_neighbor. I haven't checked really more as I couldn't apply it.
And can you try to add [] around PATCH in the summary line and remove the regards... stuff from the commits message? Otherwise it will be part of the commit message and the patch we send to the kernel folks.
For more information please read
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=Documentation/SubmittingPatches
Best regards,
Sven
Quoted 3 lines · Sven Eckelmann
And can you try to add [] around PATCH in the summary line and remove the regards... stuff from the commits message? Otherwise it will be part of the commit message and the patch we send to the kernel folks.
Ah, forgot something. Could you also change the subject to include which parts it touches ("batctl: ", "batman-adv: "). So the subject line should look something like:
* [PATCH] batman-adv: Implement fragmentation of unicast packets
* [PATCH] batctl: Add fragmentation handling
And why does your patch change the packet format and doesn't increase the COMPAT_VERSION to 12 (11 is currently used in maint)? Maybe there are other changes coming which are merged at the same time... I am just being curious. :)
thanks,
Sven
Marek has published some patches for the debugging infrastructure. Please adjust your patch for that.
Review
Quoted 5 lines · Andreas Langer
(quoted diff) +5
-0+ if (frag_enabled_tmp < 0) { + if (buff[count - 1] == '\n') + buff[count - 1] = '\0'; + + printk(KERN_ERR "batman-adv:Invalid parameter for 'frag' setting on
mesh
Review
Quoted 2 lines
%s received: %s\n",
(quoted diff) +1
-0+ net_dev->name, buff);
Please change the printk to a bat_err (remove the batman-adv: and the information on which mesh it happened).
Review
Quoted 8 lines
(quoted diff) +4
-0+ if (atomic_read(&bat_priv->frag_enabled) == frag_enabled_tmp) + return count; + + printk(KERN_INFO "batman-adv:Changing frag from: %s to: %s on mesh:%s\n", +
atomic_read(&bat_priv->frag_enabled)== 1 ?(quoted diff) +3
-0+ "enabled" : "disabled", + frag_enabled_tmp == 1 ? "enabled" : "disabled", + net_dev->name);
That printk to a bat_err (remove the batman-adv: and the information on which mesh it happened).
batman-adv/hard-interface.c int hardif_enable_interface(struct batman_if *batman_if) · line 280
Quoted 3 lines
batman-adv/hard-interface.c +1
-0atomic_set (&batman_if->seqno,1 ); +atomic_set (&batman_if->frag_seqno,1 );printk (KERN_INFO "batman-adv:Adding interface: %s\n" , batman_if->dev);
Please rebase your patch on top of the current trunk. Otherwise we have an merge failure here.
batman-adv/routing.c int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if) · line 1144
Quoted 5 lines
batman-adv/routing.c +5
-0+if (!orig_node) { +printk (KERN_WARNING +"frag: couldn't find orig node\n" ); +return NET_RX_DROP ; + }
Please change the printk to pr_warning.
Best regards,
Sven