Mcast rewrite no memcpy 53/5753/3
authorNeale Ranns <nranns@cisco.com>
Wed, 15 Mar 2017 11:22:25 +0000 (04:22 -0700)
committerFlorin Coras <florin.coras@gmail.com>
Mon, 27 Mar 2017 17:45:06 +0000 (17:45 +0000)
use a 32bit mask in the adjacency to AND with the IP address and OR into the rewrite.

Change-Id: I80b0f246c18fd74f3e43c5d49e25833412f34665
Signed-off-by: Neale Ranns <nranns@cisco.com>
17 files changed:
src/vnet.am
src/vnet/adj/adj.c
src/vnet/adj/adj_mcast.c
src/vnet/adj/adj_mcast.h
src/vnet/ethernet/arp.c
src/vnet/hdlc/hdlc.h
src/vnet/ip/ip4_forward.c
src/vnet/ip/ip6_forward.c
src/vnet/ip/ip6_neighbor.c
src/vnet/ip/lookup.h
src/vnet/llc/llc.h
src/vnet/osi/osi.h
src/vnet/ppp/ppp.h
src/vnet/rewrite.h
src/vnet/snap/snap.h
src/vnet/vnet.h
test/test_ip_mcast.py

index 9e099f3..3e73de8 100644 (file)
@@ -42,7 +42,7 @@ libvnet_la_SOURCES +=                         \
   vnet/interface_format.c                      \
   vnet/interface_output.c                      \
   vnet/misc.c                                  \
-  vnet/replication.c                           \
+  vnet/replication.c                            \
   vnet/rewrite.c
 
 nobase_include_HEADERS +=                      \
@@ -58,7 +58,6 @@ nobase_include_HEADERS +=                     \
   vnet/l3_types.h                              \
   vnet/pipeline.h                              \
   vnet/replication.h                           \
-  vnet/rewrite.h                               \
   vnet/vnet.h                                  \
   vnet/vnet_all_api_h.h                                \
   vnet/vnet_msg_enum.h                         \
index f3d483a..9a01e89 100644 (file)
@@ -360,7 +360,7 @@ adj_get_sw_if_index (adj_index_t ai)
 }
 
 /**
- * @brief Return the link type of the adjacency
+ * @brief Return the rewrite string of the adjacency
  */
 const u8*
 adj_get_rewrite (adj_index_t ai)
index a3ba4d6..4f678e4 100644 (file)
@@ -100,7 +100,9 @@ adj_mcast_add_or_lock (fib_protocol_t proto,
  */
 void
 adj_mcast_update_rewrite (adj_index_t adj_index,
-                          u8 *rewrite)
+                          u8 *rewrite,
+                          u8 offset,
+                          u32 mask)
 {
     ip_adjacency_t *adj;
 
@@ -118,6 +120,13 @@ adj_mcast_update_rewrite (adj_index_t adj_index,
                                         vnet_get_main(),
                                         adj->rewrite_header.sw_if_index),
                                     rewrite);
+    /*
+     * set the fields corresponding to the mcast IP address rewrite
+     * The mask must be stored in network byte order, since the packet's
+     * IP address will also be in network order.
+     */
+    adj->rewrite_header.dst_mcast_offset = offset;
+    adj->rewrite_header.dst_mcast_mask = clib_host_to_net_u32(mask);
 }
 
 void
