diff options
author | John Lo <loj@cisco.com> | 2016-08-27 01:11:57 -0400 |
---|---|---|
committer | Dave Barach <openvpp@barachs.net> | 2016-08-31 21:05:06 +0000 |
commit | 1edfba9a6394128ee5fad2b413e9e0a05972ef48 (patch) | |
tree | e1fbed7fe39b487bba72ead48020b3f25d1cbef6 /vnet/vnet/l2/l2_bd.c | |
parent | 7214cf11e9b9edbc015994cb7f9f5828e02d3791 (diff) |
VPP-358: Add IPv6 ND Event Notification and Termination
Add IPv6 equivalent of IPv4 ARP event notification which covers address
resolution for L3 and MAC/IP binding in L2 BD and ARP termination in BD.
For IPv6, ICMP6 neighbor solicitation and advertisement packets are
utilized instead of ARP request and response packets for IPv4.
Change-Id: I0088fa173e4480de297c8053ea2fcd0821322815
Signed-off-by: John Lo <loj@cisco.com>
Diffstat (limited to 'vnet/vnet/l2/l2_bd.c')
-rw-r--r-- | vnet/vnet/l2/l2_bd.c | 71 |
1 files changed, 53 insertions, 18 deletions
diff --git a/vnet/vnet/l2/l2_bd.c b/vnet/vnet/l2/l2_bd.c index a872453a98b..490a08f2d03 100644 --- a/vnet/vnet/l2/l2_bd.c +++ b/vnet/vnet/l2/l2_bd.c @@ -47,6 +47,8 @@ bd_validate (l2_bridge_domain_t * bd_config) bd_config->bvi_sw_if_index = ~0; bd_config->members = 0; bd_config->mac_by_ip4 = 0; + bd_config->mac_by_ip6 = hash_create_mem (0, sizeof (ip6_address_t), + sizeof (uword)); } } @@ -512,11 +514,42 @@ bd_add_del_ip_mac (u32 bd_index, ASSERT (sizeof (uword) == sizeof (u64)); /* make sure uword is 8 bytes */ - mac16[3] = 0; // Clear last 2 unsed bytes of the 8-byte MAC address + mac16[3] = 0; /* Clear last 2 unsed bytes of the 8-byte MAC address */ if (is_ip6) { - /* not yet implemented */ - return 1; + ip6_address_t *ip6_addr_key; + hash_pair_t *hp; + old_mac = (u64 *) hash_get_mem (bd_cfg->mac_by_ip6, ip_addr); + if (is_add) + { + if (old_mac == 0) + { /* new entry - allocate and craete ip6 address key */ + ip6_addr_key = clib_mem_alloc (sizeof (ip6_address_t)); + clib_memcpy (ip6_addr_key, ip_addr, sizeof (ip6_address_t)); + } + else if (*old_mac == new_mac) + { /* same mac entry already exist for ip6 address */ + return 0; + } + else + { /* updat mac for ip6 address */ + hp = hash_get_pair (bd_cfg->mac_by_ip6, ip_addr); + ip6_addr_key = (ip6_address_t *) hp->key; + } + hash_set_mem (bd_cfg->mac_by_ip6, ip6_addr_key, new_mac); + } + else + { + if (old_mac && (*old_mac == new_mac)) + { + hp = hash_get_pair (bd_cfg->mac_by_ip6, ip_addr); + ip6_addr_key = (ip6_address_t *) hp->key; + hash_unset_mem (bd_cfg->mac_by_ip6, ip_addr); + clib_mem_free (ip6_addr_key); + } + else + return 1; + } } else { @@ -524,26 +557,19 @@ bd_add_del_ip_mac (u32 bd_index, old_mac = (u64 *) hash_get (bd_cfg->mac_by_ip4, ip4_addr.as_u32); if (is_add) { - /* mac entry already exist? */ if (old_mac && (*old_mac == new_mac)) - return 0; + return 0; /* mac entry already exist */ hash_set (bd_cfg->mac_by_ip4, ip4_addr.as_u32, new_mac); } else { - /* Mac entry match? */ if (old_mac && (*old_mac == new_mac)) - { - /* clear entry */ - hash_unset (bd_cfg->mac_by_ip4, ip4_addr.as_u32); - } + hash_unset (bd_cfg->mac_by_ip4, ip4_addr.as_u32); else - { - return 1; - } + return 1; } - return 0; } + return 0; } /** @@ -610,8 +636,9 @@ bd_arp_entry (vlib_main_t * vm, { error = clib_error_return (0, "MAC %s for IP %U and MAC %U failed", is_add ? "add" : "del", - format_ip4_address, ip_addr, - format_ethernet_address, mac_addr); + is_ip6 ? + format_ip4_address : format_ip6_address, + ip_addr, format_ethernet_address, mac_addr); } done: @@ -780,17 +807,25 @@ bd_show (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) (bd_config->feature_bitmap & L2INPUT_FEAT_ARP_TERM)) { u32 ip4_addr; + ip6_address_t *ip6_addr; u64 mac_addr; vlib_cli_output (vm, - "\n IP4 to MAC table for ARP Termination"); + "\n IP4/IP6 to MAC table for ARP Termination"); /* *INDENT-OFF* */ hash_foreach (ip4_addr, mac_addr, bd_config->mac_by_ip4, ({ - vlib_cli_output (vm, "%=20U => %=20U", + vlib_cli_output (vm, "%=40U => %=20U", format_ip4_address, &ip4_addr, format_ethernet_address, &mac_addr); })); + + hash_foreach_mem (ip6_addr, mac_addr, bd_config->mac_by_ip6, + ({ + vlib_cli_output (vm, "%=40U => %=20U", + format_ip6_address, ip6_addr, + format_ethernet_address, &mac_addr); + })); /* *INDENT-ON* */ } } |