diff options
| author | Michael Brown | 2016-07-25 16:20:22 +0200 |
|---|---|---|
| committer | Michael Brown | 2016-07-25 16:20:22 +0200 |
| commit | a4c4f72297bea6902001ce813aaf432bd49d382d (patch) | |
| tree | b685b22a5472252bfa6699b2a19cd89b9073fb34 /src/include | |
| parent | [test] Update IPv6 tests to use okx() (diff) | |
| download | ipxe-a4c4f72297bea6902001ce813aaf432bd49d382d.tar.gz ipxe-a4c4f72297bea6902001ce813aaf432bd49d382d.tar.xz ipxe-a4c4f72297bea6902001ce813aaf432bd49d382d.zip | |
[ipv6] Allow for multiple routers
Select the IPv6 source address and corresponding router (if any) using
a very simplified version of the algorithm from RFC6724:
- Ignore any source address that has a smaller scope than the
destination address. For example, do not use a link-local source
address when sending to a global destination address.
- If we have a source address which is on the same link as the
destination address, then use that source address.
- If we are left with multiple possible source addresses, then choose
the address with the smallest scope. For example, if we are sending
to a site-local destination address and we have both a global source
address and a site-local source address, then use the site-local
source address.
- If we are still left with multiple possible source addresses, then
choose the address with the longest matching prefix.
For the purposes of this algorithm, we treat RFC4193 Unique Local
Addresses as having organisation-local scope. Since we use only
link-local scope for our multicast transmissions, this approximation
should remain valid in all practical situations.
Originally-implemented-by: Thomas Bächler <thomas@archlinux.org>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/include')
| -rw-r--r-- | src/include/ipxe/in.h | 8 | ||||
| -rw-r--r-- | src/include/ipxe/ipv6.h | 39 |
2 files changed, 45 insertions, 2 deletions
diff --git a/src/include/ipxe/in.h b/src/include/ipxe/in.h index 0ebf441c2..3044d6316 100644 --- a/src/include/ipxe/in.h +++ b/src/include/ipxe/in.h @@ -69,8 +69,12 @@ struct in6_addr { ( ( *( ( const uint16_t * ) (addr) ) & htons ( 0xffc0 ) ) == \ htons ( 0xfe80 ) ) -#define IN6_IS_ADDR_NONGLOBAL( addr ) \ - ( IN6_IS_ADDR_LINKLOCAL (addr) || IN6_IS_ADDR_MULTICAST (addr) ) +#define IN6_IS_ADDR_SITELOCAL( addr ) \ + ( ( *( ( const uint16_t * ) (addr) ) & htons ( 0xffc0 ) ) == \ + htons ( 0xfec0 ) ) + +#define IN6_IS_ADDR_ULA( addr ) \ + ( ( *( ( const uint8_t * ) (addr) ) & 0xfe ) == 0xfc ) /** * IPv4 socket address diff --git a/src/include/ipxe/ipv6.h b/src/include/ipxe/ipv6.h index 0e5292fba..4dd43f16d 100644 --- a/src/include/ipxe/ipv6.h +++ b/src/include/ipxe/ipv6.h @@ -158,6 +158,24 @@ struct ipv6_pseudo_header { uint8_t next_header; } __attribute__ (( packed )); +/** IPv6 address scopes */ +enum ipv6_address_scope { + /** Interface-local address scope */ + IPV6_SCOPE_INTERFACE_LOCAL = 0x1, + /** Link-local address scope */ + IPV6_SCOPE_LINK_LOCAL = 0x2, + /** Admin-local address scope */ + INV6_SCOPE_ADMIN_LOCAL = 0x4, + /** Site-local address scope */ + IPV6_SCOPE_SITE_LOCAL = 0x5, + /** Organisation-local address scope */ + IPV6_SCOPE_ORGANISATION_LOCAL = 0x8, + /** Global address scope */ + IPV6_SCOPE_GLOBAL = 0xe, + /** Maximum scope */ + IPV6_SCOPE_MAX = 0xf, +}; + /** An IPv6 address/routing table entry */ struct ipv6_miniroute { /** List of miniroutes */ @@ -174,6 +192,8 @@ struct ipv6_miniroute { struct in6_addr prefix_mask; /** Router address */ struct in6_addr router; + /** Scope */ + unsigned int scope; /** Flags */ unsigned int flags; }; @@ -244,6 +264,18 @@ static inline void ipv6_all_routers ( struct in6_addr *addr ) { addr->s6_addr[15] = 2; } +/** + * Get multicast address scope + * + * @v addr Multicast address + * @ret scope Address scope + */ +static inline unsigned int +ipv6_multicast_scope ( const struct in6_addr *addr ) { + + return ( addr->s6_addr[1] & 0x0f ); +} + /** IPv6 settings sibling order */ enum ipv6_settings_order { /** No address */ @@ -264,6 +296,13 @@ extern struct list_head ipv6_miniroutes; extern struct net_protocol ipv6_protocol __net_protocol; extern int ipv6_has_addr ( struct net_device *netdev, struct in6_addr *addr ); +extern int ipv6_add_miniroute ( struct net_device *netdev, + struct in6_addr *address, + unsigned int prefix_len, + struct in6_addr *router ); +extern void ipv6_del_miniroute ( struct ipv6_miniroute *miniroute ); +extern struct ipv6_miniroute * ipv6_route ( unsigned int scope_id, + struct in6_addr **dest ); extern int parse_ipv6_setting ( const struct setting_type *type, const char *value, void *buf, size_t len ); extern int format_ipv6_setting ( const struct setting_type *type, |