index 21c5a14..40d4431 100644 (file)
@@ -55,9 +55,18 @@ extern adj_index_t adj_mcast_add_or_lock(fib_protocol_t proto,
  *
  * @param
  *  The new rewrite
+ *
+ * @param
+ *  The offset in the rewrite a which to write in packet's
+ *  IP Address
+ *
+ * @param
+ *  The mask to apply to the packet berfore the rewrite.
  */
 extern void adj_mcast_update_rewrite(adj_index_t adj_index,
-                                     u8 *rewrite);
+                                     u8 *rewrite,
+                                     u8 offset,
+                                     u32 mask);
 
 /**
  * @brief Format/display a mcast adjacency.
index 75c7e20..2f81da3 100644 (file)
@@ -479,28 +479,30 @@ arp_update_adjacency (vnet_main_t * vnm, u32 sw_if_index, u32 ai)
        }
       break;
     case IP_LOOKUP_NEXT_MCAST:
-      /*
-       * Construct a partial rewrite from the known ethernet mcast dest MAC
-       */
-      adj_mcast_update_rewrite
-       (ai,
-        ethernet_build_rewrite (vnm,
-                                sw_if_index,
-                                adj->ia_link,
-                                ethernet_ip4_mcast_dst_addr ()));
-
-      /*
-       * 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.
-       */
-      adj->rewrite_header.dst_mcast_offset = 11;
-      adj->rewrite_header.dst_mcast_n_bytes = 3;
-
-      break;
+      {
+       /*
+        * Construct a partial rewrite from the known ethernet mcast dest MAC
+        */
+       u8 *rewrite;
+       u8 offset;
+
+       rewrite = ethernet_build_rewrite (vnm,
+                                         sw_if_index,
+                                         adj->ia_link,
+                                         ethernet_ip4_mcast_dst_addr ());
+       offset = vec_len (rewrite) - 2;
+
+       /*
+        * 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 MAC desintation address. And we copy 23 bits
+        * from the address.
+        */
+       adj_mcast_update_rewrite (ai, rewrite, offset, 0x007fffff);
 
+       break;
+      }
     case IP_LOOKUP_NEXT_DROP:
     case IP_LOOKUP_NEXT_PUNT:
     case IP_LOOKUP_NEXT_LOCAL:
index 73b15c2..8407d39 100644 (file)
@@ -91,10 +91,6 @@ hdlc_register_input_type (vlib_main_t * vm,
                         hdlc_protocol_t protocol,
                         u32 node_index);
 
-void hdlc_set_adjacency (vnet_rewrite_header_t * rw,
-                       uword max_data_bytes,
-                       hdlc_protocol_t protocol);
-
 format_function_t format_hdlc_protocol;
 format_function_t format_hdlc_header;
 format_function_t format_hdlc_header_with_length;
index 7352c2e..f2bc2a7 100644 (file)
@@ -2553,8 +2553,8 @@ ip4_rewrite_inline (vlib_main_t * vm,
              /*
               * copy bytes from the IP address into the MAC rewrite
               */
-             vnet_fixup_one_header (adj0[0], &ip0->dst_address, ip0, 1);
-             vnet_fixup_one_header (adj1[0], &ip1->dst_address, ip1, 1);
+             vnet_fixup_one_header (adj0[0], &ip0->dst_address, ip0);
+             vnet_fixup_one_header (adj1[0], &ip1->dst_address, ip1);
            }
 
          vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
@@ -2635,7 +2635,7 @@ ip4_rewrite_inline (vlib_main_t * vm,
              /*
               * copy bytes from the IP address into the MAC rewrite
               */
-             vnet_fixup_one_header (adj0[0], &ip0->dst_address, ip0, 1);
+             vnet_fixup_one_header (adj0[0], &ip0->dst_address, ip0);
            }
 
          /* Update packet buffer attributes/set output interface. */
index 0b8691b..ecc3bd2 100644 (file)
@@ -2087,8 +2087,8 @@ ip6_rewrite_inline (vlib_main_t * vm,
              /*
               * copy bytes from the IP address into the MAC rewrite
               */
-             vnet_fixup_one_header (adj0[0], &ip0->dst_address, ip0, 0);
-             vnet_fixup_one_header (adj1[0], &ip1->dst_address, ip1, 0);
+             vnet_fixup_one_header (adj0[0], &ip0->dst_address, ip0);
+             vnet_fixup_one_header (adj1[0], &ip1->dst_address, ip1);
            }
 
          vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
@@ -2197,7 +2197,7 @@ ip6_rewrite_inline (vlib_main_t * vm,
            }
          if (is_mcast)
            {
-             vnet_fixup_one_header (adj0[0], &ip0->dst_address, ip0, 0);
+             vnet_fixup_one_header (adj0[0], &ip0->dst_address, ip0);
            }
 
          p0->error = error_node->errors[error0];
