diff mbox

ipv6: Add support for sending packets through a router

Message ID 1460014339-19048-1-git-send-email-thuth@redhat.com
State Accepted
Headers show

Commit Message

Thomas Huth April 7, 2016, 7:32 a.m. UTC
The network boot over IPv6 currently fails if the TFTP server
is not in the same subnet as the SLOF client. In that case we
have to fill in the MAC address of a router into our packets
to get them to the right place.

Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 clients/net-snk/app/netlib/ipv6.c | 23 +++++++++++++++++++++++
 clients/net-snk/app/netlib/ndp.c  | 17 +++++++++++++++++
 clients/net-snk/app/netlib/ndp.h  |  1 +
 3 files changed, 41 insertions(+)

Comments

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

> The network boot over IPv6 currently fails if the TFTP server
> is not in the same subnet as the SLOF client. In that case we
> have to fill in the MAC address of a router into our packets
> to get them to the right place.
>
> Signed-off-by: Thomas Huth <thuth@redhat.com>

Looks good, one small nit below.

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

> ---
>  clients/net-snk/app/netlib/ipv6.c | 23 +++++++++++++++++++++++
>  clients/net-snk/app/netlib/ndp.c  | 17 +++++++++++++++++
>  clients/net-snk/app/netlib/ndp.h  |  1 +
>  3 files changed, 41 insertions(+)
>
> diff --git a/clients/net-snk/app/netlib/ipv6.c b/clients/net-snk/app/netlib/ipv6.c
> index 62d29ea..348e79d 100644
> --- a/clients/net-snk/app/netlib/ipv6.c
> +++ b/clients/net-snk/app/netlib/ipv6.c
> @@ -13,6 +13,7 @@
>  #include <string.h>
>  #include <stdlib.h>
>  #include <stdio.h>
> +#include <stdbool.h>
>  #include <time.h>
>  #include <ctype.h>
>  #include <sys/socket.h>
> @@ -417,6 +418,21 @@ static uint8_t *ip6_to_multicast_mac(ip6_addr_t * ip, uint8_t *mc_mac)
>  }
>
>  /**
> + * Check whether an IPv6 address is on the same network as we are
> + */
> +static bool is_ip6addr_in_my_net(ip6_addr_t *ip)
> +{
> +	struct ip6addr_list_entry *n = NULL;
> +
> +	for (n = first_ip6; n != NULL; n = n->next) {
> +		if (n->addr.part.prefix == ip->part.prefix)
> +			return true;  /* IPv6 address is in our neighborhood */
> +	}
> +
> +	return false;    /* not in our neighborhood */
> +}
> +
> +/**
>   * NET: calculate checksum over IPv6 header and upper-layer protocol
>   *      (e.g. UDP or ICMPv6)
>   *
> @@ -517,6 +533,10 @@ int send_ipv6(int fd, void* buffer, int len)
>  		if (n) {
>  			if (memcmp(n->mac, null_mac, ETH_ALEN) != 0)
>  				memcpy (mac_addr, &(n->mac), ETH_ALEN); /* found it */
> +		} else if (!is_ip6addr_in_my_net(&ip_dst)) {
> +			struct router *gw;
> +			gw = ipv6_get_default_router(&ip6h->src);
> +			mac_addr = gw ? gw->mac : null_mac;
>  		} else {
>  			mac_addr = null_mac;
>  			n = malloc(sizeof(struct neighbor));
> @@ -547,6 +567,9 @@ int send_ipv6(int fd, void* buffer, int len)
>  		}
>  	}
>
> +	if (mac_addr == null_mac)
> +		return -1;
> +
>  	fill_ethhdr (n->eth_frame, htons(ETHERTYPE_IPv6), get_mac_address(),
>  		     mac_addr);
>  	memcpy (&(n->eth_frame[sizeof(struct ethhdr)]), buffer, len);
> diff --git a/clients/net-snk/app/netlib/ndp.c b/clients/net-snk/app/netlib/ndp.c
> index 96faa87..7a8dfda 100644
> --- a/clients/net-snk/app/netlib/ndp.c
> +++ b/clients/net-snk/app/netlib/ndp.c
> @@ -84,6 +84,23 @@ find_router( ip6_addr_t *ip )
>  	return NULL; /* router is unknown */
>  }
>
> +/**
> + * Find a router for a given host address
> + * @param  ip - IPv6 address with the prefered prefix
> + * @return pointer to router, or NULL if none is available
> + */
> +struct router *ipv6_get_default_router(ip6_addr_t *ip)

Did you think of returning mac-address directly?

ipv6_get_default_router_mac() ?

