classifier-based ACL: refactor + add output ACL
[vpp.git] / src / plugins / acl / acl.c
index 2c02047..8e1880a 100644 (file)
@@ -20,7 +20,7 @@
 #include <acl/acl.h>
 
 #include <vnet/l2/l2_classify.h>
-#include <vnet/classify/input_acl.h>
+#include <vnet/classify/in_out_acl.h>
 #include <vpp/app/version.h>
 
 #include <vlibapi/api.h>
@@ -138,13 +138,11 @@ vl_api_acl_plugin_get_version_t_handler (vl_api_acl_plugin_get_version_t * mp)
   acl_main_t *am = &acl_main;
   vl_api_acl_plugin_get_version_reply_t *rmp;
   int msg_size = sizeof (*rmp);
-  unix_shared_memory_queue_t *q;
+  vl_api_registration_t *reg;
 
-  q = vl_api_client_index_to_input_queue (mp->client_index);
-  if (q == 0)
-    {
-      return;
-    }
+  reg = vl_api_client_index_to_registration (mp->client_index);
+  if (!reg)
+    return;
 
   rmp = vl_msg_api_alloc (msg_size);
   memset (rmp, 0, msg_size);
@@ -154,7 +152,7 @@ vl_api_acl_plugin_get_version_t_handler (vl_api_acl_plugin_get_version_t * mp)
   rmp->major = htonl (ACL_PLUGIN_VERSION_MAJOR);
   rmp->minor = htonl (ACL_PLUGIN_VERSION_MINOR);
 
-  vl_msg_api_send_shmem (q, (u8 *) & rmp);
+  vl_api_send_msg (reg, (u8 *) rmp);
 }
 
 static void
@@ -337,8 +335,6 @@ acl_del_list (u32 acl_list_index)
 /* Some aids in ASCII graphing the content */
 #define XX "\377"
 #define __ "\000"
-#define DOT1AD "\210\250"
-#define DOT1Q "\201\00"
 #define _(x)
 #define v
 /* *INDENT-OFF* */
@@ -393,15 +389,15 @@ u8 ip4_5tuple_mask[] =
 
  u8 dot1q_5tuple_mask[] =
    _("             dmac               smac          dot1q         etype ")
-   _(ether) __ __ __ __ __ __ v __ __ __ __ __ __ v DOT1Q __ __ v XX XX v
+   _(ether) __ __ __ __ __ __ v __ __ __ __ __ __ v XX XX __ __ v XX XX v
    _(padpad) __ __ __ __
    _(padpad) __ __ __ __
    _(padpad) __ __ __ __
    _(padeth) __ __;
 
  u8 dot1ad_5tuple_mask[] =
-   _("             dmac               smac          dot1ad                     etype ")
-   _(ether) __ __ __ __ __ __ v __ __ __ __ __ __ v DOT1AD __ __ DOT1Q __ __ v XX XX v
+   _("             dmac               smac          dot1ad      dot1q         etype ")
+   _(ether) __ __ __ __ __ __ v __ __ __ __ __ __ v XX XX __ __ XX XX __ __ v XX XX v
    _(padpad) __ __ __ __
    _(padpad) __ __ __ __
    _(padeth) __ __;
@@ -409,8 +405,6 @@ u8 ip4_5tuple_mask[] =
 /* *INDENT-ON* */
 #undef XX
 #undef __
-#undef DOT1AD
-#undef DOT1Q
 #undef _
 #undef v
 
@@ -639,6 +633,21 @@ acl_add_vlan_session (acl_main_t * am, u32 table_index, u8 is_output,
     }
   match = (is_dot1ad) ? dot1ad_5tuple_mask : dot1q_5tuple_mask;
   idx = (is_dot1ad) ? 20 : 16;
+  if (is_dot1ad)
+    {
+      /* 802.1ad ethertype */
+      match[12] = 0x88;
+      match[13] = 0xa8;
+      /* 802.1q ethertype */
+      match[16] = 0x81;
+      match[17] = 0x00;
+    }
+  else
+    {
+      /* 802.1q ethertype */
+      match[12] = 0x81;
+      match[13] = 0x00;
+    }
 
   /* add sessions to vlan tables per ethernet_type */
   if (is_ip6)
