IP Multicast FIB (mfib)
[vpp.git] / src / vnet / ethernet / arp.c
index b388e77..8f07fa5 100644 (file)
@@ -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;
     }
 }
 
@@ -1043,12 +1085,25 @@ arp_input (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
          src_flags = fib_entry_get_flags (src_fei);
 
          if (!((FIB_ENTRY_FLAG_ATTACHED & src_flags) ||
-               (FIB_ENTRY_FLAG_CONNECTED & src_flags)) ||
-             sw_if_index0 != fib_entry_get_resolving_interface (src_fei))
+               (FIB_ENTRY_FLAG_CONNECTED & src_flags)))
            {
+             /*
+              * The packet was sent from an address that is not connected nor attached
+              * i.e. it is not from an address that is covered by a link's sub-net,
+              * nor is it a already learned host resp.
+              */
              error0 = ETHERNET_ARP_ERROR_l3_src_address_not_local;
              goto drop2;
            }
+         if (sw_if_index0 != fib_entry_get_resolving_interface (src_fei))
+           {
+             /*
+              * The interface the ARP was received on is not the interface
+              * on which the covering prefix is configured. Maybe this is a case
+              * for unnumbered.
+              */
+             is_unnum0 = 1;
+           }
 
          /* Reject requests/replies with our local interface address. */
          if (FIB_ENTRY_FLAG_LOCAL & src_flags)