* [B.A.T.M.A.N.] [PATCH v3] batman-adv: Record route for ICMP messages
@ 2010-02-15 21:34 Daniel Seither
2010-02-16 10:29 ` Marek Lindner
0 siblings, 1 reply; 6+ messages in thread
From: Daniel Seither @ 2010-02-15 21:34 UTC (permalink / raw)
To: The list for a Better Approach To Mobile Ad-hoc Networking
The standard layer 3 ping utility can use the record route (RR) option
of IP to collect route data for sent ping messages (ping -R). This
patch introduces comparable functionality for batman-adv ICMP messages.
The patch adds a second batman ICMP packet format (icmp_packet_rr) such
that up to 17 MAC addresses can be recorded (sufficient for up to 8
hops per direction). When no RR is wanted, the old icmp_packet without
the RR overhead can be sent.
batctl is extended to recognize the -R option for the ping subcommand.
The output should be the same as for the standard iputils ping program.
For this, the destination host is printed two times.
Signed-off-by: Daniel Seither <post@tiwoc.de>
---
Index: batman-adv-kernelland/types.h
===================================================================
--- batman-adv-kernelland/types.h (revision 1573)
+++ batman-adv-kernelland/types.h (working copy)
@@ -106,7 +106,7 @@
struct device_packet {
struct list_head list;
- struct icmp_packet icmp_packet;
+ struct icmp_packet_rr icmp_packet;
};
struct hna_local_entry {
Index: batman-adv-kernelland/packet.h
===================================================================
--- batman-adv-kernelland/packet.h (revision 1573)
+++ batman-adv-kernelland/packet.h (working copy)
@@ -26,6 +26,7 @@
#define BAT_UNICAST 0x03
#define BAT_BCAST 0x04
#define BAT_VIS 0x05
+#define BAT_ICMP_RR 0x06
/* this file is included by batctl which needs these defines */
#define COMPAT_VERSION 9
@@ -71,6 +72,23 @@
uint8_t uid;
} __attribute__((packed));
+#define BAT_RR_LEN 16
+
+/* icmp_packet_rr must start with all fields from imcp_packet
+ as this is assumed by code that handles ICMP packets */
+struct icmp_packet_rr {
+ uint8_t packet_type;
+ uint8_t version; /* batman version field */
+ uint8_t msg_type; /* see ICMP message types above */
+ uint8_t ttl;
+ uint8_t dst[6];
+ uint8_t orig[6];
+ uint16_t seqno;
+ uint8_t uid;
+ uint8_t rr_cur;
+ uint8_t rr[BAT_RR_LEN][ETH_ALEN];
+} __attribute__((packed));
+
struct unicast_packet {
uint8_t packet_type;
uint8_t version; /* batman version field */
Index: batman-adv-kernelland/device.c
===================================================================
--- batman-adv-kernelland/device.c (revision 1573)
+++ batman-adv-kernelland/device.c (working copy)
@@ -165,6 +165,7 @@
struct device_packet *device_packet;
int error;
unsigned long flags;
+ size_t packet_len = sizeof(struct icmp_packet);
if ((file->f_flags & O_NONBLOCK) && (device_client->queue_len == 0))
return -EAGAIN;
@@ -190,15 +191,18 @@
spin_unlock_irqrestore(&device_client->lock, flags);
+ if (device_packet->icmp_packet.packet_type == BAT_ICMP_RR)
+ packet_len = sizeof(struct icmp_packet_rr);
+
error = __copy_to_user(buf, &device_packet->icmp_packet,
- sizeof(struct icmp_packet));
+ packet_len);
kfree(device_packet);
if (error)
return error;
- return sizeof(struct icmp_packet);
+ return packet_len;
}
ssize_t bat_device_write(struct file *file, const char __user *buff,
@@ -206,28 +210,42 @@
{
struct device_client *device_client =
(struct device_client *)file->private_data;
- struct icmp_packet icmp_packet;
+ struct icmp_packet_rr icmp_packet;
struct orig_node *orig_node;
struct batman_if *batman_if;
uint8_t dstaddr[ETH_ALEN];
unsigned long flags;
+ size_t packet_len = sizeof(struct icmp_packet);
+ int with_rr = 0;
if (len < sizeof(struct icmp_packet)) {
bat_dbg(DBG_BATMAN, "batman-adv:Error - can't send packet from char device: invalid packet size\n");
return -EINVAL;
}
- if (!access_ok(VERIFY_READ, buff, sizeof(struct icmp_packet)))
+ if (len >= sizeof(struct icmp_packet_rr)) {
+ with_rr = 1;
+ packet_len = sizeof(struct icmp_packet_rr);
+ }
+
+ if (!access_ok(VERIFY_READ, buff, packet_len))
return -EFAULT;
- if (__copy_from_user(&icmp_packet, buff, sizeof(icmp_packet)))
+ if (__copy_from_user(&icmp_packet, buff, packet_len))
return -EFAULT;
- if (icmp_packet.packet_type != BAT_ICMP) {
- bat_dbg(DBG_BATMAN, "batman-adv:Error - can't send packet from char device: got bogus packet type (expected: BAT_ICMP)\n");
+ if (icmp_packet.packet_type != BAT_ICMP
+ && icmp_packet.packet_type != BAT_ICMP_RR) {
+ bat_dbg(DBG_BATMAN, "batman-adv:Error - can't send packet from char device: got bogus packet type (expected: BAT_ICMP or BAT_ICMP_RR)\n");
return -EINVAL;
}
+ if (!with_rr && icmp_packet.packet_type == BAT_ICMP_RR) {
+ bat_dbg(DBG_BATMAN, "batman-adv:Error - can't send packet from "
+ "char device: invalid packet size for BAT_ICMP_RR\n");
+ return -EINVAL;
+ }
+
if (icmp_packet.msg_type != ECHO_REQUEST) {
bat_dbg(DBG_BATMAN, "batman-adv:Error - can't send packet from char device: got bogus message type (expected: ECHO_REQUEST)\n");
return -EINVAL;
@@ -269,8 +287,14 @@
batman_if->net_dev->dev_addr,
ETH_ALEN);
+ if (with_rr) {
+ memcpy(icmp_packet.rr,
+ batman_if->net_dev->dev_addr,
+ ETH_ALEN);
+ }
+
send_raw_packet((unsigned char *)&icmp_packet,
- sizeof(struct icmp_packet),
+ packet_len,
batman_if, dstaddr);
goto out;
@@ -298,11 +322,15 @@
}
void bat_device_add_packet(struct device_client *device_client,
- struct icmp_packet *icmp_packet)
+ struct icmp_packet_rr *icmp_packet)
{
struct device_packet *device_packet;
unsigned long flags;
+ size_t packet_len = sizeof(struct icmp_packet);
+ if (icmp_packet->packet_type == BAT_ICMP_RR)
+ packet_len = sizeof(struct icmp_packet_rr);
+
device_packet = kmalloc(sizeof(struct device_packet), GFP_KERNEL);
if (!device_packet)
@@ -310,7 +338,7 @@
INIT_LIST_HEAD(&device_packet->list);
memcpy(&device_packet->icmp_packet, icmp_packet,
- sizeof(struct icmp_packet));
+ packet_len);
spin_lock_irqsave(&device_client->lock, flags);
@@ -339,7 +367,7 @@
wake_up(&device_client->queue_wait);
}
-void bat_device_receive_packet(struct icmp_packet *icmp_packet)
+void bat_device_receive_packet(struct icmp_packet_rr *icmp_packet)
{
struct device_client *hash = device_client_hash[icmp_packet->uid];
Index: batman-adv-kernelland/device.h
===================================================================
--- batman-adv-kernelland/device.h (revision 1573)
+++ batman-adv-kernelland/device.h (working copy)
@@ -32,5 +32,5 @@
size_t len, loff_t *off);
unsigned int bat_device_poll(struct file *file, poll_table *wait);
void bat_device_add_packet(struct device_client *device_client,
- struct icmp_packet *icmp_packet);
-void bat_device_receive_packet(struct icmp_packet *icmp_packet);
+ struct icmp_packet_rr *icmp_packet);
+void bat_device_receive_packet(struct icmp_packet_rr *icmp_packet);
Index: batman-adv-kernelland/hard-interface.c
===================================================================
--- batman-adv-kernelland/hard-interface.c (revision 1573)
+++ batman-adv-kernelland/hard-interface.c (working copy)
@@ -479,6 +479,7 @@
/* batman icmp packet */
case BAT_ICMP:
+ case BAT_ICMP_RR:
ret = recv_icmp_packet(skb);
break;
Index: batman-adv-kernelland/routing.c
===================================================================
--- batman-adv-kernelland/routing.c (revision 1573)
+++ batman-adv-kernelland/routing.c (working copy)
@@ -709,15 +709,16 @@
static int recv_my_icmp_packet(struct sk_buff *skb)
{
struct orig_node *orig_node;
- struct icmp_packet *icmp_packet;
+ struct icmp_packet_rr *icmp_packet;
struct ethhdr *ethhdr;
struct sk_buff *skb_old;
struct batman_if *batman_if;
int ret;
unsigned long flags;
uint8_t dstaddr[ETH_ALEN];
+ int packet_len = sizeof(struct icmp_packet);
- icmp_packet = (struct icmp_packet *) skb->data;
+ icmp_packet = (struct icmp_packet_rr *) skb->data;
ethhdr = (struct ethhdr *) skb_mac_header(skb);
/* add data to device queue */
@@ -726,6 +727,9 @@
return NET_RX_DROP;
}
+ if (icmp_packet->packet_type == BAT_ICMP_RR)
+ packet_len = sizeof(struct icmp_packet_rr);
+
/* answer echo request (ping) */
/* get routing information */
spin_lock_irqsave(&orig_hash_lock, flags);
@@ -745,12 +749,12 @@
/* create a copy of the skb, if needed, to modify it. */
skb_old = NULL;
- if (!skb_clone_writable(skb, sizeof(struct icmp_packet))) {
+ if (!skb_clone_writable(skb, packet_len)) {
skb_old = skb;
skb = skb_copy(skb, GFP_ATOMIC);
if (!skb)
return NET_RX_DROP;
- icmp_packet = (struct icmp_packet *) skb->data;
+ icmp_packet = (struct icmp_packet_rr *) skb->data;
kfree_skb(skb_old);
}
@@ -778,6 +782,7 @@
int ret;
unsigned long flags;
uint8_t dstaddr[ETH_ALEN];
+ int len = sizeof(struct icmp_packet);
icmp_packet = (struct icmp_packet *)skb->data;
ethhdr = (struct ethhdr *)skb_mac_header(skb);
@@ -789,6 +794,9 @@
return NET_RX_DROP;
}
+ if (icmp_packet->packet_type == BAT_ICMP_RR)
+ len = sizeof(struct icmp_packet_rr);
+
/* get routing information */
spin_lock_irqsave(&orig_hash_lock, flags);
orig_node = ((struct orig_node *)
@@ -806,7 +814,7 @@
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 icmp_packet))) {
+ if (!skb_clone_writable(skb, len)) {
skb_old = skb;
skb = skb_copy(skb, GFP_ATOMIC);
if (!skb)
@@ -832,7 +840,7 @@
int recv_icmp_packet(struct sk_buff *skb)
{
- struct icmp_packet *icmp_packet;
+ struct icmp_packet_rr *icmp_packet;
struct ethhdr *ethhdr;
struct orig_node *orig_node;
struct sk_buff *skb_old;
@@ -860,8 +868,23 @@
if (!is_my_mac(ethhdr->h_dest))
return NET_RX_DROP;
- icmp_packet = (struct icmp_packet *) skb->data;
+ icmp_packet = (struct icmp_packet_rr *) skb->data;
+ if (icmp_packet->packet_type == BAT_ICMP_RR) {
+ hdr_size = sizeof(struct icmp_packet_rr);
+
+ /* drop packet if it has not necessary minimum size */
+ if (skb_headlen(skb) < hdr_size)
+ return NET_RX_DROP;
+
+ /* add record route information if not full */
+ if (icmp_packet->rr_cur < BAT_RR_LEN) {
+ memcpy(&(icmp_packet->rr[icmp_packet->rr_cur]),
+ ethhdr->h_dest, ETH_ALEN);
+ icmp_packet->rr_cur++;
+ }
+ }
+
/* packet for me */
if (is_my_mac(icmp_packet->dst))
return recv_my_icmp_packet(skb);
@@ -888,12 +911,12 @@
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 icmp_packet))) {
+ if (!skb_clone_writable(skb, hdr_size)) {
skb_old = skb;
skb = skb_copy(skb, GFP_ATOMIC);
if (!skb)
return NET_RX_DROP;
- icmp_packet = (struct icmp_packet *) skb->data;
+ icmp_packet = (struct icmp_packet_rr *) skb->data;
kfree_skb(skb_old);
}
Index: batctl/ping.c
===================================================================
--- batctl/ping.c (revision 1573)
+++ batctl/ping.c (working copy)
@@ -48,6 +48,7 @@
printf(" \t -h print this help\n");
printf(" \t -i interval in seconds\n");
printf(" \t -t timeout in seconds\n");
+ printf(" \t -R record route\n");
}
void sig_handler(int sig)
@@ -64,20 +65,22 @@
int ping(int argc, char **argv)
{
- struct icmp_packet icmp_packet_out, icmp_packet_in;
+ struct icmp_packet_rr icmp_packet_out, icmp_packet_in;
struct timeval tv;
- struct ether_addr *dst_mac = NULL;
- struct bat_host *bat_host;
+ struct ether_addr *dst_mac = NULL, *rr_mac = NULL;
+ struct bat_host *bat_host, *rr_host;
ssize_t read_len;
fd_set read_socket;
int ret = EXIT_FAILURE, ping_fd = 0, res, optchar, found_args = 1;
- int loop_count = -1, loop_interval = 1, timeout = 1;
+ int loop_count = -1, loop_interval = 1, timeout = 1, rr = 0, i;
unsigned int seq_counter = 0, packets_out = 0, packets_in = 0, packets_loss;
- char *dst_string, *mac_string;
+ char *dst_string, *mac_string, *rr_string;
double time_delta;
float min = 0.0, max = 0.0, avg = 0.0;
+ uint8_t last_rr_cur = 0, last_rr[BAT_RR_LEN][ETH_ALEN];
+ size_t packet_len;
- while ((optchar = getopt(argc, argv, "hc:i:t:")) != -1) {
+ while ((optchar = getopt(argc, argv, "hc:i:t:R")) != -1) {
switch (optchar) {
case 'c':
loop_count = strtol(optarg, NULL , 10);
@@ -100,6 +103,10 @@
timeout = 1;
found_args += ((*((char*)(optarg - 1)) == optchar ) ? 1 : 2);
break;
+ case 'R':
+ rr = 1;
+ found_args++;
+ break;
default:
ping_usage();
return EXIT_FAILURE;
@@ -141,6 +148,8 @@
goto out;
}
+ packet_len = sizeof(struct icmp_packet);
+
memcpy(&icmp_packet_out.dst, dst_mac, ETH_ALEN);
icmp_packet_out.packet_type = BAT_ICMP;
icmp_packet_out.version = COMPAT_VERSION;
@@ -148,8 +157,15 @@
icmp_packet_out.ttl = 50;
icmp_packet_out.seqno = 0;
+ if (rr) {
+ icmp_packet_out.packet_type = BAT_ICMP_RR;
+ packet_len = sizeof(struct icmp_packet_rr);
+ icmp_packet_out.rr_cur = 1;
+ memset(&icmp_packet_out.rr, 0, BAT_RR_LEN * ETH_ALEN);
+ }
+
printf("PING %s (%s) %zu(%zu) bytes of data\n", dst_string, mac_string,
- sizeof(icmp_packet_out), sizeof(icmp_packet_out) + 28);
+ packet_len, packet_len + 28);
while (!is_aborted) {
if (loop_count == 0)
@@ -160,7 +176,7 @@
icmp_packet_out.seqno = htons(++seq_counter);
- if (write(ping_fd, (char *)&icmp_packet_out, sizeof(icmp_packet_out)) < 0) {
+ if (write(ping_fd, (char *)&icmp_packet_out, packet_len) < 0) {
printf("Error - can't write to batman adv kernel file '%s': %s\n", BAT_DEVICE, strerror(errno));
goto sleep;
}
@@ -188,26 +204,55 @@
if (res < 0)
goto sleep;
- read_len = read(ping_fd, (char *)&icmp_packet_in, sizeof(icmp_packet_in));
+ read_len = read(ping_fd, (char *)&icmp_packet_in, packet_len);
if (read_len < 0) {
printf("Error - can't read from batman adv kernel file '%s': %s\n", BAT_DEVICE, strerror(errno));
goto sleep;
}
- if ((size_t)read_len < sizeof(icmp_packet_in)) {
+ if ((size_t)read_len < packet_len) {
printf("Warning - dropping received packet as it is smaller than expected (%zu): %zd\n",
- sizeof(icmp_packet_in), read_len);
+ packet_len, read_len);
goto sleep;
}
switch (icmp_packet_in.msg_type) {
case ECHO_REPLY:
time_delta = end_timer();
- printf("%zd bytes from %s icmp_seq=%hu ttl=%d time=%.2f ms\n",
+ printf("%zd bytes from %s icmp_seq=%hu ttl=%d time=%.2f ms",
read_len, dst_string, ntohs(icmp_packet_in.seqno),
icmp_packet_in.ttl, time_delta);
+ if (icmp_packet_in.packet_type == BAT_ICMP_RR) {
+ if (last_rr_cur == icmp_packet_in.rr_cur
+ && !memcmp(last_rr, icmp_packet_in.rr, BAT_RR_LEN * ETH_ALEN)) {
+
+ printf("\t(same route)\n");
+
+ } else {
+ printf("\nRR: ");
+ for (i = 0; i < BAT_RR_LEN
+ && i < icmp_packet_in.rr_cur; i++) {
+
+ rr_mac = (struct ether_addr *)&icmp_packet_in.rr[i];
+ rr_host = bat_hosts_find_by_mac((char *)rr_mac);
+ if (rr_host)
+ rr_string = rr_host->name;
+ else
+ rr_string = ether_ntoa_long(rr_mac);
+ printf("\t%s\n", rr_string);
+ if (memcmp(rr_mac, dst_mac, ETH_ALEN) == 0)
+ printf("\t%s\n", rr_string);
+ }
+ printf("\n");
+
+ last_rr_cur = icmp_packet_in.rr_cur;
+ memcpy(last_rr, icmp_packet_in.rr, BAT_RR_LEN * ETH_ALEN);
+ }
+ } else
+ printf("\n");
+
if ((time_delta < min) || (min == 0.0))
min = time_delta;
if (time_delta > max)
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [B.A.T.M.A.N.] [PATCH v3] batman-adv: Record route for ICMP messages
2010-02-15 21:34 [B.A.T.M.A.N.] [PATCH v3] batman-adv: Record route for ICMP messages Daniel Seither
@ 2010-02-16 10:29 ` Marek Lindner
2010-02-16 10:30 ` [B.A.T.M.A.N.] [PATCH 1/2] batman-adv: record " Marek Lindner
2010-02-16 14:53 ` [B.A.T.M.A.N.] [PATCH v3] batman-adv: Record " Daniel Seither
0 siblings, 2 replies; 6+ messages in thread
From: Marek Lindner @ 2010-02-16 10:29 UTC (permalink / raw)
To: The list for a Better Approach To Mobile Ad-hoc Networking
Hey,
> The standard layer 3 ping utility can use the record route (RR) option
> of IP to collect route data for sent ping messages (ping -R). This
> patch introduces comparable functionality for batman-adv ICMP messages.
I don't think we need another packet type for this. I reworked your patches a
bit. As soon as you checked if you like it this way I will commit them.
Note: I split them into 2 patches because batman-adv & batctl reside in
different branches. On top of that syncing distinct patches with the git repos
is much less painful. :)
Cheers,
Marek
^ permalink raw reply [flat|nested] 6+ messages in thread
* [B.A.T.M.A.N.] [PATCH 1/2] batman-adv: record route for ICMP messages
2010-02-16 10:29 ` Marek Lindner
@ 2010-02-16 10:30 ` Marek Lindner
2010-02-16 10:30 ` [B.A.T.M.A.N.] [PATCH 2/2] batctl: " Marek Lindner
2010-02-16 14:53 ` [B.A.T.M.A.N.] [PATCH v3] batman-adv: Record " Daniel Seither
1 sibling, 1 reply; 6+ messages in thread
From: Marek Lindner @ 2010-02-16 10:30 UTC (permalink / raw)
To: b.a.t.m.a.n; +Cc: Marek Lindner
The standard layer 3 ping utility can use the record route (RR) option
of IP to collect route data for sent ping messages (ping -R). This
patch introduces comparable functionality for batman-adv ICMP messages.
The patch adds a second batman ICMP packet format (icmp_packet_rr) such
that up to 17 MAC addresses can be recorded (sufficient for up to 8
hops per direction). When no RR is wanted, the old icmp_packet without
the RR overhead can be sent.
Signed-off-by: Daniel Seither <post@tiwoc.de>
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
---
batman-adv-kernelland/device.c | 42 ++++++++++++++++++++++---------------
batman-adv-kernelland/device.h | 6 +++-
batman-adv-kernelland/packet.h | 17 +++++++++++++++
batman-adv-kernelland/routing.c | 44 +++++++++++++++++++++++++-------------
batman-adv-kernelland/types.h | 3 +-
5 files changed, 77 insertions(+), 35 deletions(-)
diff --git a/batman-adv-kernelland/device.c b/batman-adv-kernelland/device.c
index df51f1c..0c3c0b3 100644
--- a/batman-adv-kernelland/device.c
+++ b/batman-adv-kernelland/device.c
@@ -163,6 +163,7 @@ ssize_t bat_device_read(struct file *file, char __user *buf, size_t count,
struct device_client *device_client =
(struct device_client *)file->private_data;
struct device_packet *device_packet;
+ size_t packet_len;
int error;
unsigned long flags;
@@ -191,14 +192,15 @@ ssize_t bat_device_read(struct file *file, char __user *buf, size_t count,
spin_unlock_irqrestore(&device_client->lock, flags);
error = __copy_to_user(buf, &device_packet->icmp_packet,
- sizeof(struct icmp_packet));
+ device_packet->icmp_len);
+ packet_len = device_packet->icmp_len;
kfree(device_packet);
if (error)
return error;
- return sizeof(struct icmp_packet);
+ return packet_len;
}
ssize_t bat_device_write(struct file *file, const char __user *buff,
@@ -206,9 +208,10 @@ ssize_t bat_device_write(struct file *file, const char __user *buff,
{
struct device_client *device_client =
(struct device_client *)file->private_data;
- struct icmp_packet icmp_packet;
+ struct icmp_packet_rr icmp_packet;
struct orig_node *orig_node;
struct batman_if *batman_if;
+ size_t packet_len = sizeof(struct icmp_packet);
uint8_t dstaddr[ETH_ALEN];
unsigned long flags;
@@ -217,10 +220,13 @@ ssize_t bat_device_write(struct file *file, const char __user *buff,
return -EINVAL;
}
- if (!access_ok(VERIFY_READ, buff, sizeof(struct icmp_packet)))
+ if (len >= sizeof(struct icmp_packet_rr))
+ packet_len = sizeof(struct icmp_packet_rr);
+
+ if (!access_ok(VERIFY_READ, buff, packet_len))
return -EFAULT;
- if (__copy_from_user(&icmp_packet, buff, sizeof(icmp_packet)))
+ if (__copy_from_user(&icmp_packet, buff, packet_len))
return -EFAULT;
if (icmp_packet.packet_type != BAT_ICMP) {
@@ -238,7 +244,7 @@ ssize_t bat_device_write(struct file *file, const char __user *buff,
if (icmp_packet.version != COMPAT_VERSION) {
icmp_packet.msg_type = PARAMETER_PROBLEM;
icmp_packet.ttl = COMPAT_VERSION;
- bat_device_add_packet(device_client, &icmp_packet);
+ bat_device_add_packet(device_client, &icmp_packet, packet_len);
goto out;
}
@@ -265,13 +271,13 @@ ssize_t bat_device_write(struct file *file, const char __user *buff,
if (batman_if->if_active != IF_ACTIVE)
goto dst_unreach;
- memcpy(icmp_packet.orig,
- batman_if->net_dev->dev_addr,
- ETH_ALEN);
+ memcpy(icmp_packet.orig, batman_if->net_dev->dev_addr, ETH_ALEN);
+
+ if (packet_len == sizeof(struct icmp_packet_rr))
+ memcpy(icmp_packet.rr, batman_if->net_dev->dev_addr, ETH_ALEN);
send_raw_packet((unsigned char *)&icmp_packet,
- sizeof(struct icmp_packet),
- batman_if, dstaddr);
+ packet_len, batman_if, dstaddr);
goto out;
@@ -279,7 +285,7 @@ unlock:
spin_unlock_irqrestore(&orig_hash_lock, flags);
dst_unreach:
icmp_packet.msg_type = DESTINATION_UNREACHABLE;
- bat_device_add_packet(device_client, &icmp_packet);
+ bat_device_add_packet(device_client, &icmp_packet, packet_len);
out:
return len;
}
@@ -298,7 +304,8 @@ unsigned int bat_device_poll(struct file *file, poll_table *wait)
}
void bat_device_add_packet(struct device_client *device_client,
- struct icmp_packet *icmp_packet)
+ struct icmp_packet_rr *icmp_packet,
+ size_t icmp_len)
{
struct device_packet *device_packet;
unsigned long flags;
@@ -309,8 +316,8 @@ void bat_device_add_packet(struct device_client *device_client,
return;
INIT_LIST_HEAD(&device_packet->list);
- memcpy(&device_packet->icmp_packet, icmp_packet,
- sizeof(struct icmp_packet));
+ memcpy(&device_packet->icmp_packet, icmp_packet, icmp_len);
+ device_packet->icmp_len = icmp_len;
spin_lock_irqsave(&device_client->lock, flags);
@@ -339,10 +346,11 @@ void bat_device_add_packet(struct device_client *device_client,
wake_up(&device_client->queue_wait);
}
-void bat_device_receive_packet(struct icmp_packet *icmp_packet)
+void bat_device_receive_packet(struct icmp_packet_rr *icmp_packet,
+ size_t icmp_len)
{
struct device_client *hash = device_client_hash[icmp_packet->uid];
if (hash)
- bat_device_add_packet(hash, icmp_packet);
+ bat_device_add_packet(hash, icmp_packet, icmp_len);
}
diff --git a/batman-adv-kernelland/device.h b/batman-adv-kernelland/device.h
index 46c0f44..7a9394b 100644
--- a/batman-adv-kernelland/device.h
+++ b/batman-adv-kernelland/device.h
@@ -32,5 +32,7 @@ ssize_t bat_device_write(struct file *file, const char __user *buff,
size_t len, loff_t *off);
unsigned int bat_device_poll(struct file *file, poll_table *wait);
void bat_device_add_packet(struct device_client *device_client,
- struct icmp_packet *icmp_packet);
-void bat_device_receive_packet(struct icmp_packet *icmp_packet);
+ struct icmp_packet_rr *icmp_packet,
+ size_t icmp_len);
+void bat_device_receive_packet(struct icmp_packet_rr *icmp_packet,
+ size_t icmp_len);
diff --git a/batman-adv-kernelland/packet.h b/batman-adv-kernelland/packet.h
index 1c8e6c8..c8b973f 100644
--- a/batman-adv-kernelland/packet.h
+++ b/batman-adv-kernelland/packet.h
@@ -71,6 +71,23 @@ struct icmp_packet {
uint8_t uid;
} __attribute__((packed));
+#define BAT_RR_LEN 16
+
+/* icmp_packet_rr must start with all fields from imcp_packet
+ as this is assumed by code that handles ICMP packets */
+struct icmp_packet_rr {
+ uint8_t packet_type;
+ uint8_t version; /* batman version field */
+ uint8_t msg_type; /* see ICMP message types above */
+ uint8_t ttl;
+ uint8_t dst[6];
+ uint8_t orig[6];
+ uint16_t seqno;
+ uint8_t uid;
+ uint8_t rr_cur;
+ uint8_t rr[BAT_RR_LEN][ETH_ALEN];
+} __attribute__((packed));
+
struct unicast_packet {
uint8_t packet_type;
uint8_t version; /* batman version field */
diff --git a/batman-adv-kernelland/routing.c b/batman-adv-kernelland/routing.c
index a3adc7f..47d5757 100644
--- a/batman-adv-kernelland/routing.c
+++ b/batman-adv-kernelland/routing.c
@@ -706,10 +706,10 @@ int recv_bat_packet(struct sk_buff *skb,
return NET_RX_SUCCESS;
}
-static int recv_my_icmp_packet(struct sk_buff *skb)
+static int recv_my_icmp_packet(struct sk_buff *skb, size_t icmp_len)
{
struct orig_node *orig_node;
- struct icmp_packet *icmp_packet;
+ struct icmp_packet_rr *icmp_packet;
struct ethhdr *ethhdr;
struct sk_buff *skb_old;
struct batman_if *batman_if;
@@ -717,12 +717,12 @@ static int recv_my_icmp_packet(struct sk_buff *skb)
unsigned long flags;
uint8_t dstaddr[ETH_ALEN];
- icmp_packet = (struct icmp_packet *) skb->data;
- ethhdr = (struct ethhdr *) skb_mac_header(skb);
+ icmp_packet = (struct icmp_packet_rr *)skb->data;
+ ethhdr = (struct ethhdr *)skb_mac_header(skb);
/* add data to device queue */
if (icmp_packet->msg_type != ECHO_REQUEST) {
- bat_device_receive_packet(icmp_packet);
+ bat_device_receive_packet(icmp_packet, icmp_len);
return NET_RX_DROP;
}
@@ -745,12 +745,12 @@ static int recv_my_icmp_packet(struct sk_buff *skb)
/* create a copy of the skb, if needed, to modify it. */
skb_old = NULL;
- if (!skb_clone_writable(skb, sizeof(struct icmp_packet))) {
+ if (!skb_clone_writable(skb, icmp_len)) {
skb_old = skb;
skb = skb_copy(skb, GFP_ATOMIC);
if (!skb)
return NET_RX_DROP;
- icmp_packet = (struct icmp_packet *) skb->data;
+ icmp_packet = (struct icmp_packet_rr *)skb->data;
kfree_skb(skb_old);
}
@@ -768,7 +768,7 @@ static int recv_my_icmp_packet(struct sk_buff *skb)
return ret;
}
-static int recv_icmp_ttl_exceeded(struct sk_buff *skb)
+static int recv_icmp_ttl_exceeded(struct sk_buff *skb, size_t icmp_len)
{
struct orig_node *orig_node;
struct icmp_packet *icmp_packet;
@@ -806,7 +806,7 @@ static int recv_icmp_ttl_exceeded(struct sk_buff *skb)
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 icmp_packet))) {
+ if (!skb_clone_writable(skb, icmp_len)) {
skb_old = skb;
skb = skb_copy(skb, GFP_ATOMIC);
if (!skb)
@@ -832,7 +832,7 @@ static int recv_icmp_ttl_exceeded(struct sk_buff *skb)
int recv_icmp_packet(struct sk_buff *skb)
{
- struct icmp_packet *icmp_packet;
+ struct icmp_packet_rr *icmp_packet;
struct ethhdr *ethhdr;
struct orig_node *orig_node;
struct sk_buff *skb_old;
@@ -842,6 +842,12 @@ int recv_icmp_packet(struct sk_buff *skb)
unsigned long flags;
uint8_t dstaddr[ETH_ALEN];
+ /**
+ * we truncate all incoming icmp packets if they don't match our size
+ */
+ if (skb_headlen(skb) >= sizeof(struct icmp_packet_rr))
+ hdr_size = sizeof(struct icmp_packet_rr);
+
/* drop packet if it has not necessary minimum size */
if (skb_headlen(skb) < hdr_size)
return NET_RX_DROP;
@@ -860,15 +866,23 @@ int recv_icmp_packet(struct sk_buff *skb)
if (!is_my_mac(ethhdr->h_dest))
return NET_RX_DROP;
- icmp_packet = (struct icmp_packet *) skb->data;
+ icmp_packet = (struct icmp_packet_rr *)skb->data;
+
+ /* add record route information if not full */
+ if ((hdr_size == sizeof(struct icmp_packet_rr)) &&
+ (icmp_packet->rr_cur < BAT_RR_LEN)) {
+ memcpy(&(icmp_packet->rr[icmp_packet->rr_cur]),
+ ethhdr->h_dest, ETH_ALEN);
+ icmp_packet->rr_cur++;
+ }
/* packet for me */
if (is_my_mac(icmp_packet->dst))
- return recv_my_icmp_packet(skb);
+ return recv_my_icmp_packet(skb, hdr_size);
/* TTL exceeded */
if (icmp_packet->ttl < 2)
- return recv_icmp_ttl_exceeded(skb);
+ return recv_icmp_ttl_exceeded(skb, hdr_size);
ret = NET_RX_DROP;
@@ -888,12 +902,12 @@ int recv_icmp_packet(struct sk_buff *skb)
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 icmp_packet))) {
+ if (!skb_clone_writable(skb, hdr_size)) {
skb_old = skb;
skb = skb_copy(skb, GFP_ATOMIC);
if (!skb)
return NET_RX_DROP;
- icmp_packet = (struct icmp_packet *) skb->data;
+ icmp_packet = (struct icmp_packet_rr *)skb->data;
kfree_skb(skb_old);
}
diff --git a/batman-adv-kernelland/types.h b/batman-adv-kernelland/types.h
index d9cb5d1..a82b52d 100644
--- a/batman-adv-kernelland/types.h
+++ b/batman-adv-kernelland/types.h
@@ -106,7 +106,8 @@ struct device_client {
struct device_packet {
struct list_head list;
- struct icmp_packet icmp_packet;
+ size_t icmp_len;
+ struct icmp_packet_rr icmp_packet;
};
struct hna_local_entry {
--
1.6.6.2
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [B.A.T.M.A.N.] [PATCH 2/2] batctl: record route for ICMP messages
2010-02-16 10:30 ` [B.A.T.M.A.N.] [PATCH 1/2] batman-adv: record " Marek Lindner
@ 2010-02-16 10:30 ` Marek Lindner
0 siblings, 0 replies; 6+ messages in thread
From: Marek Lindner @ 2010-02-16 10:30 UTC (permalink / raw)
To: b.a.t.m.a.n; +Cc: Marek Lindner
batctl is extended to recognize the -R option for the ping subcommand.
The output should be the same as for the standard iputils ping program.
For this, the destination host is printed twice.
Signed-off-by: Daniel Seither <post@tiwoc.de>
---
batctl/ping.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++----------
1 files changed, 60 insertions(+), 13 deletions(-)
diff --git a/batctl/ping.c b/batctl/ping.c
index c14141c..0352870 100644
--- a/batctl/ping.c
+++ b/batctl/ping.c
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
*
* Andreas Langer <a.langer@q-dsl.de>, Marek Lindner <lindner_marek@yahoo.de>
@@ -48,6 +48,7 @@ void ping_usage(void)
printf(" \t -h print this help\n");
printf(" \t -i interval in seconds\n");
printf(" \t -t timeout in seconds\n");
+ printf(" \t -R record route\n");
}
void sig_handler(int sig)
@@ -64,20 +65,22 @@ void sig_handler(int sig)
int ping(int argc, char **argv)
{
- struct icmp_packet icmp_packet_out, icmp_packet_in;
+ struct icmp_packet_rr icmp_packet_out, icmp_packet_in;
struct timeval tv;
- struct ether_addr *dst_mac = NULL;
- struct bat_host *bat_host;
+ struct ether_addr *dst_mac = NULL, *rr_mac = NULL;
+ struct bat_host *bat_host, *rr_host;
ssize_t read_len;
fd_set read_socket;
int ret = EXIT_FAILURE, ping_fd = 0, res, optchar, found_args = 1;
- int loop_count = -1, loop_interval = 1, timeout = 1;
+ int loop_count = -1, loop_interval = 1, timeout = 1, rr = 0, i;
unsigned int seq_counter = 0, packets_out = 0, packets_in = 0, packets_loss;
- char *dst_string, *mac_string;
+ char *dst_string, *mac_string, *rr_string;
double time_delta;
float min = 0.0, max = 0.0, avg = 0.0;
+ uint8_t last_rr_cur = 0, last_rr[BAT_RR_LEN][ETH_ALEN];
+ size_t packet_len;
- while ((optchar = getopt(argc, argv, "hc:i:t:")) != -1) {
+ while ((optchar = getopt(argc, argv, "hc:i:t:R")) != -1) {
switch (optchar) {
case 'c':
loop_count = strtol(optarg, NULL , 10);
@@ -100,6 +103,10 @@ int ping(int argc, char **argv)
timeout = 1;
found_args += ((*((char*)(optarg - 1)) == optchar ) ? 1 : 2);
break;
+ case 'R':
+ rr = 1;
+ found_args++;
+ break;
default:
ping_usage();
return EXIT_FAILURE;
@@ -141,6 +148,8 @@ int ping(int argc, char **argv)
goto out;
}
+ packet_len = sizeof(struct icmp_packet);
+
memcpy(&icmp_packet_out.dst, dst_mac, ETH_ALEN);
icmp_packet_out.packet_type = BAT_ICMP;
icmp_packet_out.version = COMPAT_VERSION;
@@ -148,8 +157,15 @@ int ping(int argc, char **argv)
icmp_packet_out.ttl = 50;
icmp_packet_out.seqno = 0;
+ if (rr) {
+ packet_len = sizeof(struct icmp_packet_rr);
+ icmp_packet_out.rr_cur = 1;
+ memset(&icmp_packet_out.rr, 0, BAT_RR_LEN * ETH_ALEN);
+ memset(last_rr, 0, BAT_RR_LEN * ETH_ALEN);
+ }
+
printf("PING %s (%s) %zu(%zu) bytes of data\n", dst_string, mac_string,
- sizeof(icmp_packet_out), sizeof(icmp_packet_out) + 28);
+ packet_len, packet_len + 28);
while (!is_aborted) {
if (loop_count == 0)
@@ -160,7 +176,7 @@ int ping(int argc, char **argv)
icmp_packet_out.seqno = htons(++seq_counter);
- if (write(ping_fd, (char *)&icmp_packet_out, sizeof(icmp_packet_out)) < 0) {
+ if (write(ping_fd, (char *)&icmp_packet_out, packet_len) < 0) {
printf("Error - can't write to batman adv kernel file '%s': %s\n", BAT_DEVICE, strerror(errno));
goto sleep;
}
@@ -188,26 +204,57 @@ int ping(int argc, char **argv)
if (res < 0)
goto sleep;
- read_len = read(ping_fd, (char *)&icmp_packet_in, sizeof(icmp_packet_in));
+ read_len = read(ping_fd, (char *)&icmp_packet_in, packet_len);
if (read_len < 0) {
printf("Error - can't read from batman adv kernel file '%s': %s\n", BAT_DEVICE, strerror(errno));
goto sleep;
}
- if ((size_t)read_len < sizeof(icmp_packet_in)) {
+ if ((size_t)read_len < packet_len) {
printf("Warning - dropping received packet as it is smaller than expected (%zu): %zd\n",
- sizeof(icmp_packet_in), read_len);
+ packet_len, read_len);
goto sleep;
}
switch (icmp_packet_in.msg_type) {
case ECHO_REPLY:
time_delta = end_timer();
- printf("%zd bytes from %s icmp_seq=%hu ttl=%d time=%.2f ms\n",
+ printf("%zd bytes from %s icmp_seq=%hu ttl=%d time=%.2f ms",
read_len, dst_string, ntohs(icmp_packet_in.seqno),
icmp_packet_in.ttl, time_delta);
+ if (read_len == sizeof(struct icmp_packet_rr)) {
+ if (last_rr_cur == icmp_packet_in.rr_cur
+ && !memcmp(last_rr, icmp_packet_in.rr, BAT_RR_LEN * ETH_ALEN)) {
+
+ printf("\t(same route)");
+
+ } else {
+ printf("\nRR: ");
+
+ for (i = 0; i < BAT_RR_LEN
+ && i < icmp_packet_in.rr_cur; i++) {
+
+ rr_mac = (struct ether_addr *)&icmp_packet_in.rr[i];
+ rr_host = bat_hosts_find_by_mac((char *)rr_mac);
+ if (rr_host)
+ rr_string = rr_host->name;
+ else
+ rr_string = ether_ntoa_long(rr_mac);
+ printf("\t%s\n", rr_string);
+
+ if (memcmp(rr_mac, dst_mac, ETH_ALEN) == 0)
+ printf("\t%s\n", rr_string);
+ }
+
+ last_rr_cur = icmp_packet_in.rr_cur;
+ memcpy(last_rr, icmp_packet_in.rr, BAT_RR_LEN * ETH_ALEN);
+ }
+ }
+
+ printf("\n");
+
if ((time_delta < min) || (min == 0.0))
min = time_delta;
if (time_delta > max)
--
1.6.6.2
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [B.A.T.M.A.N.] [PATCH v3] batman-adv: Record route for ICMP messages
2010-02-16 10:29 ` Marek Lindner
2010-02-16 10:30 ` [B.A.T.M.A.N.] [PATCH 1/2] batman-adv: record " Marek Lindner
@ 2010-02-16 14:53 ` Daniel Seither
2010-02-16 15:22 ` Marek Lindner
1 sibling, 1 reply; 6+ messages in thread
From: Daniel Seither @ 2010-02-16 14:53 UTC (permalink / raw)
To: The list for a Better Approach To Mobile Ad-hoc Networking
Marek Lindner schrieb:
> I don't think we need another packet type for this. I reworked your patches a
> bit. As soon as you checked if you like it this way I will commit them.
Okay, please commit the patches :)
Daniel
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [B.A.T.M.A.N.] [PATCH v3] batman-adv: Record route for ICMP messages
2010-02-16 14:53 ` [B.A.T.M.A.N.] [PATCH v3] batman-adv: Record " Daniel Seither
@ 2010-02-16 15:22 ` Marek Lindner
0 siblings, 0 replies; 6+ messages in thread
From: Marek Lindner @ 2010-02-16 15:22 UTC (permalink / raw)
To: The list for a Better Approach To Mobile Ad-hoc Networking
On Tuesday 16 February 2010 22:53:08 Daniel Seither wrote:
> Okay, please commit the patches :)
There are in (1574 + 1575).
Thanks again for this good work. Don't hesitate to send more if you want. :-)
Cheers,
Marek
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2010-02-16 15:22 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-02-15 21:34 [B.A.T.M.A.N.] [PATCH v3] batman-adv: Record route for ICMP messages Daniel Seither
2010-02-16 10:29 ` Marek Lindner
2010-02-16 10:30 ` [B.A.T.M.A.N.] [PATCH 1/2] batman-adv: record " Marek Lindner
2010-02-16 10:30 ` [B.A.T.M.A.N.] [PATCH 2/2] batctl: " Marek Lindner
2010-02-16 14:53 ` [B.A.T.M.A.N.] [PATCH v3] batman-adv: Record " Daniel Seither
2010-02-16 15:22 ` Marek Lindner
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.