index 8d355ab..9b61663 100644 (file)
@@ -530,28 +530,29 @@ ip6_ethernet_update_adjacency (vnet_main_t * vnm, u32 sw_if_index, u32 ai)
        }
       break;
     case IP_LOOKUP_NEXT_MCAST:
-      /*
-       * Construct a partial rewrite from the known ethernet mcast dest MAC
-       */
-      adj_mcast_update_rewrite
-       (ai,
-        ethernet_build_rewrite (vnm,
-                                sw_if_index,
-                                adj->ia_link,
-                                ethernet_ip6_mcast_dst_addr ()));
-
-      /*
-       * 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 12 bytes from the end of the MAC header - which is 2
-       * bytes into the desintation address. And we write 4 bytes.
-       */
-      adj->rewrite_header.dst_mcast_offset = 12;
-      adj->rewrite_header.dst_mcast_n_bytes = 4;
-
-      break;
+      {
+       /*
+        * Construct a partial rewrite from the known ethernet mcast dest MAC
+        */
+       u8 *rewrite;
+       u8 offset;
+
+       rewrite = ethernet_build_rewrite (vnm,
+                                         sw_if_index,
+                                         adj->ia_link,
+                                         ethernet_ip6_mcast_dst_addr ());
+
+       /*
+        * 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.
+        */
+       offset = vec_len (rewrite) - 2;
+       adj_mcast_update_rewrite (ai, rewrite, offset, 0xffffffff);
 
+       break;
+      }
     case IP_LOOKUP_NEXT_DROP:
     case IP_LOOKUP_NEXT_PUNT:
     case IP_LOOKUP_NEXT_LOCAL:
index 48360b5..f76ddb3 100644 (file)
@@ -55,6 +55,7 @@
 #include <vnet/fib/fib_node.h>
 #include <vnet/dpo/dpo.h>
 #include <vnet/feature/feature.h>
+#include <vnet/rewrite.h>
 
 /** @brief Common (IP4/IP6) next index stored in adjacency. */
 typedef enum
index 0b85f5d..990a581 100644 (file)
@@ -158,9 +158,6 @@ void
 llc_register_input_protocol (vlib_main_t * vm,
                             llc_protocol_t protocol, u32 node_index);
 
-void llc_set_adjacency (vnet_rewrite_header_t * rw,
-                       uword max_data_bytes, llc_protocol_t protocol);
-
 format_function_t format_llc_protocol;
 format_function_t format_llc_header;
 format_function_t format_llc_header_with_length;
index ee21f0c..0ff267a 100644 (file)
@@ -131,9 +131,6 @@ extern osi_main_t osi_main;
 /* Register given node index to take input for given osi type. */
 void osi_register_input_protocol (osi_protocol_t protocol, u32 node_index);
 
-void osi_set_adjacency (vnet_rewrite_header_t * rw,
-                       uword max_data_bytes, osi_protocol_t protocol);
-
 format_function_t format_osi_protocol;
 format_function_t format_osi_header;
 format_function_t format_osi_header_with_length;
index fdc205b..726eca6 100644 (file)
@@ -93,9 +93,6 @@ void
 ppp_register_input_type (vlib_main_t * vm,
                         ppp_protocol_t protocol, u32 node_index);
 
-void ppp_set_adjacency (vnet_rewrite_header_t * rw,
-                       uword max_data_bytes, ppp_protocol_t protocol);
-
 format_function_t format_ppp_protocol;
 format_function_t format_ppp_header;
 format_function_t format_ppp_header_with_length;
