[B.A.T.M.A.N.] [PATCH] batman-adv: receive packets directly using skbs

2009-12-23 Thread Simon Wunderlich
This patch removes the (ugly and racy) packet receiving thread and the 
kernel socket usage. Instead, packets are received directly by registering 
the ethernet type and handling skbs instead of self-allocated buffers. 

Some consequences and comments:
 * we don't copy the payload data when forwarding/sending/receiving data 
   anymore. This should boost performance.
 * packets from/to different interfaces can be (theoretically) processed
   simultaneously. Only the big originator hash lock might be in the way.
 * this might introduce new race conditions.
 * aggregation and vis code still use packet buffers and are not (yet) 
   converted.

This is the first version of this patch to be released, i would consider
it experimental and would hereby like to as for reviews before committing
it. Some things you might want to test:

 * performace differences (are there any?)
 * do all components still work? (vis, batctl ping, ...)
 * do high load situations or multiple interfaces cause problems
 * any memory leaks i might have overlooked?

I did some tests on my 9 node qemu environment and could confirm that 
usual sending/receiving, forwarding, vis, batctl ping etc works. However
i can not talk about the performance from this setup.

Signed-off-by: Simon Wunderlich s...@hrz.tu-chemnitz.de
---
Index: a/batman-adv-kernelland/types.h
===
--- a/batman-adv-kernelland/types.h (revision 1507)
+++ b/batman-adv-kernelland/types.h (working copy)
@@ -39,7 +39,6 @@
char if_active;
char addr_str[ETH_STR_LEN];
struct net_device *net_dev;
-   struct socket *raw_sock;
atomic_t seqno;
unsigned char *packet_buff;
int packet_len;
@@ -113,6 +112,7 @@
struct hlist_node list;
unsigned long send_time;
uint8_t own;
+   struct sk_buff *skb;
unsigned char *packet_buff;
uint16_t packet_len;
uint32_t direct_link_flags;
Index: a/batman-adv-kernelland/send.c
===
--- a/batman-adv-kernelland/send.c  (revision 1507)
+++ b/batman-adv-kernelland/send.c  (working copy)
@@ -58,25 +58,53 @@
return send_time;
 }
 
