Mcast rewrite optimisations

hard code the address mask offsets. This are protocol specific and only used on ethernet when used at all.

Change-Id: Ib1f6f33682f53254ffbb5a241a1583e65420e0c7
Signed-off-by: Neale Ranns <nranns@cisco.com>
diff --git a/src/vnet/ip/ip4_forward.c b/src/vnet/ip/ip4_forward.c
index 7c56a29..28b6203 100644
--- a/src/vnet/ip/ip4_forward.c
+++ b/src/vnet/ip/ip4_forward.c
@@ -1940,6 +1940,16 @@
   IP4_REWRITE_NEXT_ICMP_ERROR,
 } ip4_rewrite_next_t;
 
+/**
+ * This bits of an IPv4 address to mask to construct a multicast
+ * MAC address
+ */
+#if CLIB_ARCH_IS_BIG_ENDIAN
+#define IP4_MCAST_ADDR_MASK 0x007fffff
+#else
+#define IP4_MCAST_ADDR_MASK 0xffff7f00
+#endif
+
 always_inline uword
 ip4_rewrite_inline (vlib_main_t * vm,
 		    vlib_node_runtime_t * node,
@@ -2197,8 +2207,16 @@
 	      /*
 	       * copy bytes from the IP address into the MAC rewrite
 	       */
-	      vnet_fixup_one_header (adj0[0], &ip0->dst_address, ip0);
-	      vnet_fixup_one_header (adj1[0], &ip1->dst_address, ip1);
+	      vnet_ip_mcast_fixup_header (IP4_MCAST_ADDR_MASK,
+					  adj0->
+					  rewrite_header.dst_mcast_offset,
+					  &ip0->dst_address.as_u32,
+					  (u8 *) ip0);
+	      vnet_ip_mcast_fixup_header (IP4_MCAST_ADDR_MASK,
+					  adj0->
+					  rewrite_header.dst_mcast_offset,
+					  &ip1->dst_address.as_u32,
+					  (u8 *) ip1);
 	    }
 
 	  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
@@ -2277,7 +2295,11 @@
 	      /*
 	       * copy bytes from the IP address into the MAC rewrite
 	       */
-	      vnet_fixup_one_header (adj0[0], &ip0->dst_address, ip0);
+	      vnet_ip_mcast_fixup_header (IP4_MCAST_ADDR_MASK,
+					  adj0->
+					  rewrite_header.dst_mcast_offset,
+					  &ip0->dst_address.as_u32,
+					  (u8 *) ip0);
 	    }
 
 	  /* Update packet buffer attributes/set output interface. */
diff --git a/src/vnet/ip/ip6_forward.c b/src/vnet/ip/ip6_forward.c
index 588cd06..f4e45a4 100644
--- a/src/vnet/ip/ip6_forward.c
+++ b/src/vnet/ip/ip6_forward.c
@@ -1774,6 +1774,12 @@
   IP6_REWRITE_NEXT_ICMP_ERROR,
 } ip6_rewrite_next_t;
 
+/**
+ * This bits of an IPv6 address to mask to construct a multicast
+ * MAC address
+ */
+#define IP6_MCAST_ADDR_MASK 0xffffffff
+
 always_inline uword
 ip6_rewrite_inline (vlib_main_t * vm,
 		    vlib_node_runtime_t * node,
@@ -1977,8 +1983,16 @@
 	      /*
 	       * copy bytes from the IP address into the MAC rewrite
 	       */
-	      vnet_fixup_one_header (adj0[0], &ip0->dst_address, ip0);
-	      vnet_fixup_one_header (adj1[0], &ip1->dst_address, ip1);
+	      vnet_ip_mcast_fixup_header (IP6_MCAST_ADDR_MASK,
+					  adj0->
+					  rewrite_header.dst_mcast_offset,
+					  &ip0->dst_address.as_u32[3],
+					  (u8 *) ip0);
+	      vnet_ip_mcast_fixup_header (IP6_MCAST_ADDR_MASK,
+					  adj1->
+					  rewrite_header.dst_mcast_offset,
+					  &ip1->dst_address.as_u32[3],
+					  (u8 *) ip1);
 	    }
 
 	  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
@@ -2085,7 +2099,11 @@
 	    }
 	  if (is_mcast)
 	    {
-	      vnet_fixup_one_header (adj0[0], &ip0->dst_address, ip0);
+	      vnet_ip_mcast_fixup_header (IP6_MCAST_ADDR_MASK,
+					  adj0->
+					  rewrite_header.dst_mcast_offset,
+					  &ip0->dst_address.as_u32[3],
+					  (u8 *) ip0);
 	    }
 
 	  p0->error = error_node->errors[error0];
diff --git a/src/vnet/ip/ip6_neighbor.c b/src/vnet/ip/ip6_neighbor.c
index fee4356..8e44402 100644
--- a/src/vnet/ip/ip6_neighbor.c
+++ b/src/vnet/ip/ip6_neighbor.c
@@ -672,10 +672,10 @@
 	 * 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 2 bytes into the desintation address. And we write 4 bytes.
+	 * Ofset is 2 bytes into the desintation address.
 	 */
 	offset = vec_len (rewrite) - 2;
-	adj_mcast_update_rewrite (ai, rewrite, offset, 0xffffffff);
+	adj_mcast_update_rewrite (ai, rewrite, offset);
 
 	break;
       }