@@ -655,7 +664,16 @@ acl_add_vlan_session (acl_main_t * am, u32 table_index, u8 is_output,
     }
   vnet_classify_add_del_session (cm, table_index, match, next_acl,
                                 session_idx, 0, 0, 0, 1);
-  memset (&match[idx], 0x00, 2);
+  /* reset the mask back to being a mask */
+  match[idx] = 0xff;
+  match[idx + 1] = 0xff;
+  match[12] = 0xff;
+  match[13] = 0xff;
+  if (is_dot1ad)
+    {
+      match[16] = 0xff;
+      match[17] = 0xff;
+    }
 }
 
 static int
@@ -1482,6 +1500,27 @@ macip_destroy_classify_tables (acl_main_t * am, u32 macip_acl_index)
     }
 }
 
+static int
+macip_maybe_apply_unapply_classifier_tables (acl_main_t * am, u32 acl_index,
+                                            int is_apply)
+{
+  int rv = 0;
+  int rv0 = 0;
+  int i;
+  macip_acl_list_t *a = pool_elt_at_index (am->macip_acls, acl_index);
+
+  for (i = 0; i < vec_len (am->macip_acl_by_sw_if_index); i++)
+    if (vec_elt (am->macip_acl_by_sw_if_index, i) == acl_index)
+      {
+       rv0 = vnet_set_input_acl_intfc (am->vlib_main, i, a->ip4_table_index,
+                                       a->ip6_table_index, a->l2_table_index,
+                                       is_apply);
+       /* return the first unhappy outcome but make try to plough through. */
+       rv = rv || rv0;
+      }
+  return rv;
+}
+
 static int
 macip_acl_add_list (u32 count, vl_api_macip_acl_rule_t rules[],
                    u32 * acl_list_index, u8 * tag)
