From: "mihail.costea90@gmail.com" mihail.costea90@gmail.com
Renamed snooping functions in order to suggest that they should work on more protocols than ARP.
Signed-off-by: Mihail Costea mihail.costea90@gmail.com Signed-off-by: Stefan Popa Stefan.A.Popa@intel.com Reviewed-by: Stefan Popa Stefan.A.Popa@intel.com
--- distributed-arp-table.c | 16 ++++++++-------- distributed-arp-table.h | 16 ++++++++-------- routing.c | 12 ++++++------ soft-interface.c | 6 +++--- 4 files changed, 25 insertions(+), 25 deletions(-)
diff --git a/distributed-arp-table.c b/distributed-arp-table.c index af670d3..b2ca7e0 100644 --- a/distributed-arp-table.c +++ b/distributed-arp-table.c @@ -978,7 +978,7 @@ out: }
/** - * batadv_dat_snoop_outgoing_arp_request - snoop the ARP request and try to + * batadv_dat_snoop_outgoing_msg_request - snoop the ARP request and try to * answer using DAT * @bat_priv: the bat priv with all the soft interface information * @skb: packet to check @@ -987,7 +987,7 @@ out: * otherwise. In case of a positive return value the message has to be enqueued * to permit the fallback. */ -bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv, +bool batadv_dat_snoop_outgoing_msg_request(struct batadv_priv *bat_priv, struct sk_buff *skb) { uint16_t type = 0; @@ -1060,7 +1060,7 @@ out: }
/** - * batadv_dat_snoop_incoming_arp_request - snoop the ARP request and try to + * batadv_dat_snoop_incoming_msg_request - snoop the ARP request and try to * answer using the local DAT storage * @bat_priv: the bat priv with all the soft interface information * @skb: packet to check @@ -1068,7 +1068,7 @@ out: * * Returns true if the request has been answered, false otherwise. */ -bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv, +bool batadv_dat_snoop_incoming_msg_request(struct batadv_priv *bat_priv, struct sk_buff *skb, int hdr_size) { uint16_t type; @@ -1130,11 +1130,11 @@ out: }
/** - * batadv_dat_snoop_outgoing_arp_reply - snoop the ARP reply and fill the DHT + * batadv_dat_snoop_outgoing_msg_reply - snoop the ARP reply and fill the DHT * @bat_priv: the bat priv with all the soft interface information * @skb: packet to check */ -void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv, +void batadv_dat_snoop_outgoing_msg_reply(struct batadv_priv *bat_priv, struct sk_buff *skb) { uint16_t type; @@ -1167,13 +1167,13 @@ void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv, BATADV_P_DAT_DHT_PUT); } /** - * batadv_dat_snoop_incoming_arp_reply - snoop the ARP reply and fill the local + * batadv_dat_snoop_incoming_msg_reply - snoop the ARP reply and fill the local * DAT storage only * @bat_priv: the bat priv with all the soft interface information * @skb: packet to check * @hdr_size: size of the encapsulation header */ -bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv, +bool batadv_dat_snoop_incoming_msg_reply(struct batadv_priv *bat_priv, struct sk_buff *skb, int hdr_size) { uint16_t type; diff --git a/distributed-arp-table.h b/distributed-arp-table.h index 557bab9..28c062b 100644 --- a/distributed-arp-table.h +++ b/distributed-arp-table.h @@ -31,13 +31,13 @@ #define BATADV_DAT_DATA_MAX_LEN 16
void batadv_dat_status_update(struct net_device *net_dev); -bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv, +bool batadv_dat_snoop_outgoing_msg_request(struct batadv_priv *bat_priv, struct sk_buff *skb); -bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv, +bool batadv_dat_snoop_incoming_msg_request(struct batadv_priv *bat_priv, struct sk_buff *skb, int hdr_size); -void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv, +void batadv_dat_snoop_outgoing_msg_reply(struct batadv_priv *bat_priv, struct sk_buff *skb); -bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv, +bool batadv_dat_snoop_incoming_msg_reply(struct batadv_priv *bat_priv, struct sk_buff *skb, int hdr_size); bool batadv_dat_drop_broadcast_packet(struct batadv_priv *bat_priv, struct batadv_forw_packet *forw_packet); @@ -105,28 +105,28 @@ static inline void batadv_dat_status_update(struct net_device *net_dev) }
static inline bool -batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv, +batadv_dat_snoop_outgoing_msg_request(struct batadv_priv *bat_priv, struct sk_buff *skb) { return false; }
static inline bool -batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv, +batadv_dat_snoop_incoming_msg_request(struct batadv_priv *bat_priv, struct sk_buff *skb, int hdr_size) { return false; }
static inline bool -batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv, +batadv_dat_snoop_outgoing_msg_reply(struct batadv_priv *bat_priv, struct sk_buff *skb) { return false; }
static inline bool -batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv, +batadv_dat_snoop_incoming_msg_reply(struct batadv_priv *bat_priv, struct sk_buff *skb, int hdr_size) { return false; diff --git a/routing.c b/routing.c index 7c372f1..1c43f55 100644 --- a/routing.c +++ b/routing.c @@ -967,10 +967,10 @@ int batadv_recv_unicast_packet(struct sk_buff *skb, orig_node = batadv_orig_hash_find(bat_priv, orig_addr); }
- if (batadv_dat_snoop_incoming_arp_request(bat_priv, skb, + if (batadv_dat_snoop_incoming_msg_request(bat_priv, skb, hdr_size)) goto rx_success; - if (batadv_dat_snoop_incoming_arp_reply(bat_priv, skb, + if (batadv_dat_snoop_incoming_msg_reply(bat_priv, skb, hdr_size)) goto rx_success;
@@ -1015,10 +1015,10 @@ int batadv_recv_ucast_frag_packet(struct sk_buff *skb, if (!new_skb) return NET_RX_SUCCESS;
- if (batadv_dat_snoop_incoming_arp_request(bat_priv, new_skb, + if (batadv_dat_snoop_incoming_msg_request(bat_priv, new_skb, hdr_size)) goto rx_success; - if (batadv_dat_snoop_incoming_arp_reply(bat_priv, new_skb, + if (batadv_dat_snoop_incoming_msg_reply(bat_priv, new_skb, hdr_size)) goto rx_success;
@@ -1159,9 +1159,9 @@ int batadv_recv_bcast_packet(struct sk_buff *skb, if (batadv_bla_is_backbone_gw(skb, orig_node, hdr_size)) goto out;
- if (batadv_dat_snoop_incoming_arp_request(bat_priv, skb, hdr_size)) + if (batadv_dat_snoop_incoming_msg_request(bat_priv, skb, hdr_size)) goto rx_success; - if (batadv_dat_snoop_incoming_arp_reply(bat_priv, skb, hdr_size)) + if (batadv_dat_snoop_incoming_msg_reply(bat_priv, skb, hdr_size)) goto rx_success;
/* broadcast for me */ diff --git a/soft-interface.c b/soft-interface.c index a6ab9e4..9e8fd44 100644 --- a/soft-interface.c +++ b/soft-interface.c @@ -232,7 +232,7 @@ static int batadv_interface_tx(struct sk_buff *skb, * packet, instead we first wait for DAT to try to retrieve the * correct ARP entry */ - if (batadv_dat_snoop_outgoing_arp_request(bat_priv, skb)) + if (batadv_dat_snoop_outgoing_msg_request(bat_priv, skb)) brd_delay = msecs_to_jiffies(ARP_REQ_DELAY);
if (batadv_skb_head_push(skb, sizeof(*bcast_packet)) < 0) @@ -271,10 +271,10 @@ static int batadv_interface_tx(struct sk_buff *skb, goto dropped; }
- if (batadv_dat_snoop_outgoing_arp_request(bat_priv, skb)) + if (batadv_dat_snoop_outgoing_msg_request(bat_priv, skb)) goto dropped;
- batadv_dat_snoop_outgoing_arp_reply(bat_priv, skb); + batadv_dat_snoop_outgoing_msg_reply(bat_priv, skb);
ret = batadv_unicast_send_skb(bat_priv, skb); if (ret != 0)
From: "mihail.costea90@gmail.com" mihail.costea90@gmail.com
Added IPv6 functionality to generic functions implemented in the first patch.
Signed-off-by: Mihail Costea mihail.costea90@gmail.com Signed-off-by: Stefan Popa Stefan.A.Popa@intel.com Reviewed-by: Stefan Popa Stefan.A.Popa@intel.com
--- distributed-arp-table.c | 30 ++++++++++++++++++++++++++---- types.h | 6 +++++- 2 files changed, 31 insertions(+), 5 deletions(-)
diff --git a/distributed-arp-table.c b/distributed-arp-table.c index b2ca7e0..42118be 100644 --- a/distributed-arp-table.c +++ b/distributed-arp-table.c @@ -32,7 +32,7 @@ #include "unicast.h"
static char *batadv_dat_types_str_fmt[] = { - "%pI4", + "%pI4", "%pI6c", };
static void batadv_dat_purge(struct work_struct *work); @@ -173,6 +173,10 @@ static size_t batadv_sizeof_dat_data(uint8_t data_type) switch (data_type) { case BATADV_DAT_IPV4: return sizeof(__be32); +#if IS_ENABLED(CONFIG_IPV6) + case BATADV_DAT_IPV6: + return sizeof(struct in6_addr); +#endif default: return 0; } @@ -295,6 +299,12 @@ static uint32_t batadv_hash_dat_ipv4(const void *data, uint32_t size) return batadv_hash_dat(data, BATADV_DAT_IPV4, size); }
+#if IS_ENABLED(CONFIG_IPV6) +static uint32_t batadv_hash_dat_ipv6(const void *data, uint32_t size) +{ + return batadv_hash_dat(data, BATADV_DAT_IPV6, size); +} +#endif
/** * batadv_dat_entry_hash_find - look for a given dat_entry in the local hash @@ -393,6 +403,11 @@ static void batadv_dat_entry_add(struct batadv_priv *bat_priv, void *data, case BATADV_DAT_IPV4: choose = batadv_hash_dat_ipv4; break; +#if IS_ENABLED(CONFIG_IPV6) + case BATADV_DAT_IPV6: + choose = batadv_hash_dat_ipv6; + break; +#endif default: goto out; } @@ -872,8 +887,8 @@ int batadv_dat_cache_seq_print_text(struct seq_file *seq, void *offset) goto out;
seq_printf(seq, "Distributed ARP Table (%s):\n", net_dev->name); - seq_printf(seq, " %-7s %-13s %5s\n", "IPv4", "MAC", - "last-seen"); + seq_printf(seq, " %-26s %-15s %5s\n", + "IPv4/IPv6", "MAC", "last-seen");
for (i = 0; i < hash->size; i++) { head = &hash->table[i]; @@ -888,10 +903,17 @@ int batadv_dat_cache_seq_print_text(struct seq_file *seq, void *offset)
switch (dat_entry->type) { case BATADV_DAT_IPV4: - seq_printf(seq, " * %15pI4 %14pM %6i:%02i\n", + seq_printf(seq, " * %-40pI4 %15pM %6i:%02i\n", dat_entry->data, dat_entry->mac_addr, last_seen_mins, last_seen_secs); break; +#if IS_ENABLED(CONFIG_IPV6) + case BATADV_DAT_IPV6: + seq_printf(seq, " * %-40pI6c %15pM %6i:%02i\n", + dat_entry->data, dat_entry->mac_addr, + last_seen_mins, last_seen_secs); + break; +#endif } } rcu_read_unlock(); diff --git a/types.h b/types.h index 284e3d2..74c7091 100644 --- a/types.h +++ b/types.h @@ -931,10 +931,14 @@ struct batadv_dat_entry {
/** * batadv_dat_types - types used in batadv_dat_entry for IP - * @BATADV_DAT_IPv4: IPv4 address type + * @BATADV_DAT_IPV4: IPv4 address type + * @BATADV_DAT_IPV4: IPv6 address type */ enum batadv_dat_types { BATADV_DAT_IPV4 = 0, +#if IS_ENABLED(CONFIG_IPV6) + BATADV_DAT_IPV6 = 1, +#endif };
/**
On Fri, May 17, 2013 at 03:27:50PM +0300, Mihail wrote:
From: "mihail.costea90@gmail.com" mihail.costea90@gmail.com
Added IPv6 functionality to generic functions implemented in the first patch.
avoid references to "first"/"second"/"third" patch. Once committed, they will just be some patches in the list. You can either explicitly mention the name of the patch ("writing the subject in this way") or just saying previously/whatever else.
Signed-off-by: Mihail Costea mihail.costea90@gmail.com Signed-off-by: Stefan Popa Stefan.A.Popa@intel.com Reviewed-by: Stefan Popa Stefan.A.Popa@intel.com
distributed-arp-table.c | 30 ++++++++++++++++++++++++++---- types.h | 6 +++++- 2 files changed, 31 insertions(+), 5 deletions(-)
diff --git a/distributed-arp-table.c b/distributed-arp-table.c index b2ca7e0..42118be 100644 --- a/distributed-arp-table.c +++ b/distributed-arp-table.c @@ -32,7 +32,7 @@ #include "unicast.h"
static char *batadv_dat_types_str_fmt[] = {
- "%pI4",
- "%pI4", "%pI6c",
better going on a new line rather than putting both on the same one (like the array declared in the gateway code).
};
static void batadv_dat_purge(struct work_struct *work); @@ -173,6 +173,10 @@ static size_t batadv_sizeof_dat_data(uint8_t data_type) switch (data_type) { case BATADV_DAT_IPV4: return sizeof(__be32); +#if IS_ENABLED(CONFIG_IPV6)
- case BATADV_DAT_IPV6:
return sizeof(struct in6_addr);
+#endif default: return 0; } @@ -295,6 +299,12 @@ static uint32_t batadv_hash_dat_ipv4(const void *data, uint32_t size) return batadv_hash_dat(data, BATADV_DAT_IPV4, size); }
+#if IS_ENABLED(CONFIG_IPV6) +static uint32_t batadv_hash_dat_ipv6(const void *data, uint32_t size) +{
- return batadv_hash_dat(data, BATADV_DAT_IPV6, size);
+} +#endif
/**
- batadv_dat_entry_hash_find - look for a given dat_entry in the local hash
@@ -393,6 +403,11 @@ static void batadv_dat_entry_add(struct batadv_priv *bat_priv, void *data, case BATADV_DAT_IPV4: choose = batadv_hash_dat_ipv4; break; +#if IS_ENABLED(CONFIG_IPV6)
- case BATADV_DAT_IPV6:
choose = batadv_hash_dat_ipv6;
break;
+#endif
mh...I was just wondering: for the hash functions it would be nice to re-use the same "array approach" that you used for the printing format.
So we would have an array of function pointers to reference rather than having this switch block...What do you think?
I think it would be possible to do this for many other "variable" parameters if required.
default: goto out; } @@ -872,8 +887,8 @@ int batadv_dat_cache_seq_print_text(struct seq_file *seq, void *offset) goto out;
seq_printf(seq, "Distributed ARP Table (%s):\n", net_dev->name);
- seq_printf(seq, " %-7s %-13s %5s\n", "IPv4", "MAC",
"last-seen");
seq_printf(seq, " %-26s %-15s %5s\n",
"IPv4/IPv6", "MAC", "last-seen");
for (i = 0; i < hash->size; i++) { head = &hash->table[i];
@@ -888,10 +903,17 @@ int batadv_dat_cache_seq_print_text(struct seq_file *seq, void *offset)
switch (dat_entry->type) { case BATADV_DAT_IPV4:
seq_printf(seq, " * %15pI4 %14pM %6i:%02i\n",
seq_printf(seq, " * %-40pI4 %15pM %6i:%02i\n", dat_entry->data, dat_entry->mac_addr, last_seen_mins, last_seen_secs); break;
+#if IS_ENABLED(CONFIG_IPV6)
case BATADV_DAT_IPV6:
seq_printf(seq, " * %-40pI6c %15pM %6i:%02i\n",
can't you generalise this using the printing format array defined at the top of this patch?
dat_entry->data, dat_entry->mac_addr,
last_seen_mins, last_seen_secs);
break;
+#endif } } rcu_read_unlock(); diff --git a/types.h b/types.h index 284e3d2..74c7091 100644 --- a/types.h +++ b/types.h @@ -931,10 +931,14 @@ struct batadv_dat_entry {
/**
- batadv_dat_types - types used in batadv_dat_entry for IP
- @BATADV_DAT_IPv4: IPv4 address type
- @BATADV_DAT_IPV4: IPv4 address type
I guess this is a mistake. In the last version of your last patch you are using IPV4 and therefore it is impossible that you have IPv4 here (or maybe you forgot to fix this comment...in this case, this fix should go direclty in the previous patch).
*/
- @BATADV_DAT_IPV4: IPv6 address type
enum batadv_dat_types { BATADV_DAT_IPV4 = 0, +#if IS_ENABLED(CONFIG_IPV6)
- BATADV_DAT_IPV6 = 1,
+#endif };
/**
1.7.10.4
On 26 May 2013 06:57, Antonio Quartulli ordex@autistici.org wrote:
On Fri, May 17, 2013 at 03:27:50PM +0300, Mihail wrote:
From: "mihail.costea90@gmail.com" mihail.costea90@gmail.com
Added IPv6 functionality to generic functions implemented in the first patch.
avoid references to "first"/"second"/"third" patch. Once committed, they will just be some patches in the list. You can either explicitly mention the name of the patch ("writing the subject in this way") or just saying previously/whatever else.
Signed-off-by: Mihail Costea mihail.costea90@gmail.com Signed-off-by: Stefan Popa Stefan.A.Popa@intel.com Reviewed-by: Stefan Popa Stefan.A.Popa@intel.com
distributed-arp-table.c | 30 ++++++++++++++++++++++++++---- types.h | 6 +++++- 2 files changed, 31 insertions(+), 5 deletions(-)
diff --git a/distributed-arp-table.c b/distributed-arp-table.c index b2ca7e0..42118be 100644 --- a/distributed-arp-table.c +++ b/distributed-arp-table.c @@ -32,7 +32,7 @@ #include "unicast.h"
static char *batadv_dat_types_str_fmt[] = {
"%pI4",
"%pI4", "%pI6c",
better going on a new line rather than putting both on the same one (like the array declared in the gateway code).
ACK
};
static void batadv_dat_purge(struct work_struct *work); @@ -173,6 +173,10 @@ static size_t batadv_sizeof_dat_data(uint8_t data_type) switch (data_type) { case BATADV_DAT_IPV4: return sizeof(__be32); +#if IS_ENABLED(CONFIG_IPV6)
case BATADV_DAT_IPV6:
return sizeof(struct in6_addr);
+#endif default: return 0; } @@ -295,6 +299,12 @@ static uint32_t batadv_hash_dat_ipv4(const void *data, uint32_t size) return batadv_hash_dat(data, BATADV_DAT_IPV4, size); }
+#if IS_ENABLED(CONFIG_IPV6) +static uint32_t batadv_hash_dat_ipv6(const void *data, uint32_t size) +{
return batadv_hash_dat(data, BATADV_DAT_IPV6, size);
+} +#endif
/**
- batadv_dat_entry_hash_find - look for a given dat_entry in the local hash
@@ -393,6 +403,11 @@ static void batadv_dat_entry_add(struct batadv_priv *bat_priv, void *data, case BATADV_DAT_IPV4: choose = batadv_hash_dat_ipv4; break; +#if IS_ENABLED(CONFIG_IPV6)
case BATADV_DAT_IPV6:
choose = batadv_hash_dat_ipv6;
break;
+#endif
mh...I was just wondering: for the hash functions it would be nice to re-use the same "array approach" that you used for the printing format.
So we would have an array of function pointers to reference rather than having this switch block...What do you think?
I think it would be possible to do this for many other "variable" parameters if required.
Should there be a struct that contains all of them, like:
struct batadv_dat_data {
}
default: goto out; }
@@ -872,8 +887,8 @@ int batadv_dat_cache_seq_print_text(struct seq_file *seq, void *offset) goto out;
seq_printf(seq, "Distributed ARP Table (%s):\n", net_dev->name);
seq_printf(seq, " %-7s %-13s %5s\n", "IPv4", "MAC",
"last-seen");
seq_printf(seq, " %-26s %-15s %5s\n",
"IPv4/IPv6", "MAC", "last-seen"); for (i = 0; i < hash->size; i++) { head = &hash->table[i];
@@ -888,10 +903,17 @@ int batadv_dat_cache_seq_print_text(struct seq_file *seq, void *offset)
switch (dat_entry->type) { case BATADV_DAT_IPV4:
seq_printf(seq, " * %15pI4 %14pM %6i:%02i\n",
seq_printf(seq, " * %-40pI4 %15pM %6i:%02i\n", dat_entry->data, dat_entry->mac_addr, last_seen_mins, last_seen_secs); break;
+#if IS_ENABLED(CONFIG_IPV6)
case BATADV_DAT_IPV6:
seq_printf(seq, " * %-40pI6c %15pM %6i:%02i\n",
can't you generalise this using the printing format array defined at the top of this patch?
dat_entry->data, dat_entry->mac_addr,
last_seen_mins, last_seen_secs);
break;
+#endif } } rcu_read_unlock(); diff --git a/types.h b/types.h index 284e3d2..74c7091 100644 --- a/types.h +++ b/types.h @@ -931,10 +931,14 @@ struct batadv_dat_entry {
/**
- batadv_dat_types - types used in batadv_dat_entry for IP
- @BATADV_DAT_IPv4: IPv4 address type
- @BATADV_DAT_IPV4: IPv4 address type
I guess this is a mistake. In the last version of your last patch you are using IPV4 and therefore it is impossible that you have IPv4 here (or maybe you forgot to fix this comment...in this case, this fix should go direclty in the previous patch).
*/
- @BATADV_DAT_IPV4: IPv6 address type
enum batadv_dat_types { BATADV_DAT_IPV4 = 0, +#if IS_ENABLED(CONFIG_IPV6)
BATADV_DAT_IPV6 = 1,
+#endif };
/**
1.7.10.4
-- Antonio Quartulli
..each of us alone is worth nothing.. Ernesto "Che" Guevara
-- Mihail Costea
On Wed, May 29, 2013 at 08:16:25AM -0700, Mihail Costea wrote:
/**
- batadv_dat_entry_hash_find - look for a given dat_entry in the local hash
@@ -393,6 +403,11 @@ static void batadv_dat_entry_add(struct batadv_priv *bat_priv, void *data, case BATADV_DAT_IPV4: choose = batadv_hash_dat_ipv4; break; +#if IS_ENABLED(CONFIG_IPV6)
case BATADV_DAT_IPV6:
choose = batadv_hash_dat_ipv6;
break;
+#endif
mh...I was just wondering: for the hash functions it would be nice to re-use the same "array approach" that you used for the printing format.
So we would have an array of function pointers to reference rather than having this switch block...What do you think?
I think it would be possible to do this for many other "variable" parameters if required.
Should there be a struct that contains all of them, like:
struct batadv_dat_data {
I was thinking of having many array, but I have to say that the "struct idea" is much cleaner and it can be seen like an API. Then we would only have one array of objects of this type.
Cheers,
On 26 May 2013 06:57, Antonio Quartulli ordex@autistici.org wrote:
On Fri, May 17, 2013 at 03:27:50PM +0300, Mihail wrote:
From: "mihail.costea90@gmail.com" mihail.costea90@gmail.com
Added IPv6 functionality to generic functions implemented in the first patch.
avoid references to "first"/"second"/"third" patch. Once committed, they will just be some patches in the list. You can either explicitly mention the name of the patch ("writing the subject in this way") or just saying previously/whatever else.
ACK
Signed-off-by: Mihail Costea mihail.costea90@gmail.com Signed-off-by: Stefan Popa Stefan.A.Popa@intel.com Reviewed-by: Stefan Popa Stefan.A.Popa@intel.com
distributed-arp-table.c | 30 ++++++++++++++++++++++++++---- types.h | 6 +++++- 2 files changed, 31 insertions(+), 5 deletions(-)
diff --git a/distributed-arp-table.c b/distributed-arp-table.c index b2ca7e0..42118be 100644 --- a/distributed-arp-table.c +++ b/distributed-arp-table.c @@ -32,7 +32,7 @@ #include "unicast.h"
static char *batadv_dat_types_str_fmt[] = {
"%pI4",
"%pI4", "%pI6c",
better going on a new line rather than putting both on the same one (like the array declared in the gateway code).
ACK
};
static void batadv_dat_purge(struct work_struct *work); @@ -173,6 +173,10 @@ static size_t batadv_sizeof_dat_data(uint8_t data_type) switch (data_type) { case BATADV_DAT_IPV4: return sizeof(__be32); +#if IS_ENABLED(CONFIG_IPV6)
case BATADV_DAT_IPV6:
return sizeof(struct in6_addr);
+#endif default: return 0; } @@ -295,6 +299,12 @@ static uint32_t batadv_hash_dat_ipv4(const void *data, uint32_t size) return batadv_hash_dat(data, BATADV_DAT_IPV4, size); }
+#if IS_ENABLED(CONFIG_IPV6) +static uint32_t batadv_hash_dat_ipv6(const void *data, uint32_t size) +{
return batadv_hash_dat(data, BATADV_DAT_IPV6, size);
+} +#endif
/**
- batadv_dat_entry_hash_find - look for a given dat_entry in the local hash
@@ -393,6 +403,11 @@ static void batadv_dat_entry_add(struct batadv_priv *bat_priv, void *data, case BATADV_DAT_IPV4: choose = batadv_hash_dat_ipv4; break; +#if IS_ENABLED(CONFIG_IPV6)
case BATADV_DAT_IPV6:
choose = batadv_hash_dat_ipv6;
break;
+#endif
mh...I was just wondering: for the hash functions it would be nice to re-use the same "array approach" that you used for the printing format.
So we would have an array of function pointers to reference rather than having this switch block...What do you think?
I think it would be possible to do this for many other "variable" parameters if required.
Should there be a struct that contains all of them, like:
struct batadv_dat_data { char *format; signature *hash_function; ....... }
And after that the array with the initialization for all types. Or should they be declared as arrays that have nothing in common? Like just adding a new array for the choose functions.
default: goto out; }
@@ -872,8 +887,8 @@ int batadv_dat_cache_seq_print_text(struct seq_file *seq, void *offset) goto out;
seq_printf(seq, "Distributed ARP Table (%s):\n", net_dev->name);
seq_printf(seq, " %-7s %-13s %5s\n", "IPv4", "MAC",
"last-seen");
seq_printf(seq, " %-26s %-15s %5s\n",
"IPv4/IPv6", "MAC", "last-seen"); for (i = 0; i < hash->size; i++) { head = &hash->table[i];
@@ -888,10 +903,17 @@ int batadv_dat_cache_seq_print_text(struct seq_file *seq, void *offset)
switch (dat_entry->type) { case BATADV_DAT_IPV4:
seq_printf(seq, " * %15pI4 %14pM %6i:%02i\n",
seq_printf(seq, " * %-40pI4 %15pM %6i:%02i\n", dat_entry->data, dat_entry->mac_addr, last_seen_mins, last_seen_secs); break;
+#if IS_ENABLED(CONFIG_IPV6)
case BATADV_DAT_IPV6:
seq_printf(seq, " * %-40pI6c %15pM %6i:%02i\n",
can't you generalise this using the printing format array defined at the top of this patch?
I forgot about that.
dat_entry->data, dat_entry->mac_addr,
last_seen_mins, last_seen_secs);
break;
+#endif } } rcu_read_unlock(); diff --git a/types.h b/types.h index 284e3d2..74c7091 100644 --- a/types.h +++ b/types.h @@ -931,10 +931,14 @@ struct batadv_dat_entry {
/**
- batadv_dat_types - types used in batadv_dat_entry for IP
- @BATADV_DAT_IPv4: IPv4 address type
- @BATADV_DAT_IPV4: IPv4 address type
I guess this is a mistake. In the last version of your last patch you are using IPV4 and therefore it is impossible that you have IPv4 here (or maybe you forgot to fix this comment...in this case, this fix should go direclty in the previous patch).
Don't know what happened here. Maybe by mistake I introduces this when I merged it with the old code used for snooping.
*/
- @BATADV_DAT_IPV4: IPv6 address type
enum batadv_dat_types { BATADV_DAT_IPV4 = 0, +#if IS_ENABLED(CONFIG_IPV6)
BATADV_DAT_IPV6 = 1,
+#endif };
/**
1.7.10.4
-- Antonio Quartulli
..each of us alone is worth nothing.. Ernesto "Che" Guevara
Thanks, Mihail
On Wed, May 29, 2013 at 08:21:37AM -0700, Mihail Costea wrote:
On 26 May 2013 06:57, Antonio Quartulli ordex@autistici.org wrote:
On Fri, May 17, 2013 at 03:27:50PM +0300, Mihail wrote:
From: "mihail.costea90@gmail.com" mihail.costea90@gmail.com
Added IPv6 functionality to generic functions implemented in the first patch.
avoid references to "first"/"second"/"third" patch. Once committed, they will just be some patches in the list. You can either explicitly mention the name of the patch ("writing the subject in this way") or just saying previously/whatever else.
ACK
Signed-off-by: Mihail Costea mihail.costea90@gmail.com Signed-off-by: Stefan Popa Stefan.A.Popa@intel.com Reviewed-by: Stefan Popa Stefan.A.Popa@intel.com
distributed-arp-table.c | 30 ++++++++++++++++++++++++++---- types.h | 6 +++++- 2 files changed, 31 insertions(+), 5 deletions(-)
diff --git a/distributed-arp-table.c b/distributed-arp-table.c index b2ca7e0..42118be 100644 --- a/distributed-arp-table.c +++ b/distributed-arp-table.c @@ -32,7 +32,7 @@ #include "unicast.h"
static char *batadv_dat_types_str_fmt[] = {
"%pI4",
"%pI4", "%pI6c",
better going on a new line rather than putting both on the same one (like the array declared in the gateway code).
ACK
};
static void batadv_dat_purge(struct work_struct *work); @@ -173,6 +173,10 @@ static size_t batadv_sizeof_dat_data(uint8_t data_type) switch (data_type) { case BATADV_DAT_IPV4: return sizeof(__be32); +#if IS_ENABLED(CONFIG_IPV6)
case BATADV_DAT_IPV6:
return sizeof(struct in6_addr);
+#endif default: return 0; } @@ -295,6 +299,12 @@ static uint32_t batadv_hash_dat_ipv4(const void *data, uint32_t size) return batadv_hash_dat(data, BATADV_DAT_IPV4, size); }
+#if IS_ENABLED(CONFIG_IPV6) +static uint32_t batadv_hash_dat_ipv6(const void *data, uint32_t size) +{
return batadv_hash_dat(data, BATADV_DAT_IPV6, size);
+} +#endif
/**
- batadv_dat_entry_hash_find - look for a given dat_entry in the local hash
@@ -393,6 +403,11 @@ static void batadv_dat_entry_add(struct batadv_priv *bat_priv, void *data, case BATADV_DAT_IPV4: choose = batadv_hash_dat_ipv4; break; +#if IS_ENABLED(CONFIG_IPV6)
case BATADV_DAT_IPV6:
choose = batadv_hash_dat_ipv6;
break;
+#endif
mh...I was just wondering: for the hash functions it would be nice to re-use the same "array approach" that you used for the printing format.
So we would have an array of function pointers to reference rather than having this switch block...What do you think?
I think it would be possible to do this for many other "variable" parameters if required.
Should there be a struct that contains all of them, like:
struct batadv_dat_data { char *format; signature *hash_function; ....... }
And after that the array with the initialization for all types. Or should they be declared as arrays that have nothing in common? Like just adding a new array for the choose functions.
I guess you replied to the same email twice. However, the idea of 1 array of structs is nice! I like it :)
On 29 May 2013 08:33, Antonio Quartulli ordex@autistici.org wrote:
On Wed, May 29, 2013 at 08:21:37AM -0700, Mihail Costea wrote:
On 26 May 2013 06:57, Antonio Quartulli ordex@autistici.org wrote:
On Fri, May 17, 2013 at 03:27:50PM +0300, Mihail wrote:
From: "mihail.costea90@gmail.com" mihail.costea90@gmail.com
Added IPv6 functionality to generic functions implemented in the first patch.
avoid references to "first"/"second"/"third" patch. Once committed, they will just be some patches in the list. You can either explicitly mention the name of the patch ("writing the subject in this way") or just saying previously/whatever else.
ACK
Signed-off-by: Mihail Costea mihail.costea90@gmail.com Signed-off-by: Stefan Popa Stefan.A.Popa@intel.com Reviewed-by: Stefan Popa Stefan.A.Popa@intel.com
distributed-arp-table.c | 30 ++++++++++++++++++++++++++---- types.h | 6 +++++- 2 files changed, 31 insertions(+), 5 deletions(-)
diff --git a/distributed-arp-table.c b/distributed-arp-table.c index b2ca7e0..42118be 100644 --- a/distributed-arp-table.c +++ b/distributed-arp-table.c @@ -32,7 +32,7 @@ #include "unicast.h"
static char *batadv_dat_types_str_fmt[] = {
"%pI4",
"%pI4", "%pI6c",
better going on a new line rather than putting both on the same one (like the array declared in the gateway code).
ACK
};
static void batadv_dat_purge(struct work_struct *work); @@ -173,6 +173,10 @@ static size_t batadv_sizeof_dat_data(uint8_t data_type) switch (data_type) { case BATADV_DAT_IPV4: return sizeof(__be32); +#if IS_ENABLED(CONFIG_IPV6)
case BATADV_DAT_IPV6:
return sizeof(struct in6_addr);
+#endif default: return 0; } @@ -295,6 +299,12 @@ static uint32_t batadv_hash_dat_ipv4(const void *data, uint32_t size) return batadv_hash_dat(data, BATADV_DAT_IPV4, size); }
+#if IS_ENABLED(CONFIG_IPV6) +static uint32_t batadv_hash_dat_ipv6(const void *data, uint32_t size) +{
return batadv_hash_dat(data, BATADV_DAT_IPV6, size);
+} +#endif
/**
- batadv_dat_entry_hash_find - look for a given dat_entry in the local hash
@@ -393,6 +403,11 @@ static void batadv_dat_entry_add(struct batadv_priv *bat_priv, void *data, case BATADV_DAT_IPV4: choose = batadv_hash_dat_ipv4; break; +#if IS_ENABLED(CONFIG_IPV6)
case BATADV_DAT_IPV6:
choose = batadv_hash_dat_ipv6;
break;
+#endif
mh...I was just wondering: for the hash functions it would be nice to re-use the same "array approach" that you used for the printing format.
So we would have an array of function pointers to reference rather than having this switch block...What do you think?
I think it would be possible to do this for many other "variable" parameters if required.
Should there be a struct that contains all of them, like:
struct batadv_dat_data { char *format; signature *hash_function; ....... }
And after that the array with the initialization for all types. Or should they be declared as arrays that have nothing in common? Like just adding a new array for the choose functions.
I guess you replied to the same email twice. However, the idea of 1 array of structs is nice! I like it :)
Sorry about that. I thought it didn't send (I was messing with tab key).
I'll implement it in the next version for a review :).
-- Antonio Quartulli
..each of us alone is worth nothing.. Ernesto "Che" Guevara
-- Mihail Costea
On Wed, May 29, 2013 at 09:12:49AM -0700, Mihail Costea wrote:
I guess you replied to the same email twice. However, the idea of 1 array of structs is nice! I like it :)
Sorry about that. I thought it didn't send (I was messing with tab key).
no worries :)
I'll implement it in the next version for a review :).
Great! Sounds cool :)
Cheers,
From: "mihail.costea90@gmail.com" mihail.costea90@gmail.com
Added functions needed for NDP snooping, like getting the IPv6 addresses or getting the target HW address from an Neighbor Advertisement (NA). Also added functions to create NA for Neighbor Solicitations that have already the HW address in DAT.
Problems: I have to generate router and override flags for NA. For now I don't now exactly how to get them. From what I've seen, batman could now which nodes are routers, but for override flag, we should find a mechanism to know if the node is proxy or has anycast address. For inspiration I have used the code at: <net/ipv6/ndisc.c>.
Signed-off-by: Mihail Costea mihail.costea90@gmail.com Signed-off-by: Stefan Popa Stefan.A.Popa@intel.com Reviewed-by: Stefan Popa Stefan.A.Popa@intel.com
--- distributed-arp-table.c | 322 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 322 insertions(+)
diff --git a/distributed-arp-table.c b/distributed-arp-table.c index 42118be..bd69b89 100644 --- a/distributed-arp-table.c +++ b/distributed-arp-table.c @@ -19,7 +19,9 @@
#include <linux/if_ether.h> #include <linux/if_arp.h> +#include <net/addrconf.h> #include <net/arp.h> +#include <net/ipv6.h>
#include "main.h" #include "hash.h" @@ -999,6 +1001,326 @@ out: return type; }
+#if IS_ENABLED(CONFIG_IPV6) +/** + * batadv_ndisc_hw_src - get source hw address from a packet + * @skb: packet to check + * @hdr_size: size of the encapsulation header + * + * Returns source hw address of the skb packet. + */ +static uint8_t *batadv_ndisc_hw_src(struct sk_buff *skb, int hdr_size) +{ + struct ethhdr *ethhdr; + ethhdr = (struct ethhdr *)(skb->data + hdr_size); + return (uint8_t *)ethhdr->h_source; +} + +/** + * batadv_ndisc_hw_dst - get destination hw address from a packet + * @skb: packet to check + * @hdr_size: size of the encapsulation header + * + * Returns destination hw address of the skb packet. + */ +static uint8_t *batadv_ndisc_hw_dst(struct sk_buff *skb, int hdr_size) +{ + struct ethhdr *ethhdr; + ethhdr = (struct ethhdr *)(skb->data + hdr_size); + return (uint8_t *)ethhdr->h_dest; +} + +/** + * batadv_ndisc_ipv6_src - get source IPv6 address from a packet + * @skb: packet to check + * @hdr_size: size of the encapsulation header + * + * Returns source IPv6 address of the skb packet. + */ +static struct in6_addr *batadv_ndisc_ipv6_src(struct sk_buff *skb, + int hdr_size) +{ + struct ipv6hdr *ipv6hdr; + ipv6hdr = (struct ipv6hdr *)(skb->data + hdr_size + ETH_HLEN); + return &ipv6hdr->saddr; +} + +/** + * batadv_ndisc_ipv6_dst - get destination IPv6 address from a packet + * @skb: packet to check + * @hdr_size: size of the encapsulation header + * + * Returns destination IPv6 address of the skb packet. + */ +static struct in6_addr *batadv_ndisc_ipv6_dst(struct sk_buff *skb, + int hdr_size) +{ + struct ipv6hdr *ipv6hdr; + ipv6hdr = (struct ipv6hdr *)(skb->data + hdr_size + ETH_HLEN); + return &ipv6hdr->daddr; +} + +/** + * batadv_ndisc_ipv6_target - get target IPv6 address from a NS/NA packet + * @skb: packet to check + * @hdr_size: size of the encapsulation header + * + * Returns target IPv6 address of the skb packet. + */ +static struct in6_addr *batadv_ndisc_ipv6_target(struct sk_buff *skb, + int hdr_size) +{ + return (struct in6_addr *)(skb->data + hdr_size + ETH_HLEN + + sizeof(struct ipv6hdr) + sizeof(struct icmp6hdr)); +} + +/** + * batadv_ndisc_hw_opt - get hw address from NS/NA packet options + * @skb: packet to check + * @hdr_size: size of the encapsulation header + * @type: type of the address (ND_OPT_SOURCE_LL_ADDR or ND_OPT_TARGET_LL_ADDR) + * + * The address can be either the source link-layer address + * or the target link-layer address. + * For more info see RFC2461. + * + * Returns hw address from packet options. + */ +static uint8_t *batadv_ndisc_hw_opt(struct sk_buff *skb, int hdr_size, + uint8_t type) +{ + unsigned char *opt_addr; + + opt_addr = skb->data + hdr_size + ETH_HLEN + + sizeof(struct ipv6hdr) + sizeof(struct icmp6hdr) + + sizeof(struct in6_addr); + + /* test if option header is ok */ + if (*opt_addr != type || *(opt_addr + 1) != 1) + return NULL; + return (uint8_t *)(opt_addr + 2); +} + +/** + * batadv_ndisc_get_type - get icmp6 packet type + * @bat_priv: the bat priv with all the soft interface information + * @skb: packet to check + * @hdr_size: size of the encapsulation header + * + * Returns the icmp6 type, or 0 if packet is not a valid icmp6 packet. + */ +static __u8 batadv_ndisc_get_type(struct batadv_priv *bat_priv, + struct sk_buff *skb, int hdr_size) +{ + struct ethhdr *ethhdr; + struct ipv6hdr *ipv6hdr; + struct icmp6hdr *icmp6hdr; + __u8 type = 0; + + /* pull headers */ + if (unlikely(!pskb_may_pull(skb, hdr_size + ETH_HLEN + + sizeof(struct ipv6hdr) + sizeof(struct icmp6hdr)))) + goto out; + + /* get the ethernet header */ + ethhdr = (struct ethhdr *)(skb->data + hdr_size); + if (ethhdr->h_proto != htons(ETH_P_IPV6)) + goto out; + + /* get the ipv6 header */ + ipv6hdr = (struct ipv6hdr *)(skb->data + hdr_size + ETH_HLEN); + if (ipv6hdr->nexthdr != IPPROTO_ICMPV6) + goto out; + + /* get the icmpv6 header */ + icmp6hdr = (struct icmp6hdr *)(skb->data + hdr_size + ETH_HLEN + + sizeof(struct ipv6hdr)); + + /* check whether the ndisc packet carries a valid icmp6 header */ + if (ipv6hdr->hop_limit != 255) + goto out; + + if (icmp6hdr->icmp6_code != 0) + goto out; + + type = icmp6hdr->icmp6_type; +out: + return type; +} + +/** + * batadv_ndisc_is_valid - check if a ndisc packet is valid + * @bat_priv: the bat priv with all the soft interface information + * @skb: packet to check + * @hdr_size: size of the encapsulation header + * @ndisc_type: type of ndisc packet to check + * + * Check if all IPs are valid (source, destination, target) and if + * options hw address is valid too. + * Some options might be ignored, like NS packets sent automatically + * for verification of the reachability of a neighbor. + * + * Returns true if packet is valid, otherwise false if invalid or ignored. + */ +static bool batadv_ndisc_is_valid(struct batadv_priv *bat_priv, + struct sk_buff *skb, int hdr_size, + int ndisc_type) +{ + uint8_t *hw_target = NULL; + struct in6_addr *ipv6_src, *ipv6_dst, *ipv6_target; + __u8 type = batadv_ndisc_get_type(bat_priv, skb, hdr_size); + int ndisc_hdr_len = hdr_size + ETH_HLEN + sizeof(struct ipv6hdr) + + sizeof(struct icmp6hdr) + sizeof(struct in6_addr) + + 8; /* ndisc options length */ + + if (type != ndisc_type) + return false; + if (unlikely(!pskb_may_pull(skb, ndisc_hdr_len))) + return false; + + /* Check for bad NA/NS. If the ndisc message is not sane, DAT + * will simply ignore it + */ + if (type == NDISC_NEIGHBOUR_SOLICITATION) + hw_target = batadv_ndisc_hw_opt(skb, hdr_size, + ND_OPT_SOURCE_LL_ADDR); + else if (type == NDISC_NEIGHBOUR_ADVERTISEMENT) + hw_target = batadv_ndisc_hw_opt(skb, hdr_size, + ND_OPT_TARGET_LL_ADDR); + + if (!hw_target || is_zero_ether_addr(hw_target) || + is_multicast_ether_addr(hw_target)) + return false; + + ipv6_src = batadv_ndisc_ipv6_src(skb, hdr_size); + ipv6_dst = batadv_ndisc_ipv6_dst(skb, hdr_size); + ipv6_target = batadv_ndisc_ipv6_target(skb, hdr_size); + if (ipv6_addr_loopback(ipv6_src) || ipv6_addr_loopback(ipv6_dst) || + ipv6_addr_is_multicast(ipv6_src) || + ipv6_addr_is_multicast(ipv6_target)) + return false; + + /* ignore messages with unspecified address */ + if (ipv6_addr_any(ipv6_src) || ipv6_addr_any(ipv6_dst) || + ipv6_addr_any(ipv6_target)) + return false; + + /* ignore the verification of the reachability of a neighbor */ + if (type == NDISC_NEIGHBOUR_SOLICITATION && + !ipv6_addr_is_multicast(ipv6_dst)) + return false; + + return true; +} + +static void batadv_ndisc_ip6_hdr(struct sock *sk, struct sk_buff *skb, + struct net_device *dev, + const struct in6_addr *ipv6_src, + const struct in6_addr *ipv6_dst, + int proto, int len) +{ + struct ipv6_pinfo *np = inet6_sk(sk); + struct ipv6hdr *hdr; + + skb->protocol = htons(ETH_P_IPV6); + skb->dev = dev; + + skb_reset_network_header(skb); + skb_put(skb, sizeof(struct ipv6hdr)); + hdr = ipv6_hdr(skb); + + *(__be32 *)hdr = htonl(0x60000000); + + hdr->payload_len = htons(len); + hdr->nexthdr = proto; + hdr->hop_limit = np->hop_limit; + + hdr->saddr = *ipv6_src; + hdr->daddr = *ipv6_dst; +} + +/** + * batadv_ndisc_create_na - create an NA for a solicited NS + * @net_device: the devices for which the packet is created + * @ipv6_dst: destination IPv6 + * @ipv6_target: target IPv6 (same with source IPv6) + * @hw_dst: destination HW Address + * @hw_target: target HW Address (same with source HW Address) + * @router: 1 if target is a router, else 0 + * @solicited: 1 if this is a solicited NA, else 0 + * @override: 1 if the target entry should be override, else 0 + * + * TODO problem with router and override parameters + * (how do we calculate them ?) + * + * For more info see RFC2461. + * + * Returns the newly created skb, otherwise NULL. + */ +static struct +sk_buff *batadv_ndisc_create_na(struct net_device *dev, + const struct in6_addr *ipv6_dst, + const struct in6_addr *ipv6_target, + const uint8_t *hw_dst, + const uint8_t *hw_target, + int router, int solicited, int override) +{ + struct net *net = dev_net(dev); + struct sock *sk = net->ipv6.ndisc_sk; + struct sk_buff *skb; + struct icmp6hdr *icmp6hdr; + int hlen = LL_RESERVED_SPACE(dev); + int tlen = dev->needed_tailroom; + int len, err; + u8 *opt; + + /* alloc space for skb */ + len = sizeof(struct icmp6hdr) + sizeof(*ipv6_target) + 8; + skb = sock_alloc_send_skb(sk, + (MAX_HEADER + sizeof(struct ipv6hdr) + + len + hlen + tlen), + 1, &err); + if (!skb) + return NULL; + + skb_reserve(skb, hlen); + batadv_ndisc_ip6_hdr(sk, skb, dev, ipv6_target, ipv6_dst, + IPPROTO_ICMPV6, len); + + skb->transport_header = skb->tail; + skb_put(skb, len); + + /* fill the device header for the NA frame */ + if (dev_hard_header(skb, dev, ETH_P_IPV6, hw_dst, + hw_target, skb->len) < 0) { + kfree_skb(skb); + return NULL; + } + + /* set icmpv6 header */ + icmp6hdr = (struct icmp6hdr *)skb_transport_header(skb); + icmp6hdr->icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT; + icmp6hdr->icmp6_router = router; + icmp6hdr->icmp6_solicited = solicited; + icmp6hdr->icmp6_override = override; + + /* set NA target and options */ + opt = skb_transport_header(skb) + sizeof(*icmp6hdr); + *(struct in6_addr *)opt = *ipv6_target; + opt += sizeof(*ipv6_target); + + opt[0] = ND_OPT_TARGET_LL_ADDR; + opt[1] = 1; + memcpy(opt + 2, hw_target, dev->addr_len); + + icmp6hdr->icmp6_cksum = csum_ipv6_magic(ipv6_target, ipv6_dst, len, + IPPROTO_ICMPV6, + csum_partial(icmp6hdr, len, 0)); + + return skb; +} +#endif + /** * batadv_dat_snoop_outgoing_msg_request - snoop the ARP request and try to * answer using DAT
On Fri, May 17, 2013 at 03:27:51PM +0300, Mihail wrote:
From: "mihail.costea90@gmail.com" mihail.costea90@gmail.com
Added functions needed for NDP snooping, like getting the IPv6 addresses or getting the target HW address from an Neighbor Advertisement (NA). Also added functions to create NA for Neighbor Solicitations that have already the HW address in DAT.
Problems: I have to generate router and override flags for NA. For now I don't now exactly how to get them. From what I've seen, batman could now which nodes are routers, but for override flag, we should find a mechanism to know if the node is proxy or has anycast address. For inspiration I have used the code at: <net/ipv6/ndisc.c>.
What is the concept you have in mind? Maybe you first explain a bit more about your idea so that we can help you in find a way to implement that.
You want to edit the router address and flags carried by the NA?
On 26 May 2013 07:02, Antonio Quartulli ordex@autistici.org wrote:
On Fri, May 17, 2013 at 03:27:51PM +0300, Mihail wrote:
From: "mihail.costea90@gmail.com" mihail.costea90@gmail.com
Added functions needed for NDP snooping, like getting the IPv6 addresses or getting the target HW address from an Neighbor Advertisement (NA). Also added functions to create NA for Neighbor Solicitations that have already the HW address in DAT.
Problems: I have to generate router and override flags for NA. For now I don't now exactly how to get them. From what I've seen, batman could now which nodes are routers, but for override flag, we should find a mechanism to know if the node is proxy or has anycast address. For inspiration I have used the code at: <net/ipv6/ndisc.c>.
What is the concept you have in mind? Maybe you first explain a bit more about your idea so that we can help you in find a way to implement that.
You want to edit the router address and flags carried by the NA?
When creating the NA response for an HW address already contained in the DAT, I must set 3 flags: router, solicited and override.
The solicited flag is 1 because I only answer to solicited NS.
The router flag should be 1 only if the device for which we have the HW address is a router. From what I've seen there are some functions in batatv for finding routers, but I'll have to see if they can be used on the nodes connected to mesh-nodes. Or maybe there is another way to see if the device is a router.
About the override flag, I don't really have an idea. I didn't understand very well how it was calculated in net/ipv6/ndisc.c so I set it to 1 by default (it should be 0 for proxy and anycast address).
-- Antonio Quartulli
..each of us alone is worth nothing.. Ernesto "Che" Guevara
Thanks, Mihail
On Wed, May 29, 2013 at 08:36:50AM -0700, Mihail Costea wrote:
On 26 May 2013 07:02, Antonio Quartulli ordex@autistici.org wrote:
On Fri, May 17, 2013 at 03:27:51PM +0300, Mihail wrote:
From: "mihail.costea90@gmail.com" mihail.costea90@gmail.com
Added functions needed for NDP snooping, like getting the IPv6 addresses or getting the target HW address from an Neighbor Advertisement (NA). Also added functions to create NA for Neighbor Solicitations that have already the HW address in DAT.
Problems: I have to generate router and override flags for NA. For now I don't now exactly how to get them. From what I've seen, batman could now which nodes are routers, but for override flag, we should find a mechanism to know if the node is proxy or has anycast address. For inspiration I have used the code at: <net/ipv6/ndisc.c>.
What is the concept you have in mind? Maybe you first explain a bit more about your idea so that we can help you in find a way to implement that.
You want to edit the router address and flags carried by the NA?
When creating the NA response for an HW address already contained in the DAT, I must set 3 flags: router, solicited and override.
The solicited flag is 1 because I only answer to solicited NS.
The router flag should be 1 only if the device for which we have the HW address is a router. From what I've seen there are some functions in batatv for finding routers, but I'll have to see if they can be used on the nodes connected to mesh-nodes. Or maybe there is another way to see if the device is a router.
I guess here you are looking for an IPv6 router, right? so a node which advertised itself as it, correct? In this case in batman-adv there is nothing which can help you because there is no IPv6 detection of any type.. How can we recognise if a node is advertising itself as router? maybe by snooping other NDP messages?
About the override flag, I don't really have an idea. I didn't understand very well how it was calculated in net/ipv6/ndisc.c so I set it to 1 by default (it should be 0 for proxy and anycast address).
mh..ok. We may want to better check this once more to avoid triggering any strange behaviour in the network :)
Cheers,
On 29 May 2013 08:43, Antonio Quartulli ordex@autistici.org wrote:
On Wed, May 29, 2013 at 08:36:50AM -0700, Mihail Costea wrote:
On 26 May 2013 07:02, Antonio Quartulli ordex@autistici.org wrote:
On Fri, May 17, 2013 at 03:27:51PM +0300, Mihail wrote:
From: "mihail.costea90@gmail.com" mihail.costea90@gmail.com
Added functions needed for NDP snooping, like getting the IPv6 addresses or getting the target HW address from an Neighbor Advertisement (NA). Also added functions to create NA for Neighbor Solicitations that have already the HW address in DAT.
Problems: I have to generate router and override flags for NA. For now I don't now exactly how to get them. From what I've seen, batman could now which nodes are routers, but for override flag, we should find a mechanism to know if the node is proxy or has anycast address. For inspiration I have used the code at: <net/ipv6/ndisc.c>.
What is the concept you have in mind? Maybe you first explain a bit more about your idea so that we can help you in find a way to implement that.
You want to edit the router address and flags carried by the NA?
When creating the NA response for an HW address already contained in the DAT, I must set 3 flags: router, solicited and override.
The solicited flag is 1 because I only answer to solicited NS.
The router flag should be 1 only if the device for which we have the HW address is a router. From what I've seen there are some functions in batatv for finding routers, but I'll have to see if they can be used on the nodes connected to mesh-nodes. Or maybe there is another way to see if the device is a router.
I guess here you are looking for an IPv6 router, right? so a node which advertised itself as it, correct? In this case in batman-adv there is nothing which can help you because there is no IPv6 detection of any type.. How can we recognise if a node is advertising itself as router? maybe by snooping other NDP messages?
I'll look into this. There are some router packets, so those might be useful.
About the override flag, I don't really have an idea. I didn't understand very well how it was calculated in net/ipv6/ndisc.c so I set it to 1 by default (it should be 0 for proxy and anycast address).
mh..ok. We may want to better check this once more to avoid triggering any strange behaviour in the network :)
Cheers,
-- Antonio Quartulli
..each of us alone is worth nothing.. Ernesto "Che" Guevara
This needs more research. Maybe we can find something for this.
I'll get a laptop in 1-2 weeks, but I'll be able to work only during weekends. I'll implement the mentioned changes at that moment.
-- Mihail Costea
From: "mihail.costea90@gmail.com" mihail.costea90@gmail.com
Generalized snooping functions in order to support Neighbor Advertisement and Neighbor Solicitation too.
Signed-off-by: Mihail Costea mihail.costea90@gmail.com Signed-off-by: Stefan Popa Stefan.A.Popa@intel.com Reviewed-by: Stefan Popa Stefan.A.Popa@intel.com
--- distributed-arp-table.c | 459 +++++++++++++++++++++++++++++++++++------------ types.h | 16 ++ 2 files changed, 360 insertions(+), 115 deletions(-)
diff --git a/distributed-arp-table.c b/distributed-arp-table.c index bd69b89..9bac6cb 100644 --- a/distributed-arp-table.c +++ b/distributed-arp-table.c @@ -235,9 +235,9 @@ static uint8_t *batadv_arp_hw_src(struct sk_buff *skb, int hdr_size) * * Returns the value of the ip_src field in the ARP packet. */ -static __be32 batadv_arp_ip_src(struct sk_buff *skb, int hdr_size) +static __be32 *batadv_arp_ip_src(struct sk_buff *skb, int hdr_size) { - return *(__be32 *)(batadv_arp_hw_src(skb, hdr_size) + ETH_ALEN); + return (__be32 *)(batadv_arp_hw_src(skb, hdr_size) + ETH_ALEN); }
/** @@ -259,9 +259,9 @@ static uint8_t *batadv_arp_hw_dst(struct sk_buff *skb, int hdr_size) * * Returns the value of the ip_dst field in the ARP packet. */ -static __be32 batadv_arp_ip_dst(struct sk_buff *skb, int hdr_size) +static __be32 *batadv_arp_ip_dst(struct sk_buff *skb, int hdr_size) { - return *(__be32 *)(batadv_arp_hw_src(skb, hdr_size) + ETH_ALEN * 2 + 4); + return (__be32 *)(batadv_arp_hw_src(skb, hdr_size) + ETH_ALEN * 2 + 4); }
/** @@ -456,8 +456,8 @@ static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb, if (msg) batadv_dbg(BATADV_DBG_DAT, bat_priv, "%s\n", msg);
- ip_src = batadv_arp_ip_src(skb, hdr_size); - ip_dst = batadv_arp_ip_dst(skb, hdr_size); + ip_src = *batadv_arp_ip_src(skb, hdr_size); + ip_dst = *batadv_arp_ip_dst(skb, hdr_size); batadv_dbg(BATADV_DBG_DAT, bat_priv, "ARP MSG = [src: %pM-%pI4 dst: %pM-%pI4]\n", batadv_arp_hw_src(skb, hdr_size), &ip_src, @@ -976,8 +976,8 @@ static uint16_t batadv_arp_get_type(struct batadv_priv *bat_priv, /* Check for bad reply/request. If the ARP message is not sane, DAT * will simply ignore it */ - ip_src = batadv_arp_ip_src(skb, hdr_size); - ip_dst = batadv_arp_ip_dst(skb, hdr_size); + ip_src = *batadv_arp_ip_src(skb, hdr_size); + ip_dst = *batadv_arp_ip_dst(skb, hdr_size); if (ipv4_is_loopback(ip_src) || ipv4_is_multicast(ip_src) || ipv4_is_loopback(ip_dst) || ipv4_is_multicast(ip_dst) || ipv4_is_zeronet(ip_src) || ipv4_is_lbcast(ip_src) || @@ -1319,11 +1319,237 @@ sk_buff *batadv_ndisc_create_na(struct net_device *dev,
return skb; } + +/** + * batadv_dat_snoop_ndisc_addr - snoop addresses from NA / NS messages + * @skb: packet to snoop + * @hdr_size: size of the encapsulation header + * @target_address_type: type of target address + * (ND_OPT_SOURCE_LL_ADDR or ND_OPT_TARGET_LL_ADDR) + * @hw_src: source HW Address + * @ipv6_src: source IPv6 + * @hw_dst: destination HW Address + * @ipv6_dst: destination IPv6 + * @hw_target: target HW Address + * @ipv6_target: target IPv6 + * + * If an address parameter is NULL, then the correspondent field is not + * snooped. The fields might be different depending on packet type (NS / NA). + * + * Return true if snooping was successful. + */ +static bool batadv_dat_snoop_ndisc_addr(struct sk_buff *skb, int hdr_size, + uint8_t target_address_type, + uint8_t **hw_src, void **ipv6_src, + uint8_t **hw_dst, void **ipv6_dst, + uint8_t **hw_target, void **ipv6_target) +{ + if (hw_src) + *hw_src = batadv_ndisc_hw_src(skb, hdr_size); + if (ipv6_src) + *ipv6_src = batadv_ndisc_ipv6_src(skb, hdr_size); + if (hw_dst) + *hw_dst = batadv_ndisc_hw_dst(skb, hdr_size); + if (ipv6_dst) + *ipv6_dst = batadv_ndisc_ipv6_dst(skb, hdr_size); + if (hw_target) { + *hw_target = batadv_ndisc_hw_opt(skb, hdr_size, + target_address_type); + if (!*hw_target) + return false; + } + if (ipv6_target) + *ipv6_target = batadv_ndisc_ipv6_target(skb, hdr_size); + + return true; +} +#endif + +/** + * batadv_dat_snoop_arp_addr - snoop addresses from ARP Request / Reply + * @skb: packet to snoop + * @hdr_size: size of the encapsulation header + * @hw_src: source HW Address + * @ip_src: source IPv4 + * @hw_dst: destination HW Address + * @ip_dst: destination IPv4 + */ +static void batadv_dat_snoop_arp_addr(struct sk_buff *skb, int hdr_size, + uint8_t **hw_src, void **ip_src, + uint8_t **hw_dst, void **ip_dst) +{ + *hw_src = batadv_arp_hw_src(skb, hdr_size); + *ip_src = batadv_arp_ip_src(skb, hdr_size); + *hw_dst = batadv_arp_hw_dst(skb, hdr_size); + *ip_dst = batadv_arp_ip_dst(skb, hdr_size); +} + +/** + * batadv_dat_snoop_msg_addresses - snooping mechanism for all packets that + * participate in DAT + * @bat_priv: the bat priv with all the soft interface information + * @skb: packet to snoop + * @hdr_size: size of the encapsulation header + * @msg_type: outgoing / incoming message request / reply + * @hw_src: source HW Address + * @ip_src: source IP + * @hw_dst: destination HW Address + * @ip_dst: destination IP + * + * Returns a batadv_dat_types data type. + */ +static int batadv_dat_snoop_msg(struct batadv_priv *bat_priv, + struct sk_buff *skb, int hdr_size, + uint8_t msg_type, + uint8_t **hw_src, void **ip_src, + uint8_t **hw_dst, void **ip_dst) +{ + uint16_t type; + int data_type = -1; + + /* parse message requests */ + type = batadv_arp_get_type(bat_priv, skb, hdr_size); + if (msg_type == BATADV_DAT_OUTGOING_MSG_REQUEST || + msg_type == BATADV_DAT_INCOMING_MSG_REQUEST) { + if (type == ARPOP_REQUEST) { + batadv_dat_snoop_arp_addr(skb, hdr_size, hw_src, ip_src, + hw_dst, ip_dst); + batadv_dbg_arp(bat_priv, skb, type, hdr_size, + "Parsing ARP REQUEST"); + data_type = BATADV_DAT_IPV4; + goto out; + } + +#if IS_ENABLED(CONFIG_IPV6) + if (batadv_ndisc_is_valid(bat_priv, skb, hdr_size, + NDISC_NEIGHBOUR_SOLICITATION)) { + if (!batadv_dat_snoop_ndisc_addr(skb, hdr_size, + ND_OPT_SOURCE_LL_ADDR, + NULL, ip_src, + hw_dst, NULL, + hw_src, ip_dst)) + goto out; + + batadv_dbg(BATADV_DBG_DAT, bat_priv, + "Parsing NS = [src: %pM / %pI6c -> " + "target: %pM / %pI6c]\n", + *hw_src, *ip_src, *hw_dst, *ip_dst); + data_type = BATADV_DAT_IPV6; + goto out; + } +#endif + } + + /* parse message replies */ + if (msg_type == BATADV_DAT_OUTGOING_MSG_REPLY || + msg_type == BATADV_DAT_INCOMING_MSG_REPLY) { + if (type == ARPOP_REPLY) { + batadv_dat_snoop_arp_addr(skb, hdr_size, hw_src, ip_src, + hw_dst, ip_dst); + batadv_dbg_arp(bat_priv, skb, type, hdr_size, + "Parsing ARP REPLY"); + data_type = BATADV_DAT_IPV4; + goto out; + } + +#if IS_ENABLED(CONFIG_IPV6) + if (batadv_ndisc_is_valid(bat_priv, skb, hdr_size, + NDISC_NEIGHBOUR_ADVERTISEMENT)) { + if (!batadv_dat_snoop_ndisc_addr(skb, hdr_size, + ND_OPT_TARGET_LL_ADDR, + NULL, NULL, + hw_dst, ip_dst, + hw_src, ip_src)) + goto out; + + batadv_dbg(BATADV_DBG_DAT, bat_priv, + "Parsing NA = [src: %pM / %pI6c -> " + "target: %pM / %pI6c]\n", + *hw_src, *ip_src, *hw_dst, *ip_dst); + + data_type = BATADV_DAT_IPV6; + goto out; + } +#endif + } + +out: + return data_type; +} + +/** + * batadv_dat_snoop_ip_dst - snoops only destination IP from skb + * (useful for broadcast check) + * @bat_priv: the bat priv with all the soft interface information + * @skb: packet to snoop + * @hdr_size: size of the encapsulation header + * @ip_dst: destination IP + * + * Returns a batadv_dat_types data type. + */ +static int batadv_dat_snoop_ip_dst(struct batadv_priv *bat_priv, + struct sk_buff *skb, int hdr_size, + void **ip_dst) +{ + int data_type = -1; + + if (batadv_arp_get_type(bat_priv, skb, hdr_size) == ARPOP_REQUEST) { + *ip_dst = batadv_arp_ip_dst(skb, hdr_size); + data_type = BATADV_DAT_IPV4; + goto out; + } + +#if IS_ENABLED(CONFIG_IPV6) + if (batadv_ndisc_is_valid(bat_priv, skb, hdr_size, + NDISC_NEIGHBOUR_SOLICITATION)) { + *ip_dst = batadv_ndisc_ipv6_target(skb, hdr_size); + data_type = BATADV_DAT_IPV6; + goto out; + } +#endif + +out: + return data_type; +} + +/** + * batadv_dat_create_skb - creates a skb as a reply to a message request + * (useful for broadcast check) + * @bat_priv: the bat priv with all the soft interface information + * @dat_entry: the DAT entry used for destination HW Address + * @hdr_size: size of the encapsulation header + * @hw_src: source HW Address + * @ip_src: source IP + * @ip_dst: destination IP + * + * Returns the newly created skb, or NULL if any error. + */ +struct sk_buff *batadv_dat_create_skb(struct batadv_priv *bat_priv, + struct batadv_dat_entry *dat_entry, + uint8_t *hw_src, void *ip_src, + void *ip_dst) +{ + switch (dat_entry->type) { + case BATADV_DAT_IPV4: + return arp_create(ARPOP_REPLY, ETH_P_ARP, *(__be32 *)ip_src, + bat_priv->soft_iface, *(__be32 *)ip_dst, + hw_src, dat_entry->mac_addr, hw_src); +#if IS_ENABLED(CONFIG_IPV6) + case BATADV_DAT_IPV6: + /* TODO calculate router and override parameters */ + return batadv_ndisc_create_na(bat_priv->soft_iface, + ip_src, ip_dst, + hw_src, dat_entry->mac_addr, + 0, 1, 1); #endif + default: + return NULL; + } +}
/** - * batadv_dat_snoop_outgoing_msg_request - snoop the ARP request and try to - * answer using DAT + * batadv_dat_snoop_outgoing_msg_request - snoop the ARP request / NS + * and try to answer using DAT * @bat_priv: the bat priv with all the soft interface information * @skb: packet to check * @@ -1334,50 +1560,33 @@ sk_buff *batadv_ndisc_create_na(struct net_device *dev, bool batadv_dat_snoop_outgoing_msg_request(struct batadv_priv *bat_priv, struct sk_buff *skb) { - uint16_t type = 0; - __be32 ip_dst, ip_src; - uint8_t *hw_src; + void *ip_src, *ip_dst; + uint8_t *hw_src, *hw_dst; bool ret = false; struct batadv_dat_entry *dat_entry = NULL; struct sk_buff *skb_new; + int data_type;
if (!atomic_read(&bat_priv->distributed_arp_table)) goto out;
- type = batadv_arp_get_type(bat_priv, skb, 0); - /* If the node gets an ARP_REQUEST it has to send a DHT_GET unicast + /* If the node gets an ARP_REQUEST / NS it has to send a DHT_GET unicast * message to the selected DHT candidates */ - if (type != ARPOP_REQUEST) + data_type = batadv_dat_snoop_msg(bat_priv, skb, 0, + BATADV_DAT_OUTGOING_MSG_REQUEST, + &hw_src, &ip_src, + &hw_dst, &ip_dst); + if (data_type < 0) goto out;
- batadv_dbg_arp(bat_priv, skb, type, 0, "Parsing outgoing ARP REQUEST"); + batadv_dat_entry_add(bat_priv, ip_src, data_type, hw_src);
- ip_src = batadv_arp_ip_src(skb, 0); - hw_src = batadv_arp_hw_src(skb, 0); - ip_dst = batadv_arp_ip_dst(skb, 0); - - batadv_dat_entry_add(bat_priv, &ip_src, BATADV_DAT_IPV4, hw_src); - - dat_entry = batadv_dat_entry_hash_find(bat_priv, &ip_dst, - BATADV_DAT_IPV4); + dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst, + data_type); if (dat_entry) { - /* If the ARP request is destined for a local client the local - * client will answer itself. DAT would only generate a - * duplicate packet. - * - * Moreover, if the soft-interface is enslaved into a bridge, an - * additional DAT answer may trigger kernel warnings about - * a packet coming from the wrong port. - */ - if (batadv_is_my_client(bat_priv, dat_entry->mac_addr)) { - ret = true; - goto out; - } - - skb_new = arp_create(ARPOP_REPLY, ETH_P_ARP, ip_src, - bat_priv->soft_iface, ip_dst, hw_src, - dat_entry->mac_addr, hw_src); + skb_new = batadv_dat_create_skb(bat_priv, dat_entry, + hw_src, ip_src, ip_dst); if (!skb_new) goto out;
@@ -1389,12 +1598,12 @@ bool batadv_dat_snoop_outgoing_msg_request(struct batadv_priv *bat_priv, bat_priv->soft_iface->last_rx = jiffies;
netif_rx(skb_new); - batadv_dbg(BATADV_DBG_DAT, bat_priv, "ARP request replied locally\n"); + batadv_dbg(BATADV_DBG_DAT, bat_priv, + "ARP request / NS replied locally\n"); ret = true; } else { /* Send the request to the DHT */ - ret = batadv_dat_send_data(bat_priv, skb, &ip_dst, - BATADV_DAT_IPV4, + ret = batadv_dat_send_data(bat_priv, skb, ip_dst, data_type, BATADV_P_DAT_DHT_GET); } out: @@ -1404,7 +1613,7 @@ out: }
/** - * batadv_dat_snoop_incoming_msg_request - snoop the ARP request and try to + * batadv_dat_snoop_incoming_msg_request - snoop the ARP request / NS and try to * answer using the local DAT storage * @bat_priv: the bat priv with all the soft interface information * @skb: packet to check @@ -1415,39 +1624,31 @@ out: bool batadv_dat_snoop_incoming_msg_request(struct batadv_priv *bat_priv, struct sk_buff *skb, int hdr_size) { - uint16_t type; - __be32 ip_src, ip_dst; - uint8_t *hw_src; + void *ip_src, *ip_dst; + uint8_t *hw_src, *hw_dst; struct sk_buff *skb_new; struct batadv_dat_entry *dat_entry = NULL; bool ret = false; - int err; + int err, data_type;
if (!atomic_read(&bat_priv->distributed_arp_table)) goto out;
- type = batadv_arp_get_type(bat_priv, skb, hdr_size); - if (type != ARPOP_REQUEST) + data_type = batadv_dat_snoop_msg(bat_priv, skb, hdr_size, + BATADV_DAT_INCOMING_MSG_REQUEST, + &hw_src, &ip_src, + &hw_dst, &ip_dst); + if (data_type < 0) goto out;
- hw_src = batadv_arp_hw_src(skb, hdr_size); - ip_src = batadv_arp_ip_src(skb, hdr_size); - ip_dst = batadv_arp_ip_dst(skb, hdr_size); + batadv_dat_entry_add(bat_priv, ip_src, data_type, hw_src);
- batadv_dbg_arp(bat_priv, skb, type, hdr_size, - "Parsing incoming ARP REQUEST"); - - batadv_dat_entry_add(bat_priv, &ip_src, BATADV_DAT_IPV4, hw_src); - - dat_entry = batadv_dat_entry_hash_find(bat_priv, &ip_dst, - BATADV_DAT_IPV4); + dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst, data_type); if (!dat_entry) goto out;
- skb_new = arp_create(ARPOP_REPLY, ETH_P_ARP, ip_src, - bat_priv->soft_iface, ip_dst, hw_src, - dat_entry->mac_addr, hw_src); - + skb_new = batadv_dat_create_skb(bat_priv, dat_entry, + hw_src, ip_src, ip_dst); if (!skb_new) goto out;
@@ -1474,45 +1675,50 @@ out: }
/** - * batadv_dat_snoop_outgoing_msg_reply - snoop the ARP reply and fill the DHT + * batadv_dat_snoop_outgoing_msg_reply - snoop the ARP reply / NA and fill + * the DHT * @bat_priv: the bat priv with all the soft interface information * @skb: packet to check */ void batadv_dat_snoop_outgoing_msg_reply(struct batadv_priv *bat_priv, struct sk_buff *skb) { - uint16_t type; - __be32 ip_src, ip_dst; + void *ip_src, *ip_dst; uint8_t *hw_src, *hw_dst; + int data_type; + bool add_entry = true;
if (!atomic_read(&bat_priv->distributed_arp_table)) return;
- type = batadv_arp_get_type(bat_priv, skb, 0); - if (type != ARPOP_REPLY) + data_type = batadv_dat_snoop_msg(bat_priv, skb, 0, + BATADV_DAT_OUTGOING_MSG_REPLY, + &hw_src, &ip_src, + &hw_dst, &ip_dst); + if (data_type < 0) return;
- batadv_dbg_arp(bat_priv, skb, type, 0, "Parsing outgoing ARP REPLY"); - - hw_src = batadv_arp_hw_src(skb, 0); - ip_src = batadv_arp_ip_src(skb, 0); - hw_dst = batadv_arp_hw_dst(skb, 0); - ip_dst = batadv_arp_ip_dst(skb, 0); - - batadv_dat_entry_add(bat_priv, &ip_src, BATADV_DAT_IPV4, hw_src); - batadv_dat_entry_add(bat_priv, &ip_dst, BATADV_DAT_IPV4, hw_dst); - - /* Send the ARP reply to the candidates for both the IP addresses that - * the node obtained from the ARP reply + batadv_dat_entry_add(bat_priv, ip_src, data_type, hw_src); + /* Send the ARP reply / NA to the candidates for both the IP addresses + * that the node obtained from the ARP reply */ - batadv_dat_send_data(bat_priv, skb, &ip_src, BATADV_DAT_IPV4, - BATADV_P_DAT_DHT_PUT); - batadv_dat_send_data(bat_priv, skb, &ip_dst, BATADV_DAT_IPV4, + batadv_dat_send_data(bat_priv, skb, ip_src, data_type, BATADV_P_DAT_DHT_PUT); + + /* not a solicited advertisement */ +#if IS_ENABLED(CONFIG_IPV6) + if (data_type == BATADV_DAT_IPV6 && ipv6_addr_is_multicast(ip_dst)) + add_entry = false; +#endif + if (add_entry) { + batadv_dat_entry_add(bat_priv, ip_dst, data_type, hw_dst); + batadv_dat_send_data(bat_priv, skb, ip_dst, data_type, + BATADV_P_DAT_DHT_PUT); + } } /** - * batadv_dat_snoop_incoming_msg_reply - snoop the ARP reply and fill the local - * DAT storage only + * batadv_dat_snoop_incoming_msg_reply - snoop the ARP reply / NA and fill the + * local DAT storage only * @bat_priv: the bat priv with all the soft interface information * @skb: packet to check * @hdr_size: size of the encapsulation header @@ -1520,31 +1726,33 @@ void batadv_dat_snoop_outgoing_msg_reply(struct batadv_priv *bat_priv, bool batadv_dat_snoop_incoming_msg_reply(struct batadv_priv *bat_priv, struct sk_buff *skb, int hdr_size) { - uint16_t type; - __be32 ip_src, ip_dst; + void *ip_src, *ip_dst; uint8_t *hw_src, *hw_dst; bool ret = false; + int data_type; + bool add_entry = true;
if (!atomic_read(&bat_priv->distributed_arp_table)) goto out;
- type = batadv_arp_get_type(bat_priv, skb, hdr_size); - if (type != ARPOP_REPLY) + data_type = batadv_dat_snoop_msg(bat_priv, skb, hdr_size, + BATADV_DAT_INCOMING_MSG_REPLY, + &hw_src, &ip_src, + &hw_dst, &ip_dst); + if (data_type < 0) goto out;
- batadv_dbg_arp(bat_priv, skb, type, hdr_size, - "Parsing incoming ARP REPLY"); - - hw_src = batadv_arp_hw_src(skb, hdr_size); - ip_src = batadv_arp_ip_src(skb, hdr_size); - hw_dst = batadv_arp_hw_dst(skb, hdr_size); - ip_dst = batadv_arp_ip_dst(skb, hdr_size); - /* Update our internal cache with both the IP addresses the node got * within the ARP reply */ - batadv_dat_entry_add(bat_priv, &ip_src, BATADV_DAT_IPV4, hw_src); - batadv_dat_entry_add(bat_priv, &ip_dst, BATADV_DAT_IPV4, hw_dst); + batadv_dat_entry_add(bat_priv, ip_src, data_type, hw_src); + /* not a solicited advertisement */ +#if IS_ENABLED(CONFIG_IPV6) + if (data_type == BATADV_DAT_IPV6 && ipv6_addr_is_multicast(ip_dst)) + add_entry = false; +#endif + if (add_entry) + batadv_dat_entry_add(bat_priv, ip_dst, data_type, hw_dst);
/* if this REPLY is directed to a client of mine, let's deliver the * packet to the interface @@ -1558,8 +1766,8 @@ out: }
/** - * batadv_dat_drop_broadcast_packet - check if an ARP request has to be dropped - * (because the node has already obtained the reply via DAT) or not + * batadv_dat_drop_broadcast_packet - check if an ARP request / NS has to be + * dropped (because the node has already obtained the reply via DAT) or not * @bat_priv: the bat priv with all the soft interface information * @forw_packet: the broadcast packet * @@ -1568,37 +1776,58 @@ out: bool batadv_dat_drop_broadcast_packet(struct batadv_priv *bat_priv, struct batadv_forw_packet *forw_packet) { - uint16_t type; - __be32 ip_dst; + void *ip_dst; struct batadv_dat_entry *dat_entry = NULL; bool ret = false; const size_t bcast_len = sizeof(struct batadv_bcast_packet); + int data_type;
if (!atomic_read(&bat_priv->distributed_arp_table)) goto out;
- /* If this packet is an ARP_REQUEST and the node already has the + /* If this packet is an ARP_REQUEST / NS and the node already has the * information that it is going to ask, then the packet can be dropped */ if (forw_packet->num_packets) goto out;
- type = batadv_arp_get_type(bat_priv, forw_packet->skb, bcast_len); - if (type != ARPOP_REQUEST) + data_type = batadv_dat_snoop_ip_dst(bat_priv, forw_packet->skb, + bcast_len, &ip_dst); + if (data_type < 0) goto out;
- ip_dst = batadv_arp_ip_dst(forw_packet->skb, bcast_len); - dat_entry = batadv_dat_entry_hash_find(bat_priv, &ip_dst, - BATADV_DAT_IPV4); + dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst, data_type); /* check if the node already got this entry */ if (!dat_entry) { - batadv_dbg(BATADV_DBG_DAT, bat_priv, - "ARP Request for %pI4: fallback\n", &ip_dst); + switch (data_type) { + case BATADV_DAT_IPV4: + batadv_dbg(BATADV_DBG_DAT, bat_priv, + "ARP Request for %pI4: fallback\n", ip_dst); + break; +#if IS_ENABLED(CONFIG_IPV6) + case BATADV_DAT_IPV6: + batadv_dbg(BATADV_DBG_DAT, bat_priv, + "NS for %pI6c: fallback\n", ip_dst); + break; +#endif + } goto out; }
- batadv_dbg(BATADV_DBG_DAT, bat_priv, - "ARP Request for %pI4: fallback prevented\n", &ip_dst); + switch (data_type) { + case BATADV_DAT_IPV4: + batadv_dbg(BATADV_DBG_DAT, bat_priv, + "ARP Request for %pI4: fallback prevented\n", + ip_dst); + break; +#if IS_ENABLED(CONFIG_IPV6) + case BATADV_DAT_IPV6: + batadv_dbg(BATADV_DBG_DAT, bat_priv, + "NS for %pI6c: fallback prevented\n", ip_dst); + break; + } +#endif + ret = true;
out: diff --git a/types.h b/types.h index 74c7091..ac85d4a 100644 --- a/types.h +++ b/types.h @@ -942,6 +942,22 @@ enum batadv_dat_types { };
/** + * batadv_dat_msg_types - describe generic message types + * @BATADV_DAT_OUTGOING_MSG_REQUEST: an outgoing message request + * @BATADV_DAT_INCOMING_MSG_REQUEST: an incoming message request + * @BATADV_DAT_OUTGOING_MSG_REPLY: an outgoing message reply + * @BATADV_DAT_INCOMING_MSG_REPLY: an incoming message reply + * + * The messages can be ARP Request / Reply, NS / NA or other packets. + */ +enum batadv_dat_msg_types { + BATADV_DAT_OUTGOING_MSG_REQUEST, + BATADV_DAT_INCOMING_MSG_REQUEST, + BATADV_DAT_OUTGOING_MSG_REPLY, + BATADV_DAT_INCOMING_MSG_REPLY, +}; + +/** * struct batadv_dat_candidate - candidate destination for DAT operations * @type: the type of the selected candidate. It can one of the following: * - BATADV_DAT_CANDIDATE_NOT_FOUND
Hi,
For now is only for RFC, because there is a problem with the calculation of router and override flags (see comments in RFC 3/4).
The code is based on the patch sent 2 weeks ago (the one with the generalization).
There is no hurry with the review, because in 1 week I leave the country and it will take another 1-2 weeks to get the laptop. But, if the review is done and we need to discuss on the list (which I think it should happen for the problem above and maybe other problems too), I'll be available almost any time :) (with the exception of 3 days after my flight). Just that I will restart coding after I get the new laptop.
Thanks, Mihail
On 17 May 2013 15:27, Mihail mihail.costea2005@gmail.com wrote:
From: "mihail.costea90@gmail.com" mihail.costea90@gmail.com
Renamed snooping functions in order to suggest that they should work on more protocols than ARP.
Signed-off-by: Mihail Costea mihail.costea90@gmail.com Signed-off-by: Stefan Popa Stefan.A.Popa@intel.com Reviewed-by: Stefan Popa Stefan.A.Popa@intel.com
distributed-arp-table.c | 16 ++++++++-------- distributed-arp-table.h | 16 ++++++++-------- routing.c | 12 ++++++------ soft-interface.c | 6 +++--- 4 files changed, 25 insertions(+), 25 deletions(-)
diff --git a/distributed-arp-table.c b/distributed-arp-table.c index af670d3..b2ca7e0 100644 --- a/distributed-arp-table.c +++ b/distributed-arp-table.c @@ -978,7 +978,7 @@ out: }
/**
- batadv_dat_snoop_outgoing_arp_request - snoop the ARP request and try to
- batadv_dat_snoop_outgoing_msg_request - snoop the ARP request and try to
- answer using DAT
- @bat_priv: the bat priv with all the soft interface information
- @skb: packet to check
@@ -987,7 +987,7 @@ out:
- otherwise. In case of a positive return value the message has to be enqueued
- to permit the fallback.
*/ -bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv, +bool batadv_dat_snoop_outgoing_msg_request(struct batadv_priv *bat_priv, struct sk_buff *skb) { uint16_t type = 0; @@ -1060,7 +1060,7 @@ out: }
/**
- batadv_dat_snoop_incoming_arp_request - snoop the ARP request and try to
- batadv_dat_snoop_incoming_msg_request - snoop the ARP request and try to
- answer using the local DAT storage
- @bat_priv: the bat priv with all the soft interface information
- @skb: packet to check
@@ -1068,7 +1068,7 @@ out:
- Returns true if the request has been answered, false otherwise.
*/ -bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv, +bool batadv_dat_snoop_incoming_msg_request(struct batadv_priv *bat_priv, struct sk_buff *skb, int hdr_size) { uint16_t type; @@ -1130,11 +1130,11 @@ out: }
/**
- batadv_dat_snoop_outgoing_arp_reply - snoop the ARP reply and fill the DHT
*/
- batadv_dat_snoop_outgoing_msg_reply - snoop the ARP reply and fill the DHT
- @bat_priv: the bat priv with all the soft interface information
- @skb: packet to check
-void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv, +void batadv_dat_snoop_outgoing_msg_reply(struct batadv_priv *bat_priv, struct sk_buff *skb) { uint16_t type; @@ -1167,13 +1167,13 @@ void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv, BATADV_P_DAT_DHT_PUT); } /**
- batadv_dat_snoop_incoming_arp_reply - snoop the ARP reply and fill the local
*/
- batadv_dat_snoop_incoming_msg_reply - snoop the ARP reply and fill the local
- DAT storage only
- @bat_priv: the bat priv with all the soft interface information
- @skb: packet to check
- @hdr_size: size of the encapsulation header
-bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv, +bool batadv_dat_snoop_incoming_msg_reply(struct batadv_priv *bat_priv, struct sk_buff *skb, int hdr_size) { uint16_t type; diff --git a/distributed-arp-table.h b/distributed-arp-table.h index 557bab9..28c062b 100644 --- a/distributed-arp-table.h +++ b/distributed-arp-table.h @@ -31,13 +31,13 @@ #define BATADV_DAT_DATA_MAX_LEN 16
void batadv_dat_status_update(struct net_device *net_dev); -bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv, +bool batadv_dat_snoop_outgoing_msg_request(struct batadv_priv *bat_priv, struct sk_buff *skb); -bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv, +bool batadv_dat_snoop_incoming_msg_request(struct batadv_priv *bat_priv, struct sk_buff *skb, int hdr_size); -void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv, +void batadv_dat_snoop_outgoing_msg_reply(struct batadv_priv *bat_priv, struct sk_buff *skb); -bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv, +bool batadv_dat_snoop_incoming_msg_reply(struct batadv_priv *bat_priv, struct sk_buff *skb, int hdr_size); bool batadv_dat_drop_broadcast_packet(struct batadv_priv *bat_priv, struct batadv_forw_packet *forw_packet); @@ -105,28 +105,28 @@ static inline void batadv_dat_status_update(struct net_device *net_dev) }
static inline bool -batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv, +batadv_dat_snoop_outgoing_msg_request(struct batadv_priv *bat_priv, struct sk_buff *skb) { return false; }
static inline bool -batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv, +batadv_dat_snoop_incoming_msg_request(struct batadv_priv *bat_priv, struct sk_buff *skb, int hdr_size) { return false; }
static inline bool -batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv, +batadv_dat_snoop_outgoing_msg_reply(struct batadv_priv *bat_priv, struct sk_buff *skb) { return false; }
static inline bool -batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv, +batadv_dat_snoop_incoming_msg_reply(struct batadv_priv *bat_priv, struct sk_buff *skb, int hdr_size) { return false; diff --git a/routing.c b/routing.c index 7c372f1..1c43f55 100644 --- a/routing.c +++ b/routing.c @@ -967,10 +967,10 @@ int batadv_recv_unicast_packet(struct sk_buff *skb, orig_node = batadv_orig_hash_find(bat_priv, orig_addr); }
if (batadv_dat_snoop_incoming_arp_request(bat_priv, skb,
if (batadv_dat_snoop_incoming_msg_request(bat_priv, skb, hdr_size)) goto rx_success;
if (batadv_dat_snoop_incoming_arp_reply(bat_priv, skb,
if (batadv_dat_snoop_incoming_msg_reply(bat_priv, skb, hdr_size)) goto rx_success;
@@ -1015,10 +1015,10 @@ int batadv_recv_ucast_frag_packet(struct sk_buff *skb, if (!new_skb) return NET_RX_SUCCESS;
if (batadv_dat_snoop_incoming_arp_request(bat_priv, new_skb,
if (batadv_dat_snoop_incoming_msg_request(bat_priv, new_skb, hdr_size)) goto rx_success;
if (batadv_dat_snoop_incoming_arp_reply(bat_priv, new_skb,
if (batadv_dat_snoop_incoming_msg_reply(bat_priv, new_skb, hdr_size)) goto rx_success;
@@ -1159,9 +1159,9 @@ int batadv_recv_bcast_packet(struct sk_buff *skb, if (batadv_bla_is_backbone_gw(skb, orig_node, hdr_size)) goto out;
if (batadv_dat_snoop_incoming_arp_request(bat_priv, skb, hdr_size))
if (batadv_dat_snoop_incoming_msg_request(bat_priv, skb, hdr_size)) goto rx_success;
if (batadv_dat_snoop_incoming_arp_reply(bat_priv, skb, hdr_size))
if (batadv_dat_snoop_incoming_msg_reply(bat_priv, skb, hdr_size)) goto rx_success; /* broadcast for me */
diff --git a/soft-interface.c b/soft-interface.c index a6ab9e4..9e8fd44 100644 --- a/soft-interface.c +++ b/soft-interface.c @@ -232,7 +232,7 @@ static int batadv_interface_tx(struct sk_buff *skb, * packet, instead we first wait for DAT to try to retrieve the * correct ARP entry */
if (batadv_dat_snoop_outgoing_arp_request(bat_priv, skb))
if (batadv_dat_snoop_outgoing_msg_request(bat_priv, skb)) brd_delay = msecs_to_jiffies(ARP_REQ_DELAY); if (batadv_skb_head_push(skb, sizeof(*bcast_packet)) < 0)
@@ -271,10 +271,10 @@ static int batadv_interface_tx(struct sk_buff *skb, goto dropped; }
if (batadv_dat_snoop_outgoing_arp_request(bat_priv, skb))
if (batadv_dat_snoop_outgoing_msg_request(bat_priv, skb)) goto dropped;
batadv_dat_snoop_outgoing_arp_reply(bat_priv, skb);
batadv_dat_snoop_outgoing_msg_reply(bat_priv, skb); ret = batadv_unicast_send_skb(bat_priv, skb); if (ret != 0)
-- 1.7.10.4
On Fri, May 17, 2013 at 03:27:49PM +0300, Mihail wrote:
From: "mihail.costea90@gmail.com" mihail.costea90@gmail.com
Renamed snooping functions in order to suggest that they should work on more protocols than ARP.
You are introducing the change now, therefore I'd rather speak using simple present instead of past (at least this is what we usually do in all the commits...same applies for the subject).
Signed-off-by: Mihail Costea mihail.costea90@gmail.com Signed-off-by: Stefan Popa Stefan.A.Popa@intel.com Reviewed-by: Stefan Popa Stefan.A.Popa@intel.com
distributed-arp-table.c | 16 ++++++++-------- distributed-arp-table.h | 16 ++++++++-------- routing.c | 12 ++++++------ soft-interface.c | 6 +++--- 4 files changed, 25 insertions(+), 25 deletions(-)
diff --git a/distributed-arp-table.c b/distributed-arp-table.c index af670d3..b2ca7e0 100644 --- a/distributed-arp-table.c +++ b/distributed-arp-table.c @@ -978,7 +978,7 @@ out: }
/**
- batadv_dat_snoop_outgoing_arp_request - snoop the ARP request and try to
- batadv_dat_snoop_outgoing_msg_request - snoop the ARP request and try to
To be honest I do not really like this new naming schema..but I have no better idea now :)
Sorry for answering this late. But I gain access to a PC just now after the flight.
On 26 May 2013 06:59, Antonio Quartulli ordex@autistici.org wrote:
On Fri, May 17, 2013 at 03:27:49PM +0300, Mihail wrote:
From: "mihail.costea90@gmail.com" mihail.costea90@gmail.com
Renamed snooping functions in order to suggest that they should work on more protocols than ARP.
You are introducing the change now, therefore I'd rather speak using simple present instead of past (at least this is what we usually do in all the commits...same applies for the subject).
ACK
Signed-off-by: Mihail Costea mihail.costea90@gmail.com Signed-off-by: Stefan Popa Stefan.A.Popa@intel.com Reviewed-by: Stefan Popa Stefan.A.Popa@intel.com
distributed-arp-table.c | 16 ++++++++-------- distributed-arp-table.h | 16 ++++++++-------- routing.c | 12 ++++++------ soft-interface.c | 6 +++--- 4 files changed, 25 insertions(+), 25 deletions(-)
diff --git a/distributed-arp-table.c b/distributed-arp-table.c index af670d3..b2ca7e0 100644 --- a/distributed-arp-table.c +++ b/distributed-arp-table.c @@ -978,7 +978,7 @@ out: }
/**
- batadv_dat_snoop_outgoing_arp_request - snoop the ARP request and try to
- batadv_dat_snoop_outgoing_msg_request - snoop the ARP request and try to
To be honest I do not really like this new naming schema..but I have no better idea now :)
-- Antonio Quartulli
..each of us alone is worth nothing.. Ernesto "Che" Guevara
It could be batadv_dat_snoop_outgoing_pkt_request, with pkt from packet. That's the only other idea I have.
-- Mihail Costea
Hey Mihail,
any news on this? Do you need any input from us? If so, please ask :)
Cheers,
On 24 June 2013 00:57, Antonio Quartulli ordex@autistici.org wrote:
Hey Mihail,
any news on this? Do you need any input from us? If so, please ask :)
Cheers,
-- Antonio Quartulli
..each of us alone is worth nothing.. Ernesto "Che" Guevara
Hi Antonio,
I got my laptop a weekend ago and did the initial setup. I also started doing the initial patches.
I think by 5-6 July I should have it ready. It depends how much it will take to make those flags work.
Thanks, Mihail
b.a.t.m.a.n@lists.open-mesh.org