index 8435a72..1dea72f 100644 (file)
@@ -72,20 +72,18 @@ typedef CLIB_PACKED (struct {
      Used for MTU check after packet rewrite. */
   u16 max_l3_packet_bytes;
 
-  u16 unused1;
-  u8  unused2;
-
+  /* Data-plane flags on the adjacency/rewrite */
   vnet_rewrite_flags_t flags;
 
   /* When dynamically writing a multicast destination L2 addresss
-   * this is the offset within the address to start writing n
-   * bytes of the IP mcast address */
+   * this is the offset from the IP address at which to write in the
+   * IP->MAC address translation.
+   */
   u8 dst_mcast_offset;
 
-  /* When dynamically writing a multicast destination L2 addresss
-   * this is the number of bytes of the dest IP address to write into
-   * the MAC rewrite */
-  u8 dst_mcast_n_bytes;
+  /* The mask to apply to the lower 4 bytes of the IP address before ORing
+   * into the destinaiton MAC address */
+  u32 dst_mcast_mask;
 
   /* Rewrite string starting at end and going backwards. */
   u8 data[0];
@@ -293,24 +291,24 @@ _vnet_rewrite_two_headers (vnet_rewrite_header_t * h0,
 
 always_inline void
 _vnet_fixup_one_header (vnet_rewrite_header_t * h0,
-                       u8 * addr, u32 addr_len,
-                       u8 * packet0, int clear_first_bit)
+                       u8 * addr, u32 addr_len, u8 * packet0)
 {
-  /* location to write to in the packet */
-  u8 *p0 = packet0 - h0->dst_mcast_offset;
-  u8 *p1 = p0;
-  /* location to write from in the L3 dest address */
-  u8 *a0 = addr + addr_len - h0->dst_mcast_n_bytes;
-
-  clib_memcpy (p0, a0, h0->dst_mcast_n_bytes);
-  if (clear_first_bit)
-    *p1 &= 0x7f;
+  if (PREDICT_TRUE (h0->dst_mcast_mask))
+    {
+      /* location to write to in the packet */
+      u8 *p0 = packet0 - h0->dst_mcast_offset;
+      u32 *p1 = (u32 *) p0;
+      /* location to copy from in the L3 dest address */
+      u32 *a0 = (u32 *) (addr + addr_len - sizeof (h0->dst_mcast_mask));
+
+      *p1 |= (*a0 & h0->dst_mcast_mask);
+    }
 }
 
-#define vnet_fixup_one_header(rw0,addr,p0,clear_first_bit)              \
+#define vnet_fixup_one_header(rw0,addr,p0)              \
   _vnet_fixup_one_header (&((rw0).rewrite_header),                      \
                           (u8*)(addr), sizeof((*addr)),                 \
-                          (u8*)(p0), (clear_first_bit))
+                          (u8*)(p0))
 
 #define VNET_REWRITE_FOR_SW_INTERFACE_ADDRESS_BROADCAST ((void *) 0)
 /** Deprecated */
index dbba15b..7cd453e 100644 (file)
@@ -173,9 +173,6 @@ snap_register_input_protocol (vlib_main_t * vm,
                              char *name,
                              u32 ieee_oui, u16 protocol, u32 node_index);
 
-void snap_set_adjacency (vnet_rewrite_header_t * rw,
-                        uword max_data_bytes, u32 ieee_oui, u16 protocol);
-
 format_function_t format_snap_protocol;
 format_function_t format_snap_header;
 format_function_t format_snap_header_with_length;
index 5a8ae85..8405f61 100644 (file)
@@ -46,7 +46,6 @@
 #include <vnet/buffer.h>
 #include <vnet/config.h>
 #include <vnet/interface.h>
-#include <vnet/rewrite.h>
 #include <vnet/api_errno.h>
 
 typedef struct vnet_main_t
index 094942b..36d597a 100644 (file)
@@ -101,7 +101,6 @@ class TestIPMcast(VppTestCase):
                 tx = sent[i]
                 rx = capture[i]
 
-                # the rx'd packet has the MPLS label popped
                 eth = rx[Ether]
                 self.assertEqual(eth.type, 0x800)
 
@@ -128,7 +127,6 @@ class TestIPMcast(VppTestCase):
             tx = sent[i]
             rx = capture[i]
 
-            # the rx'd packet has the MPLS label popped
             eth = rx[Ether]
             self.assertEqual(eth.type, 0x86DD)