sr: SRv6 FlowLabel Added
[vpp.git] / src / vnet / srv6 / sr_policy_rewrite.c
old mode 100755 (executable)
new mode 100644 (file)
index 9c4d0ec..c7ac44b
@@ -41,9 +41,9 @@
 #include <vlib/vlib.h>
 #include <vnet/vnet.h>
 #include <vnet/srv6/sr.h>
-#include <vnet/ip/ip.h>
+#include <vnet/ip/ip4_inlines.h>
+#include <vnet/ip/ip6_inlines.h>
 #include <vnet/srv6/sr_packet.h>
-#include <vnet/ip/ip6_packet.h>
 #include <vnet/fib/ip6_fib.h>
 #include <vnet/dpo/dpo.h>
 #include <vnet/dpo/replicate_dpo.h>
@@ -119,6 +119,12 @@ sr_set_source (ip6_address_t * address)
   clib_memcpy_fast (&sr_pr_encaps_src, address, sizeof (sr_pr_encaps_src));
 }
 
+ip6_address_t *
+sr_get_encaps_source ()
+{
+  return &sr_pr_encaps_src;
+}
+
 static clib_error_t *
 set_sr_src_command_fn (vlib_main_t * vm, unformat_input_t * input,
                       vlib_cli_command_t * cmd)
@@ -973,10 +979,10 @@ sr_policy_command_fn (vlib_main_t * vm, unformat_input_t * input,
          sr_policy_fn_registration_t **plugin_it = 0;
 
          /* *INDENT-OFF* */
-         pool_foreach (plugin, sm->policy_plugin_functions,
+         pool_foreach (plugin, sm->policy_plugin_functions)
            {
              vec_add1 (vec_plugins, plugin);
-           });
+           }
          /* *INDENT-ON* */
 
          vec_foreach (plugin_it, vec_plugins)
@@ -1115,8 +1121,8 @@ show_sr_policies_command_fn (vlib_main_t * vm, unformat_input_t * input,
   vlib_cli_output (vm, "SR policies:");
 
   /* *INDENT-OFF* */
-  pool_foreach  (sr_policy, sm->sr_policies,
-                {vec_add1 (vec_policies, sr_policy); } );
+  pool_foreach (sr_policy, sm->sr_policies)
+                {vec_add1 (vec_policies, sr_policy); }
   /* *INDENT-ON* */
 
   vec_foreach_index (i, vec_policies)
@@ -1147,7 +1153,7 @@ show_sr_policies_command_fn (vlib_main_t * vm, unformat_input_t * input,
       }
       s = format (s, "\b\b > ");
       s = format (s, "weight: %u", segment_list->weight);
-      vlib_cli_output (vm, "  %s", s);
+      vlib_cli_output (vm, "  %v", s);
     }
     vlib_cli_output (vm, "-----------");
   }
@@ -1162,6 +1168,48 @@ VLIB_CLI_COMMAND (show_sr_policies_command, static) = {
 };
 /* *INDENT-ON* */
 