@@ -1491,6 +1530,7 @@ macip_acl_add_list (u32 count, vl_api_macip_acl_rule_t rules[],
   macip_acl_rule_t *r;
   macip_acl_rule_t *acl_new_rules = 0;
   int i;
+  int rv = 0;
 
   if (*acl_list_index != ~0)
     {
@@ -1511,6 +1551,9 @@ macip_acl_add_list (u32 count, vl_api_macip_acl_rule_t rules[],
        ("acl-plugin-warning: Trying to create empty MACIP ACL (tag %s)",
         tag);
     }
+  /* if replacing the ACL, unapply the classifier tables first - they will be gone.. */
+  if (~0 != *acl_list_index)
+    rv = macip_maybe_apply_unapply_classifier_tables (am, *acl_list_index, 0);
   void *oldheap = acl_set_heap (am);
   /* Create and populate the rules */
   if (count > 0)
@@ -1555,7 +1598,10 @@ macip_acl_add_list (u32 count, vl_api_macip_acl_rule_t rules[],
   /* Create and populate the classifer tables */
   macip_create_classify_tables (am, *acl_list_index);
   clib_mem_set_heap (oldheap);
-  return 0;
+  /* If the ACL was already applied somewhere, reapply the newly created tables */
+  rv = rv
+    || macip_maybe_apply_unapply_classifier_tables (am, *acl_list_index, 1);
+  return rv;
 }
 
 
@@ -1823,7 +1869,7 @@ copy_acl_rule_to_api_rule (vl_api_acl_rule_t * api_rule, acl_rule_t * r)
 }
 
 static void
-send_acl_details (acl_main_t * am, unix_shared_memory_queue_t * q,
+send_acl_details (acl_main_t * am, vl_api_registration_t * reg,
                  acl_list_t * acl, u32 context)
 {
   vl_api_acl_details_t *mp;
@@ -1849,7 +1895,7 @@ send_acl_details (acl_main_t * am, unix_shared_memory_queue_t * q,
     }
 
   clib_mem_set_heap (oldheap);
-  vl_msg_api_send_shmem (q, (u8 *) & mp);
+  vl_api_send_msg (reg, (u8 *) mp);
 }
 
 
@@ -1859,15 +1905,12 @@ vl_api_acl_dump_t_handler (vl_api_acl_dump_t * mp)
   acl_main_t *am = &acl_main;
   u32 acl_index;
   acl_list_t *acl;
-
   int rv = -1;
-  unix_shared_memory_queue_t *q;
+  vl_api_registration_t *reg;
 
-  q = vl_api_client_index_to_input_queue (mp->client_index);
-  if (q == 0)
-    {
-      return;
-    }
+  reg = vl_api_client_index_to_registration (mp->client_index);
+  if (!reg)
+    return;
 
   if (mp->acl_index == ~0)
     {
@@ -1875,7 +1918,7 @@ vl_api_acl_dump_t_handler (vl_api_acl_dump_t * mp)
     /* Just dump all ACLs */
     pool_foreach (acl, am->acls,
     ({
-      send_acl_details(am, q, acl, mp->context);
+      send_acl_details(am, reg, acl, mp->context);
     }));
     /* *INDENT-ON* */
     }
@@ -1885,7 +1928,7 @@ vl_api_acl_dump_t_handler (vl_api_acl_dump_t * mp)
       if (!pool_is_free_index (am->acls, acl_index))
        {
          acl = pool_elt_at_index (am->acls, acl_index);
-         send_acl_details (am, q, acl, mp->context);
+         send_acl_details (am, reg, acl, mp->context);
        }
     }
 
@@ -1898,7 +1941,7 @@ vl_api_acl_dump_t_handler (vl_api_acl_dump_t * mp)
 
 static void
 send_acl_interface_list_details (acl_main_t * am,
-                                unix_shared_memory_queue_t * q,
+                                vl_api_registration_t * reg,
                                 u32 sw_if_index, u32 context)
 {
   vl_api_acl_interface_list_details_t *mp;
@@ -1939,7 +1982,7 @@ send_acl_interface_list_details (acl_main_t * am,
        htonl (am->output_acl_vec_by_sw_if_index[sw_if_index][i]);
     }
   clib_mem_set_heap (oldheap);
-  vl_msg_api_send_shmem (q, (u8 *) & mp);
+  vl_api_send_msg (reg, (u8 *) mp);
 }
 
 static void
@@ -1951,20 +1994,18 @@ vl_api_acl_interface_list_dump_t_handler (vl_api_acl_interface_list_dump_t *
   vnet_interface_main_t *im = &am->vnet_main->interface_main;
 
   u32 sw_if_index;
-  unix_shared_memory_queue_t *q;
+  vl_api_registration_t *reg;
 
-  q = vl_api_client_index_to_input_queue (mp->client_index);
-  if (q == 0)
-    {
-      return;
-    }
+  reg = vl_api_client_index_to_registration (mp->client_index);
+  if (!reg)
+    return;
 
   if (mp->sw_if_index == ~0)
     {
     /* *INDENT-OFF* */
     pool_foreach (swif, im->sw_interfaces,
     ({
-      send_acl_interface_list_details(am, q, swif->sw_if_index, mp->context);
+      send_acl_interface_list_details(am, reg, swif->sw_if_index, mp->context);
     }));
     /* *INDENT-ON* */
     }
@@ -1972,7 +2013,7 @@ vl_api_acl_interface_list_dump_t_handler (vl_api_acl_interface_list_dump_t *
     {
       sw_if_index = ntohl (mp->sw_if_index);
       if (!pool_is_free_index (im->sw_interfaces, sw_if_index))
-       send_acl_interface_list_details (am, q, sw_if_index, mp->context);
+       send_acl_interface_list_details (am, reg, sw_if_index, mp->context);
     }
 }
 
@@ -2065,7 +2106,7 @@ static void
 }
 
 static void
-send_macip_acl_details (acl_main_t * am, unix_shared_memory_queue_t * q,
+send_macip_acl_details (acl_main_t * am, vl_api_registration_t * reg,
                        macip_acl_list_t * acl, u32 context)
 {
   vl_api_macip_acl_details_t *mp;
@@ -2110,7 +2151,7 @@ send_macip_acl_details (acl_main_t * am, unix_shared_memory_queue_t * q,
       mp->count = 0;
     }
 
-  vl_msg_api_send_shmem (q, (u8 *) & mp);
+  vl_api_send_msg (reg, (u8 *) mp);
 }
 
 
@@ -2120,22 +2161,21 @@ vl_api_macip_acl_dump_t_handler (vl_api_macip_acl_dump_t * mp)
   acl_main_t *am = &acl_main;
   macip_acl_list_t *acl;
 
-  unix_shared_memory_queue_t *q;
+  vl_api_registration_t *reg;
 
-  q = vl_api_client_index_to_input_queue (mp->client_index);
-  if (q == 0)
-    {
-      return;
-    }
+  reg = vl_api_client_index_to_registration (mp->client_index);
+  if (!reg)
+    return;
 
   if (mp->acl_index == ~0)
     {
       /* Just dump all ACLs for now, with sw_if_index = ~0 */
       pool_foreach (acl, am->macip_acls, (
                                           {
-                                          send_macip_acl_details (am, q, acl,
-                                                                  mp->
-                                                                  context);}
+                                          send_macip_acl_details (am, reg,
+                                                                  acl,
+                                                                  mp->context);
+                                          }
                    ));
       /* *INDENT-ON* */
     }
@@ -2145,7 +2185,7 @@ vl_api_macip_acl_dump_t_handler (vl_api_macip_acl_dump_t * mp)
       if (!pool_is_free_index (am->macip_acls, acl_index))
        {
          acl = pool_elt_at_index (am->macip_acls, acl_index);
-         send_macip_acl_details (am, q, acl, mp->context);
+         send_macip_acl_details (am, reg, acl, mp->context);
        }
     }
 }