> +{
> +	struct router *n = NULL;
> +
> +	for (n = first_router; n != NULL; n = n->next) {
> +		if (n->ip.part.prefix == ip->part.prefix)
> +			return n;
> +	}
> +
> +	return first_router;
> +}
> +
>  /*
>   * NET: add new neighbor to list
>   * @param  struct neighbor nghb  - new neighbor
> diff --git a/clients/net-snk/app/netlib/ndp.h b/clients/net-snk/app/netlib/ndp.h
> index c785c48..74fbd8b 100644
> --- a/clients/net-snk/app/netlib/ndp.h
> +++ b/clients/net-snk/app/netlib/ndp.h
> @@ -67,5 +67,6 @@ struct neighbor * find_neighbor (ip6_addr_t *);
>  int8_t router_add(struct router*);
>  void * router_create(uint8_t *mac, ip6_addr_t *ip);
>  struct router * find_router(ip6_addr_t *);
> +struct router *ipv6_get_default_router(ip6_addr_t *ip);
>
>  #endif //_NDP_H_
> -- 
> 1.8.3.1
Thomas Huth April 11, 2016, 8:01 a.m. UTC | #2
On 11.04.2016 06:51, Nikunj A Dadhania wrote:
> Thomas Huth <thuth@redhat.com> writes:
> 
>> The network boot over IPv6 currently fails if the TFTP server
>> is not in the same subnet as the SLOF client. In that case we
>> have to fill in the MAC address of a router into our packets
>> to get them to the right place.
>>
>> Signed-off-by: Thomas Huth <thuth@redhat.com>
> 
> Looks good, one small nit below.
> 
> Reviewed-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>

Thanks for the review!

>> +/**
>> + * Find a router for a given host address
>> + * @param  ip - IPv6 address with the prefered prefix
>> + * @return pointer to router, or NULL if none is available
>> + */
>> +struct router *ipv6_get_default_router(ip6_addr_t *ip)
> 
> Did you think of returning mac-address directly?
> 
> ipv6_get_default_router_mac() ?

That's maybe a tiny little bit easier for this case, but I think if we
ever need any information from the "struct router" of the default router
again in another part of the code, it's better to have a function like
this (i.e. returning the whole structure). So I'd prefer to keep the
code this way.

 Thomas
diff mbox

Patch

diff --git a/clients/net-snk/app/netlib/ipv6.c b/clients/net-snk/app/netlib/ipv6.c
index 62d29ea..348e79d 100644
--- a/clients/net-snk/app/netlib/ipv6.c
+++ b/clients/net-snk/app/netlib/ipv6.c
@@ -13,6 +13,7 @@ 
 #include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <stdbool.h>
 #include <time.h>
 #include <ctype.h>
 #include <sys/socket.h>
@@ -417,6 +418,21 @@  static uint8_t *ip6_to_multicast_mac(ip6_addr_t * ip, uint8_t *mc_mac)
 }
 
 /**
+ * Check whether an IPv6 address is on the same network as we are
+ */
+static bool is_ip6addr_in_my_net(ip6_addr_t *ip)
+{
+	struct ip6addr_list_entry *n = NULL;
+
+	for (n = first_ip6; n != NULL; n = n->next) {
+		if (n->addr.part.prefix == ip->part.prefix)
+			return true;  /* IPv6 address is in our neighborhood */
+	}
+
+	return false;    /* not in our neighborhood */
+}
+
+/**
  * NET: calculate checksum over IPv6 header and upper-layer protocol
  *      (e.g. UDP or ICMPv6)
  *
@@ -517,6 +533,10 @@  int send_ipv6(int fd, void* buffer, int len)
 		if (n) {
 			if (memcmp(n->mac, null_mac, ETH_ALEN) != 0)
 				memcpy (mac_addr, &(n->mac), ETH_ALEN); /* found it */
+		} else if (!is_ip6addr_in_my_net(&ip_dst)) {
+			struct router *gw;
+			gw = ipv6_get_default_router(&ip6h->src);
+			mac_addr = gw ? gw->mac : null_mac;
 		} else {
 			mac_addr = null_mac;
 			n = malloc(sizeof(struct neighbor));
@@ -547,6 +567,9 @@  int send_ipv6(int fd, void* buffer, int len)
 		}
 	}
 
+	if (mac_addr == null_mac)
+		return -1;
+
 	fill_ethhdr (n->eth_frame, htons(ETHERTYPE_IPv6), get_mac_address(),
 		     mac_addr);
 	memcpy (&(n->eth_frame[sizeof(struct ethhdr)]), buffer, len);
diff --git a/clients/net-snk/app/netlib/ndp.c b/clients/net-snk/app/netlib/ndp.c
index 96faa87..7a8dfda 100644
--- a/clients/net-snk/app/netlib/ndp.c
+++ b/clients/net-snk/app/netlib/ndp.c
@@ -84,6 +84,23 @@  find_router( ip6_addr_t *ip )
 	return NULL; /* router is unknown */
 }
 
+/**
+ * Find a router for a given host address
+ * @param  ip - IPv6 address with the prefered prefix
+ * @return pointer to router, or NULL if none is available
+ */
+struct router *ipv6_get_default_router(ip6_addr_t *ip)
+{
+	struct router *n = NULL;
+
+	for (n = first_router; n != NULL; n = n->next) {
+		if (n->ip.part.prefix == ip->part.prefix)
+			return n;
+	}
+
+	return first_router;
+}
+
 /*
  * NET: add new neighbor to list
  * @param  struct neighbor nghb  - new neighbor
diff --git a/clients/net-snk/app/netlib/ndp.h b/clients/net-snk/app/netlib/ndp.h
index c785c48..74fbd8b 100644
--- a/clients/net-snk/app/netlib/ndp.h
+++ b/clients/net-snk/app/netlib/ndp.h
@@ -67,5 +67,6 @@  struct neighbor * find_neighbor (ip6_addr_t *);
 int8_t router_add(struct router*);
 void * router_create(uint8_t *mac, ip6_addr_t *ip);
 struct router * find_router(ip6_addr_t *);
+struct router *ipv6_get_default_router(ip6_addr_t *ip);
 
 #endif //_NDP_H_