-/* sends a raw packet. */
-void send_raw_packet(unsigned char *pack_buff, int pack_buff_len,
-struct batman_if *batman_if, uint8_t *dst_addr)
+/* send out an already prepared packet to the given address via the
+ * specified batman interface */
+int send_skb_packet(struct sk_buff *skb,
+   struct batman_if *batman_if,
+   uint8_t *dst_addr)
 {
struct ethhdr *ethhdr;
-   struct sk_buff *skb;
-   int retval;
-   char *data;
 
if (batman_if-if_active != IF_ACTIVE)
-   return;
+   goto send_skb_err;
 
+   if (unlikely(!batman_if-net_dev))
+   goto send_skb_err;
+
if (!(batman_if-net_dev-flags  IFF_UP)) {
printk(KERN_WARNING
   batman-adv:Interface %s is not up - can't send packet 
via that interface!\n,
   batman_if-dev);
-   return;
+   goto send_skb_err;
}
 
+
+   ethhdr = (struct ethhdr *) skb_mac_header(skb);
+   memcpy(ethhdr-h_source, batman_if-net_dev-dev_addr, ETH_ALEN);
+   memcpy(ethhdr-h_dest, dst_addr, ETH_ALEN);
+   ethhdr-h_proto = __constant_htons(ETH_P_BATMAN);
+
+   skb-dev = batman_if-net_dev;
+
+   /* 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. */
+
+   return dev_queue_xmit(skb);
+send_skb_err:
+   kfree_skb(skb);
+   return NET_XMIT_DROP;
+}
+
+/* sends a raw packet. */
+void send_raw_packet(unsigned char *pack_buff, int pack_buff_len,
+struct batman_if *batman_if, uint8_t *dst_addr)
+{
+   struct sk_buff *skb;
+   char *data;
+
+
skb = dev_alloc_skb(pack_buff_len + sizeof(struct ethhdr));
if (!skb)
return;
@@ -84,25 +112,12 @@
 
memcpy(data + sizeof(struct ethhdr), pack_buff, pack_buff_len);
 
-   ethhdr = (struct ethhdr *) data;
-   memcpy(ethhdr-h_source, batman_if-net_dev-dev_addr, ETH_ALEN);
-   memcpy(ethhdr-h_dest, dst_addr, ETH_ALEN);
-   ethhdr-h_proto = __constant_htons(ETH_P_BATMAN);
-
skb_reset_mac_header(skb);
skb_set_network_header(skb, ETH_HLEN);
skb-priority = TC_PRIO_CONTROL;
skb-protocol = __constant_htons(ETH_P_BATMAN);
-   skb-dev = batman_if-net_dev;
 
-   /* 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. */
-   retval = 

Re: [B.A.T.M.A.N.] [PATCH] batman-adv: receive packets directly using skbs

2009-12-23 Thread Sven Eckelmann
Simon Wunderlich wrote:
 +/* receive a packet with the batman ethertype coming on a hard
 + * interface */
 +int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
 + struct packet_type *ptype, struct net_device *orig_dev)
 +{
 + struct batman_packet *batman_packet;
 + struct batman_if *batman_if;
 + struct net_device_stats *stats;
 + int ret;
 +
 +skb = skb_share_check(skb, GFP_ATOMIC);
 +
 +if (skb == NULL)
 + goto err_free;
 +
 + /* packet should hold at least type and version */
 + if (unlikely(skb-len  2))
 + goto err_free;

Len field includes the length of the data in the main socket buffer and 
possible fragments attached to the main socket buffer. This length is changed 
when you move from layer to layer. So it is ok to test for 2 here to check if 
it is enough data for version and type.

 +
 + batman_if = find_batman_if(skb-dev);
 + if (!batman_if)
 + goto err_free;
 +
 +stats = skb-dev-stats;
 +stats-rx_packets++;
 +stats-rx_bytes += skb-len;
 +
 +
 + /* push back, we want to look at the ethernet header as well. */
 + skb_push(skb, sizeof(struct ethhdr));
 + skb_reset_mac_header(skb);
 +
 + batman_packet = (struct batman_packet *)(skb-data
 + + sizeof(struct ethhdr));
 +
 + if (batman_packet-version != COMPAT_VERSION) {
 + bat_dbg(DBG_BATMAN,
 + Drop packet: incompatible batman version (%i)\n,
 + batman_packet-version);
 + goto err_free;
 + }
Here you try to to access data which may be fragmented over different buffers. 
This could for example happen if we send our data over a layer which fragments 
it.

In the normal scenario of sending it directly over ethernet this shouldn't 
happen, but that doesn't mean that nobody wants to do something special.

There are different other positions like recv_bat_packet where this is 
ignored.

Maybe someone knows why this could never happen, but everything I have read 
was more like you have to deal with it.

 -static void recv_icmp_packet(struct ethhdr *ethhdr,
 -  unsigned char *packet_buff,
 -  int result,
 -  struct batman_if *batman_if)
 +int recv_icmp_packet(struct sk_buff *skb)
  {
   struct icmp_packet *icmp_packet;
 + struct ethhdr *ethhdr;
   struct orig_node *orig_node;
 + int hdr_size = sizeof(struct icmp_packet) + sizeof(struct ethhdr);
 + int ret;
 
 + /* drop packet if it has not necessary minimum size */
 + if (skb-len  hdr_size)
 + return NET_RX_DROP;
 +
 + ethhdr = (struct ethhdr *)skb_mac_header(skb);
 +
   /* packet with unicast indication but broadcast recipient */
   if (is_bcast(ethhdr-h_dest))
 - return;
 + return NET_RX_DROP;
 
   /* packet with broadcast sender address */
   if (is_bcast(ethhdr-h_source))
 - return;
 + return NET_RX_DROP;
 
   /* not for me */
   if (!is_my_mac(ethhdr-h_dest))
 - return;
 + return NET_RX_DROP;
 
 - /* drop packet if it has not necessary minimum size */
 - if (result  sizeof(struct ethhdr) + sizeof(struct icmp_packet))
 - return;
 -
   icmp_packet = (struct icmp_packet *)
 - (packet_buff + sizeof(struct ethhdr));
 + (skb-data + sizeof(struct ethhdr));
 
   /* packet for me */
   if (is_my_mac(icmp_packet-dst))
 - recv_my_icmp_packet(ethhdr, icmp_packet, packet_buff, result);
 + return recv_my_icmp_packet(skb);
 
   /* TTL exceeded */
   if (icmp_packet-ttl  2) {
 - recv_icmp_ttl_exceeded(icmp_packet, ethhdr, packet_buff, result,
 -batman_if);
 - return;
 + return recv_icmp_ttl_exceeded(skb);
 
   }
 
 + ret = NET_RX_DROP;
 +
   /* get routing information */
   spin_lock(orig_hash_lock);
   orig_node = ((struct orig_node *)
 @@ -725,49 +721,51 @@
   icmp_packet-ttl--;

You are modify the data inside the socket buffer (not the control structure 
but the real data), but I cannot see where you created a private copy of it. 
Data of cloned copies is not allowed to be changed. You must use (p)skb_copy 
(it clones the the data too and not only the sk_buff structure).

This is explained in Understanding Linux Network Internals, Christian 
Benvenuti, December 2005, O'Reilly, 2.1.5.5. Cloning and copying buffers


Best regards,
Sven


signature.asc
Description: This is a digitally signed message part.


[B.A.T.M.A.N.] can't start batmand

2009-12-23 Thread Conner, Eric
I tried to start batmand with 

 

batmand wlan0

 

got back and error stating

 

which iptables  /dev/null returned an error

 

Does anyone know what is the cause and/or solution to this problem?

 

Thanks

Eric

 



Re: [B.A.T.M.A.N.] can't start batmand

2009-12-23 Thread Sven Eckelmann
Conner, Eric wrote:
 Does anyone know what is the cause and/or solution to this problem?
Either iptables is not installed, iptables not installed in a path which is is 
part of $PATH, batmand is not started as root or which is not installed/not a 
builtin function of the shell.

Best regards,
Sven


signature.asc
Description: This is a digitally signed message part.


Re: [B.A.T.M.A.N.] [PATCH] batman-adv: receive packets directly using skbs

2009-12-23 Thread Sven Eckelmann
On Wed, Dec 23, 2009 at 09:34:17AM -0800, Gus Wirth wrote:
 On 12/23/2009 02:20 AM, Sven Eckelmann wrote:
 [snip]
  This is explained in Understanding Linux Network Internals, Christian 
  Benvenuti, December 2005, O'Reilly, 2.1.5.5. Cloning and copying 
  buffers
 
 Where did the 2.1.5.5 come from?

Second chapter, first section, fifth subsection, fifth subsubsection. Simple
counting :)

But yes, some eBooks from oreilly seem to have that numbers. Cannot tell for
sure if they are the same books you can download from them, but my library
provides them that way. Publisher for that ebook is Safari Books.

http://proquest.safaribooksonline.com/0596002556

Just noticed that the safari books image view (aka buggy flash viewer) also
doesn't display the subsection numbers - but the HTML view does.

Best regards,
Sven


signature.asc
Description: Digital signature