diff options
author | Neale Ranns <nranns@cisco.com> | 2016-11-22 17:07:28 +0000 |
---|---|---|
committer | Damjan Marion <dmarion.lists@gmail.com> | 2017-01-27 19:53:46 +0000 |
commit | 32e1c010b0c34fd0984f7fc45fae648a182025c5 (patch) | |
tree | 06a440bdc9dc039ad0dcf866acc9e10a6ea5e2e7 /src/vnet/ethernet | |
parent | 6f692d6e5a8ffc920a728372ef773199bc5466c0 (diff) |
IP Multicast FIB (mfib)
- IPv[46] mfib tables with support for (*,G/m), (*,G) and (S,G) exact and longest prefix match
- Replication represented via a new replicate DPO.
- RPF configuration and data-plane checking
- data-plane signals sent to listening control planes.
The functions of multicast forwarding entries differ from their unicast conterparts, so we introduce a new mfib_table_t and mfib_entry_t objects. However, we re-use the fib_path_list to resolve and build the entry's output list. the fib_path_list provides the service to construct a replicate DPO for multicast.
'make tests' is added to with two new suites; TEST=mfib, this is invocation of the CLI command 'test mfib' which deals with many path add/remove, flag set/unset scenarios, TEST=ip-mcast, data-plane forwarding tests.
Updated applications to use the new MIFB functions;
- IPv6 NS/RA.
- DHCPv6
unit tests for these are undated accordingly.
Change-Id: I49ec37b01f1b170335a5697541c8fd30e6d3a961
Signed-off-by: Neale Ranns <nranns@cisco.com>
Diffstat (limited to 'src/vnet/ethernet')
-rw-r--r-- | src/vnet/ethernet/arp.c | 84 | ||||
-rw-r--r-- | src/vnet/ethernet/ethernet.h | 2 | ||||
-rw-r--r-- | src/vnet/ethernet/interface.c | 20 |
3 files changed, 85 insertions, 21 deletions
diff --git a/src/vnet/ethernet/arp.c b/src/vnet/ethernet/arp.c index 0298541bb46..8f07fa55394 100644 --- a/src/vnet/ethernet/arp.c +++ b/src/vnet/ethernet/arp.c @@ -23,6 +23,7 @@ #include <vppinfra/mhash.h> #include <vnet/fib/ip4_fib.h> #include <vnet/adj/adj_nbr.h> +#include <vnet/adj/adj_mcast.h> #include <vnet/mpls/mpls.h> /** @@ -438,33 +439,74 @@ arp_update_adjacency (vnet_main_t * vnm, u32 sw_if_index, u32 ai) arp_int = &am->ethernet_arp_by_sw_if_index[sw_if_index]; e = arp_entry_find (arp_int, &adj->sub_type.nbr.next_hop.ip4); - if (NULL != e) - { - adj_nbr_walk_nh4 (sw_if_index, - &e->ip4_address, arp_mk_complete_walk, e); - } - else + switch (adj->lookup_next_index) { + case IP_LOOKUP_NEXT_ARP: + case IP_LOOKUP_NEXT_GLEAN: + if (NULL != e) + { + adj_nbr_walk_nh4 (sw_if_index, + &e->ip4_address, arp_mk_complete_walk, e); + } + else + { + /* + * no matching ARP entry. + * construct the rewrite required to for an ARP packet, and stick + * that in the adj's pipe to smoke. + */ + adj_nbr_update_rewrite + (ai, + ADJ_NBR_REWRITE_FLAG_INCOMPLETE, + ethernet_build_rewrite + (vnm, + sw_if_index, + VNET_LINK_ARP, + VNET_REWRITE_FOR_SW_INTERFACE_ADDRESS_BROADCAST)); + + /* + * since the FIB has added this adj for a route, it makes sense it + * may want to forward traffic sometime soon. Let's send a + * speculative ARP. just one. If we were to do periodically that + * wouldn't be bad either, but that's more code than i'm prepared to + * write at this time for relatively little reward. + */ + arp_nbr_probe (adj); + } + break; + case IP_LOOKUP_NEXT_MCAST: /* - * no matching ARP entry. - * construct the rewire required to for an ARP packet, and stick - * that in the adj's pipe to smoke. + * Construct a partial rewrite from the known ethernet mcast dest MAC */ - adj_nbr_update_rewrite (ai, - ADJ_NBR_REWRITE_FLAG_INCOMPLETE, - ethernet_build_rewrite (vnm, - sw_if_index, - VNET_LINK_ARP, - VNET_REWRITE_FOR_SW_INTERFACE_ADDRESS_BROADCAST)); + adj_mcast_update_rewrite + (ai, + ethernet_build_rewrite (vnm, + sw_if_index, + adj->ia_link, + ethernet_ip4_mcast_dst_addr ())); /* - * since the FIB has added this adj for a route, it makes sense it may - * want to forward traffic sometime soon. Let's send a speculative ARP. - * just one. If we were to do periodically that wouldn't be bad either, - * but that's more code than i'm prepared to write at this time for - * relatively little reward. + * Complete the remaining fields of the adj's rewrite to direct the + * complete of the rewrite at switch time by copying in the IP + * dst address's bytes. + * Ofset is 11 bytes from the end of the MAC header - which is three + * bytes into the desintation address. And we write 3 bytes. */ - arp_nbr_probe (adj); + adj->rewrite_header.dst_mcast_offset = 11; + adj->rewrite_header.dst_mcast_n_bytes = 3; + + break; + + case IP_LOOKUP_NEXT_DROP: + case IP_LOOKUP_NEXT_PUNT: + case IP_LOOKUP_NEXT_LOCAL: + case IP_LOOKUP_NEXT_REWRITE: + case IP_LOOKUP_NEXT_LOAD_BALANCE: + case IP_LOOKUP_NEXT_MIDCHAIN: + case IP_LOOKUP_NEXT_ICMP_ERROR: + case IP_LOOKUP_N_NEXT: + ASSERT (0); + break; } } diff --git a/src/vnet/ethernet/ethernet.h b/src/vnet/ethernet/ethernet.h index f88b0cf3c87..3acde421f78 100644 --- a/src/vnet/ethernet/ethernet.h +++ b/src/vnet/ethernet/ethernet.h @@ -547,6 +547,8 @@ void ethernet_update_adjacency (vnet_main_t * vnm, u32 sw_if_index, u32 ai); u8 *ethernet_build_rewrite (vnet_main_t * vnm, u32 sw_if_index, vnet_link_t link_type, const void *dst_address); +const u8 *ethernet_ip4_mcast_dst_addr (void); +const u8 *ethernet_ip6_mcast_dst_addr (void); extern vlib_node_registration_t ethernet_input_node; diff --git a/src/vnet/ethernet/interface.c b/src/vnet/ethernet/interface.c index 1c1f4353983..95700309499 100644 --- a/src/vnet/ethernet/interface.c +++ b/src/vnet/ethernet/interface.c @@ -51,6 +51,26 @@ * This file contains code to manage loopback interfaces. */ +const u8 * +ethernet_ip4_mcast_dst_addr (void) +{ + const static u8 ethernet_mcast_dst_mac[] = { + 0x1, 0x0, 0x5e, 0x0, 0x0, 0x0, + }; + + return (ethernet_mcast_dst_mac); +} + +const u8 * +ethernet_ip6_mcast_dst_addr (void) +{ + const static u8 ethernet_mcast_dst_mac[] = { + 0x33, 0x33, 0x00, 0x0, 0x0, 0x0, + }; + + return (ethernet_mcast_dst_mac); +} + /** * @brief build a rewrite string to use for sending packets of type 'link_type' * to 'dst_address' |