+/**
+ * @brief CLI to display onscreen the SR encaps source addr
+ */
+static clib_error_t *
+show_sr_encaps_source_command_fn (vlib_main_t * vm, unformat_input_t * input,
+                                 vlib_cli_command_t * cmd)
+{
+  vlib_cli_output (vm, "SR encaps source addr = %U", format_ip6_address,
+                  sr_get_encaps_source ());
+
+  return 0;
+}
+
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (show_sr_encaps_source_command, static) = {
+  .path = "show sr encaps source addr",
+  .short_help = "show sr encaps source addr",
+  .function = show_sr_encaps_source_command_fn,
+};
+/* *INDENT-ON* */
+
+/**
+ * @brief CLI to display onscreen the hop-limit value used for SRv6 encapsulation
+ */
+static clib_error_t *
+show_sr_encaps_hop_limit_command_fn (vlib_main_t * vm,
+                                    unformat_input_t * input,
+                                    vlib_cli_command_t * cmd)
+{
+  vlib_cli_output (vm, "SR encaps hop-limit = %u", sr_get_hop_limit ());
+
+  return 0;
+}
+
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (show_sr_encaps_hop_limit_command, static) = {
+  .path = "show sr encaps hop-limit",
+  .short_help = "show sr encaps hop-limit",
+  .function = show_sr_encaps_hop_limit_command_fn,
+};
+/* *INDENT-ON* */
+
 /*************************** SR rewrite graph node ****************************/
 /**
  * @brief Trace for the SR Policy Rewrite graph node
@@ -1190,14 +1238,21 @@ encaps_processing_v6 (vlib_node_runtime_t * node,
                      ip6_header_t * ip0, ip6_header_t * ip0_encap)
 {
   u32 new_l0;
+  u32 flow_label;
 
   ip0_encap->hop_limit -= 1;
   new_l0 =
     ip0->payload_length + sizeof (ip6_header_t) +
     clib_net_to_host_u16 (ip0_encap->payload_length);
   ip0->payload_length = clib_host_to_net_u16 (new_l0);
-  ip0->ip_version_traffic_class_and_flow_label =
-    ip0_encap->ip_version_traffic_class_and_flow_label;
+
+  flow_label = ip6_compute_flow_hash (ip0_encap, IP_FLOW_HASH_DEFAULT);
+  ip0->ip_version_traffic_class_and_flow_label = clib_host_to_net_u32 (
+    0 |
+    (clib_net_to_host_u32 (
+       ip0_encap->ip_version_traffic_class_and_flow_label) &
+     0xfff00000) |
+    (flow_label & 0x0000ffff));
 }
 
 /**
@@ -1462,6 +1517,7 @@ encaps_processing_v4 (vlib_node_runtime_t * node,
   ip6_sr_header_t *sr0;
 
   u32 checksum0;
+  u32 flow_label;
 
   /* Inner IPv4: Decrement TTL & update checksum */
   ip0_encap->ttl -= 1;
