diff mbox

[2/3] ipv6: send_ipv6() has to return after doing NDP

Message ID 1460023795-27136-3-git-send-email-thuth@redhat.com
State Accepted
Headers show

Commit Message

Thomas Huth April 7, 2016, 10:09 a.m. UTC
The send_ipv6() function should return after doing NDP, since either
the queued packet got send out during handle_na() already, or it has
been stored to be sent out later (once the neighbor advertisment has
been received). If we don't return here, the code runs into the final
send_ether() here later, which then sends out the packet a second time.

Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 Note: The code flow is now similar to the arp handling in send_ipv4()

 clients/net-snk/app/netlib/icmpv6.c | 2 +-
 clients/net-snk/app/netlib/ipv6.c   | 9 +++++++--
 2 files changed, 8 insertions(+), 3 deletions(-)

Comments

Nikunj A Dadhania April 11, 2016, 5:57 a.m. UTC | #1
Thomas Huth <thuth@redhat.com> writes:

> The send_ipv6() function should return after doing NDP, since either
> the queued packet got send out during handle_na() already, or it has
> been stored to be sent out later (once the neighbor advertisment has
> been received). If we don't return here, the code runs into the final
> send_ether() here later, which then sends out the packet a second time.
>
> Signed-off-by: Thomas Huth <thuth@redhat.com>

Nice catch

Reviewed-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>

Some observation regarding receive_ether(), although not related to
this patch.

> ---
>  Note: The code flow is now similar to the arp handling in send_ipv4()
>
>  clients/net-snk/app/netlib/icmpv6.c | 2 +-
>  clients/net-snk/app/netlib/ipv6.c   | 9 +++++++--
>  2 files changed, 8 insertions(+), 3 deletions(-)
>
> diff --git a/clients/net-snk/app/netlib/icmpv6.c b/clients/net-snk/app/netlib/icmpv6.c
> index c104f70..ad3f994 100644
> --- a/clients/net-snk/app/netlib/icmpv6.c
> +++ b/clients/net-snk/app/netlib/icmpv6.c
> @@ -336,7 +336,7 @@ handle_na (int fd, uint8_t *packet)
>  			return 0;
>  	} else {
>  		memcpy (&(n->mac), &(headers.ethh->src_mac[0]), 6);
> -
> +		n->status = NB_REACHABLE;
>  		if (n->eth_len > 0) {
>  			struct ethhdr * ethh = (struct ethhdr *) &(n->eth_frame);
>  			memcpy(ethh->dest_mac, &(n->mac), 6);
> diff --git a/clients/net-snk/app/netlib/ipv6.c b/clients/net-snk/app/netlib/ipv6.c
> index 5a307ca..00912ca 100644
> --- a/clients/net-snk/app/netlib/ipv6.c
> +++ b/clients/net-snk/app/netlib/ipv6.c
> @@ -478,8 +478,10 @@ static unsigned short ip6_checksum(struct ip6hdr *ip6h, unsigned short *packet,
>   * @param fd          socket fd
>   * @param ip6_packet  Pointer to IPv6 header in packet
>   * @param packetsize  Size of IPv6 packet
> - * @return -1 == ERRROR
> - *	   return of handle_udp() or handle_icmp6()
> + * @return -1 : Some error occured
> + *          0 : packet stored (NDP request sent - packet will be sent if
> + *                             NDP response is received)
> + *         >0 : packet sent   (number of transmitted bytes is returned)
>   *
>   * @see receive_ether
>   * @see ip6hdr
> @@ -562,7 +564,10 @@ int send_ipv6(int fd, void* buffer, int len)
>  				set_timer(TICKS_SEC);
>  				do {
>  					receive_ether(fd);

We need to handle return by receive_ether() as well. Unfortunately, all
calls to receive_ether() ignores the return. :(

clients/net-snk/app/netapps/ping.c:187:         receive_ether(fd_device);
clients/net-snk/app/netlib/dhcp.c:254:                  receive_ether(fd);
clients/net-snk/app/netlib/dhcpv6.c:99:                 receive_ether(fd);
clients/net-snk/app/netlib/dns.c:182:                   receive_ether(fd);
clients/net-snk/app/netlib/ipv4.c:502:                  receive_ether(fd);
clients/net-snk/app/netlib/ipv6.c:371:                  receive_ether(fd);
clients/net-snk/app/netlib/ipv6.c:544:                                  receive_ether(fd);
clients/net-snk/app/netlib/tftp.c:555:          receive_ether(fn_ip->fd);

> +					if (n->status == NB_REACHABLE)
> +						return len;
>  				} while (get_timer() > 0);
> +				return 0;
>  			}
>  		}
>  	}
> -- 
> 1.8.3.1
diff mbox

Patch

diff --git a/clients/net-snk/app/netlib/icmpv6.c b/clients/net-snk/app/netlib/icmpv6.c
index c104f70..ad3f994 100644
--- a/clients/net-snk/app/netlib/icmpv6.c
+++ b/clients/net-snk/app/netlib/icmpv6.c
@@ -336,7 +336,7 @@  handle_na (int fd, uint8_t *packet)
 			return 0;
 	} else {
 		memcpy (&(n->mac), &(headers.ethh->src_mac[0]), 6);
-
+		n->status = NB_REACHABLE;
 		if (n->eth_len > 0) {
 			struct ethhdr * ethh = (struct ethhdr *) &(n->eth_frame);
 			memcpy(ethh->dest_mac, &(n->mac), 6);
diff --git a/clients/net-snk/app/netlib/ipv6.c b/clients/net-snk/app/netlib/ipv6.c
index 5a307ca..00912ca 100644
--- a/clients/net-snk/app/netlib/ipv6.c
+++ b/clients/net-snk/app/netlib/ipv6.c
@@ -478,8 +478,10 @@  static unsigned short ip6_checksum(struct ip6hdr *ip6h, unsigned short *packet,
  * @param fd          socket fd
  * @param ip6_packet  Pointer to IPv6 header in packet
  * @param packetsize  Size of IPv6 packet
- * @return -1 == ERRROR
- *	   return of handle_udp() or handle_icmp6()
+ * @return -1 : Some error occured
+ *          0 : packet stored (NDP request sent - packet will be sent if
+ *                             NDP response is received)
+ *         >0 : packet sent   (number of transmitted bytes is returned)
  *
  * @see receive_ether
  * @see ip6hdr
@@ -562,7 +564,10 @@  int send_ipv6(int fd, void* buffer, int len)
 				set_timer(TICKS_SEC);
 				do {
 					receive_ether(fd);
+					if (n->status == NB_REACHABLE)
+						return len;
 				} while (get_timer() > 0);
+				return 0;
 			}
 		}
 	}