@@ -2158,14 +2198,12 @@ vl_api_macip_acl_interface_get_t_handler (vl_api_macip_acl_interface_get_t *
   vl_api_macip_acl_interface_get_reply_t *rmp;
   u32 count = vec_len (am->macip_acl_by_sw_if_index);
   int msg_size = sizeof (*rmp) + sizeof (rmp->acls[0]) * count;
-  unix_shared_memory_queue_t *q;
+  vl_api_registration_t *reg;
   int i;
 
-  q = vl_api_client_index_to_input_queue (mp->client_index);
-  if (q == 0)
-    {
-      return;
-    }
+  reg = vl_api_client_index_to_registration (mp->client_index);
+  if (!reg)
+    return;
 
   rmp = vl_msg_api_alloc (msg_size);
   memset (rmp, 0, msg_size);
@@ -2178,12 +2216,12 @@ vl_api_macip_acl_interface_get_t_handler (vl_api_macip_acl_interface_get_t *
       rmp->acls[i] = htonl (am->macip_acl_by_sw_if_index[i]);
     }
 
-  vl_msg_api_send_shmem (q, (u8 *) & rmp);
+  vl_api_send_msg (reg, (u8 *) rmp);
 }
 
 static void
 send_macip_acl_interface_list_details (acl_main_t * am,
-                                      unix_shared_memory_queue_t * q,
+                                      vl_api_registration_t * reg,
                                       u32 sw_if_index,
                                       u32 acl_index, u32 context)
 {
@@ -2202,22 +2240,20 @@ send_macip_acl_interface_list_details (acl_main_t * am,
   rmp->sw_if_index = htonl (sw_if_index);
   rmp->acls[0] = htonl (acl_index);
 
-  vl_msg_api_send_shmem (q, (u8 *) & rmp);
+  vl_api_send_msg (reg, (u8 *) rmp);
 }
 
 static void
   vl_api_macip_acl_interface_list_dump_t_handler
   (vl_api_macip_acl_interface_list_dump_t * mp)
 {
-  unix_shared_memory_queue_t *q;
+  vl_api_registration_t *reg;
   acl_main_t *am = &acl_main;
   u32 sw_if_index = ntohl (mp->sw_if_index);
 
-  q = vl_api_client_index_to_input_queue (mp->client_index);
-  if (q == 0)
-    {
-      return;
-    }
+  reg = vl_api_client_index_to_registration (mp->client_index);
+  if (!reg)
+    return;
 
   if (sw_if_index == ~0)
     {
@@ -2225,7 +2261,7 @@ static void
       {
        if (~0 != am->macip_acl_by_sw_if_index[sw_if_index])
          {
-           send_macip_acl_interface_list_details (am, q, sw_if_index,
+           send_macip_acl_interface_list_details (am, reg, sw_if_index,
                                                   am->macip_acl_by_sw_if_index
                                                   [sw_if_index],
                                                   mp->context);
@@ -2236,7 +2272,7 @@ static void
     {
       if (vec_len (am->macip_acl_by_sw_if_index) > sw_if_index)
        {
-         send_macip_acl_interface_list_details (am, q, sw_if_index,
+         send_macip_acl_interface_list_details (am, reg, sw_if_index,
                                                 am->macip_acl_by_sw_if_index
                                                 [sw_if_index], mp->context);
        }
@@ -2717,7 +2753,7 @@ acl_show_aclplugin_acl_fn (vlib_main_t * vm,
   acl_main_t *am = &acl_main;
 
   u32 acl_index = ~0;
-  unformat (input, "index %u", &acl_index);
+  (void) unformat (input, "index %u", &acl_index);
 
   acl_plugin_show_acl (am, acl_index);
   return error;
@@ -2773,6 +2809,26 @@ acl_plugin_show_interface (acl_main_t * am, u32 sw_if_index, int show_acl)
 
 }
 
+
+static clib_error_t *
+acl_show_aclplugin_decode_5tuple_fn (vlib_main_t * vm,
+                                    unformat_input_t * input,
+                                    vlib_cli_command_t * cmd)
+{
+  clib_error_t *error = 0;
+  u64 five_tuple[6] = { 0, 0, 0, 0, 0, 0 };
+
+  if (unformat
+      (input, "%llx %llx %llx %llx %llx %llx", &five_tuple[0], &five_tuple[1],
+       &five_tuple[2], &five_tuple[3], &five_tuple[4], &five_tuple[5]))
+    vlib_cli_output (vm, "5-tuple structure decode: %U\n\n",
+                    format_acl_plugin_5tuple, five_tuple);
+  else
+    error = clib_error_return (0, "expecting 6 hex integers");
+  return error;
+}
+
+
 static clib_error_t *
 acl_show_aclplugin_interface_fn (vlib_main_t * vm,
                                 unformat_input_t * input,
@@ -2782,7 +2838,7 @@ acl_show_aclplugin_interface_fn (vlib_main_t * vm,
   acl_main_t *am = &acl_main;
 
   u32 sw_if_index = ~0;
-  unformat (input, "sw_if_index %u", &sw_if_index);
+  (void) unformat (input, "sw_if_index %u", &sw_if_index);
   int show_acl = unformat (input, "acl");
 
   acl_plugin_show_interface (am, sw_if_index, show_acl);
@@ -2964,9 +3020,9 @@ acl_show_aclplugin_sessions_fn (vlib_main_t * vm,
   u32 show_bihash_verbose = 0;
   u32 show_session_thread_id = ~0;
   u32 show_session_session_index = ~0;
-  unformat (input, "thread %u index %u", &show_session_thread_id,
-           &show_session_session_index);
-  unformat (input, "verbose %u", &show_bihash_verbose);
+  (void) unformat (input, "thread %u index %u", &show_session_thread_id,
+                  &show_session_session_index);
+  (void) unformat (input, "verbose %u", &show_bihash_verbose);
 
   acl_plugin_show_sessions (am, show_session_thread_id,
                            show_session_session_index);
@@ -3193,6 +3249,12 @@ VLIB_CLI_COMMAND (aclplugin_show_acl_command, static) = {
     .function = acl_show_aclplugin_acl_fn,
 };
 
+VLIB_CLI_COMMAND (aclplugin_show_decode_5tuple_command, static) = {
+    .path = "show acl-plugin decode 5tuple",
+    .short_help = "show acl-plugin decode 5tuple XXXX XXXX XXXX XXXX XXXX XXXX",
+    .function = acl_show_aclplugin_decode_5tuple_fn,
+};
+
 VLIB_CLI_COMMAND (aclplugin_show_interface_command, static) = {
     .path = "show acl-plugin interface",
     .short_help = "show acl-plugin interface [sw_if_index N] [acl]",