@@ -1472,9 +1528,10 @@ encaps_processing_v4 (vlib_node_runtime_t * node,
   /* Outer IPv6: Update length, FL, proto */
   new_l0 = ip0->payload_length + clib_net_to_host_u16 (ip0_encap->length);
   ip0->payload_length = clib_host_to_net_u16 (new_l0);
-  ip0->ip_version_traffic_class_and_flow_label =
-    clib_host_to_net_u32 (0 | ((6 & 0xF) << 28) |
-                         ((ip0_encap->tos & 0xFF) << 20));
+  flow_label = ip4_compute_flow_hash (ip0_encap, IP_FLOW_HASH_DEFAULT);
+  ip0->ip_version_traffic_class_and_flow_label = clib_host_to_net_u32 (
+    0 | ((6 & 0xF) << 28) | ((ip0_encap->tos & 0xFF) << 20) |
+    (flow_label & 0x0000ffff));
   if (ip0->protocol == IP_PROTOCOL_IPV6_ROUTE)
     {
       sr0 = (void *) (ip0 + 1);
@@ -1813,6 +1870,7 @@ sr_policy_rewrite_encaps_l2 (vlib_main_t * vm, vlib_node_runtime_t * node,
          ip6_sr_header_t *sr0, *sr1, *sr2, *sr3;
          ip6_sr_policy_t *sp0, *sp1, *sp2, *sp3;
          ip6_sr_sl_t *sl0, *sl1, *sl2, *sl3;
+         u32 flow_label0, flow_label1, flow_label2, flow_label3;
 
          /* Prefetch next iteration. */
          {
@@ -1868,12 +1926,16 @@ sr_policy_rewrite_encaps_l2 (vlib_main_t * vm, vlib_node_runtime_t * node,
                                   sm->sw_iface_sr_policies[vnet_buffer
                                                            (b3)->sw_if_index
                                                            [VLIB_RX]]);
+         flow_label0 = l2_flow_hash (b0);
+         flow_label1 = l2_flow_hash (b1);
+         flow_label2 = l2_flow_hash (b2);
+         flow_label3 = l2_flow_hash (b3);
 
          if (vec_len (sp0->segments_lists) == 1)
            vnet_buffer (b0)->ip.adj_index[VLIB_TX] = sp0->segments_lists[0];
          else
            {
-             vnet_buffer (b0)->ip.flow_hash = l2_flow_hash (b0);
+             vnet_buffer (b0)->ip.flow_hash = flow_label0;
              vnet_buffer (b0)->ip.adj_index[VLIB_TX] =
                sp0->segments_lists[(vnet_buffer (b0)->ip.flow_hash &
                                     (vec_len (sp0->segments_lists) - 1))];
@@ -1883,7 +1945,7 @@ sr_policy_rewrite_encaps_l2 (vlib_main_t * vm, vlib_node_runtime_t * node,
            vnet_buffer (b1)->ip.adj_index[VLIB_TX] = sp1->segments_lists[1];
          else
            {
-             vnet_buffer (b1)->ip.flow_hash = l2_flow_hash (b1);
+             vnet_buffer (b1)->ip.flow_hash = flow_label1;
              vnet_buffer (b1)->ip.adj_index[VLIB_TX] =
                sp1->segments_lists[(vnet_buffer (b1)->ip.flow_hash &
                                     (vec_len (sp1->segments_lists) - 1))];
@@ -1893,7 +1955,7 @@ sr_policy_rewrite_encaps_l2 (vlib_main_t * vm, vlib_node_runtime_t * node,
            vnet_buffer (b2)->ip.adj_index[VLIB_TX] = sp2->segments_lists[2];
          else
            {
-             vnet_buffer (b2)->ip.flow_hash = l2_flow_hash (b2);
+             vnet_buffer (b2)->ip.flow_hash = flow_label2;
              vnet_buffer (b2)->ip.adj_index[VLIB_TX] =
                sp2->segments_lists[(vnet_buffer (b2)->ip.flow_hash &
                                     (vec_len (sp2->segments_lists) - 1))];
@@ -1903,7 +1965,7 @@ sr_policy_rewrite_encaps_l2 (vlib_main_t * vm, vlib_node_runtime_t * node,
            vnet_buffer (b3)->ip.adj_index[VLIB_TX] = sp3->segments_lists[3];
          else
            {
-             vnet_buffer (b3)->ip.flow_hash = l2_flow_hash (b3);
+             vnet_buffer (b3)->ip.flow_hash = flow_label3;
              vnet_buffer (b3)->ip.adj_index[VLIB_TX] =
                sp3->segments_lists[(vnet_buffer (b3)->ip.flow_hash &
                                     (vec_len (sp3->segments_lists) - 1))];
@@ -1967,37 +2029,45 @@ sr_policy_rewrite_encaps_l2 (vlib_main_t * vm, vlib_node_runtime_t * node,
          if (ip0->protocol == IP_PROTOCOL_IPV6_ROUTE)
            {
              sr0 = (void *) (ip0 + 1);
-             sr0->protocol = IP_PROTOCOL_IP6_NONXT;
+             sr0->protocol = IP_PROTOCOL_IP6_ETHERNET;
            }
          else
-           ip0->protocol = IP_PROTOCOL_IP6_NONXT;
+           ip0->protocol = IP_PROTOCOL_IP6_ETHERNET;
 
          if (ip1->protocol == IP_PROTOCOL_IPV6_ROUTE)
            {
              sr1 = (void *) (ip1 + 1);
-             sr1->protocol = IP_PROTOCOL_IP6_NONXT;
+             sr1->protocol = IP_PROTOCOL_IP6_ETHERNET;
            }
          else
-           ip1->protocol = IP_PROTOCOL_IP6_NONXT;
+           ip1->protocol = IP_PROTOCOL_IP6_ETHERNET;
 
          if (ip2->protocol == IP_PROTOCOL_IPV6_ROUTE)
            {
              sr2 = (void *) (ip2 + 1);
-             sr2->protocol = IP_PROTOCOL_IP6_NONXT;
+             sr2->protocol = IP_PROTOCOL_IP6_ETHERNET;
            }
          else
-           ip2->protocol = IP_PROTOCOL_IP6_NONXT;
+           ip2->protocol = IP_PROTOCOL_IP6_ETHERNET;
 
          if (ip3->protocol == IP_PROTOCOL_IPV6_ROUTE)
            {
              sr3 = (void *) (ip3 + 1);
-             sr3->protocol = IP_PROTOCOL_IP6_NONXT;
+             sr3->protocol = IP_PROTOCOL_IP6_ETHERNET;
            }
          else
-           ip3->protocol = IP_PROTOCOL_IP6_NONXT;
-
-         /* Which Traffic class and flow label do I set ? */
-         //ip0->ip_version_traffic_class_and_flow_label = clib_host_to_net_u32(0|((6&0xF)<<28)|((ip0_encap->tos&0xFF)<<20));
+           ip3->protocol = IP_PROTOCOL_IP6_ETHERNET;
+
+         /* TC is set to 0 for all ethernet frames, should be taken from COS
+          * od DSCP of encapsulated packet in the future */
+         ip0->ip_version_traffic_class_and_flow_label = clib_host_to_net_u32 (
+           0 | ((6 & 0xF) << 28) | ((0x00) << 20) | (flow_label0 & 0xffff));
+         ip1->ip_version_traffic_class_and_flow_label = clib_host_to_net_u32 (
+           0 | ((6 & 0xF) << 28) | ((0x00) << 20) | (flow_label1 & 0xffff));
+         ip2->ip_version_traffic_class_and_flow_label = clib_host_to_net_u32 (
+           0 | ((6 & 0xF) << 28) | ((0x00) << 20) | (flow_label2 & 0xffff));
+         ip3->ip_version_traffic_class_and_flow_label = clib_host_to_net_u32 (
+           0 | ((6 & 0xF) << 28) | ((0x00) << 20) | (flow_label3 & 0xffff));
 
          if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
            {
@@ -2059,6 +2129,7 @@ sr_policy_rewrite_encaps_l2 (vlib_main_t * vm, vlib_node_runtime_t * node,
          ip6_sr_policy_t *sp0;
          ip6_sr_sl_t *sl0;
          u32 next0 = SR_POLICY_REWRITE_NEXT_IP6_LOOKUP;
+         u32 flow_label0;
 
          bi0 = from[0];
          to_next[0] = bi0;
@@ -2073,13 +2144,14 @@ sr_policy_rewrite_encaps_l2 (vlib_main_t * vm, vlib_node_runtime_t * node,
                                   sm->sw_iface_sr_policies[vnet_buffer
                                                            (b0)->sw_if_index
                                                            [VLIB_RX]]);
+         flow_label0 = l2_flow_hash (b0);
 
          /* In case there is more than one SL, LB among them */
          if (vec_len (sp0->segments_lists) == 1)
            vnet_buffer (b0)->ip.adj_index[VLIB_TX] = sp0->segments_lists[0];
          else
            {
-             vnet_buffer (b0)->ip.flow_hash = l2_flow_hash (b0);
+             vnet_buffer (b0)->ip.flow_hash = flow_label0;
              vnet_buffer (b0)->ip.adj_index[VLIB_TX] =
                sp0->segments_lists[(vnet_buffer (b0)->ip.flow_hash &
                                     (vec_len (sp0->segments_lists) - 1))];
@@ -2105,10 +2177,13 @@ sr_policy_rewrite_encaps_l2 (vlib_main_t * vm, vlib_node_runtime_t * node,
          if (ip0->protocol == IP_PROTOCOL_IPV6_ROUTE)
            {
              sr0 = (void *) (ip0 + 1);
-             sr0->protocol = IP_PROTOCOL_IP6_NONXT;
+             sr0->protocol = IP_PROTOCOL_IP6_ETHERNET;
            }
          else
-           ip0->protocol = IP_PROTOCOL_IP6_NONXT;
+           ip0->protocol = IP_PROTOCOL_IP6_ETHERNET;
+
+         ip0->ip_version_traffic_class_and_flow_label = clib_host_to_net_u32 (
+           0 | ((6 & 0xF) << 28) | ((0x00) << 20) | (flow_label0 & 0xffff));
 
          if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
              PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
@@ -3363,8 +3438,8 @@ show_sr_policy_behaviors_command_fn (vlib_main_t * vm,
   vlib_cli_output (vm, "SR Policy behaviors:\n-----------------------\n\n");
 
   /* *INDENT-OFF* */
-  pool_foreach (plugin, sm->policy_plugin_functions,
-    ({ vec_add1 (plugins_vec, plugin); }));
+  pool_foreach (plugin, sm->policy_plugin_functions)
+     { vec_add1 (plugins_vec, plugin); }
   /* *INDENT-ON* */
 
   vlib_cli_output (vm, "Plugin behaviors:\n");