Fix pretty-printing in "api trace custom-dump" (VPP-683)
[vpp.git] / plugins / acl-plugin / acl / acl.c
index 6b7f637..bc2b2bc 100644 (file)
@@ -13,6 +13,8 @@
  * limitations under the License.
  */
 
+#include <stddef.h>
+
 #include <vnet/vnet.h>
 #include <vnet/plugin/plugin.h>
 #include <acl/acl.h>
@@ -109,23 +111,6 @@ do {                                                            \
     vl_msg_api_send_shmem (q, (u8 *)&rmp);                      \
 } while(0);
 
-#define VALIDATE_SW_IF_INDEX(mp)                                \
- do { u32 __sw_if_index = ntohl(mp->sw_if_index);               \
-    vnet_main_t *__vnm = vnet_get_main();                       \
-    if (pool_is_free_index(__vnm->interface_main.sw_interfaces, \
-                           __sw_if_index)) {                    \
-        rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;                \
-        goto bad_sw_if_index;                                   \
-    }                                                           \
-} while(0);
-
-#define BAD_SW_IF_INDEX_LABEL                   \
-do {                                            \
-bad_sw_if_index:                                \
-    ;                                           \
-} while (0);
-
-
 
 /* List of message types that this plugin understands */
 
@@ -1059,6 +1044,7 @@ typedef struct
   u8 prefix_len;
   u32 count;
   u32 table_index;
+  u32 arp_table_index;
 } macip_match_type_t;
 
 static u32
@@ -1097,6 +1083,16 @@ match_type_compare (macip_match_type_t * m1, macip_match_type_t * m2)
   return match_type_metric (m1) - match_type_metric (m2);
 }
 
+/* Get the offset of L3 source within ethernet packet */
+static int
+get_l3_src_offset(int is6)
+{
+  if(is6)
+    return (sizeof(ethernet_header_t) + offsetof(ip6_header_t, src_address));
+  else
+    return (sizeof(ethernet_header_t) + offsetof(ip4_header_t, src_address));
+}
+
 static int
 macip_create_classify_tables (acl_main_t * am, u32 macip_acl_index)
 {
@@ -1132,11 +1128,39 @@ macip_create_classify_tables (acl_main_t * am, u32 macip_acl_index)
   vec_sort_with_function (mvec, match_type_compare);
   /* Create the classifier tables */
   last_table = ~0;
+  /* First add ARP tables */
   vec_foreach (mt, mvec)
   {
     int mask_len;
-    int is6 = a->rules[i].is_ipv6;
-    int l3_src_offs = is6 ? 22 : 26;   /* See the ascii art packet format above to verify these */
+    int is6 = mt->is_ipv6;
+
+    mt->arp_table_index = ~0;
+    if (!is6)
+      {
+        memset (mask, 0, sizeof (mask));
+        memcpy (&mask[6], mt->mac_mask, 6);
+        memset (&mask[12], 0xff, 2); /* ethernet protocol */
+        memcpy (&mask[14 + 8], mt->mac_mask, 6);
+
+        for (i = 0; i < (mt->prefix_len / 8); i++)
+          mask[14 + 14 + i] = 0xff;
+        if (mt->prefix_len % 8)
+          mask[14 + 14 + (mt->prefix_len / 8)] = 0xff - ((1 << (8 - mt->prefix_len % 8)) - 1);
+
+        mask_len = ((14 + 14 + ((mt->prefix_len+7) / 8) +
+                (sizeof (u32x4)-1))/sizeof(u32x4)) * sizeof (u32x4);
+        acl_classify_add_del_table_small (cm, mask, mask_len, last_table,
+                               (~0 == last_table) ? 0 : ~0, &mt->arp_table_index,
+                               1);
+        last_table = mt->arp_table_index;
+      }
+  }
+  /* Now add IP[46] tables */
+  vec_foreach (mt, mvec)
+  {
+    int mask_len;
+    int is6 = mt->is_ipv6;
+    int l3_src_offs = get_l3_src_offset(is6);
     memset (mask, 0, sizeof (mask));
     memcpy (&mask[6], mt->mac_mask, 6);
     for (i = 0; i < (mt->prefix_len / 8); i++)
@@ -1148,7 +1172,12 @@ macip_create_classify_tables (acl_main_t * am, u32 macip_acl_index)
        mask[l3_src_offs + (mt->prefix_len / 8)] =
          0xff - ((1 << (8 - mt->prefix_len % 8)) - 1);
       }
-    mask_len = ((l3_src_offs + (mt->prefix_len / 8)) / 16 + 1) * 16;
+    /*
+     * Round-up the number of bytes needed to store the prefix,
+     * and round up the number of vectors too
+     */
+    mask_len = ((l3_src_offs + ((mt->prefix_len+7) / 8) +
+                (sizeof (u32x4)-1))/sizeof(u32x4)) * sizeof (u32x4);
     acl_classify_add_del_table_small (cm, mask, mask_len, last_table,
                                (~0 == last_table) ? 0 : ~0, &mt->table_index,
                                1);
@@ -1164,16 +1193,21 @@ macip_create_classify_tables (acl_main_t * am, u32 macip_acl_index)
       u32 action = 0;
       u32 metadata = 0;
       int is6 = a->rules[i].is_ipv6;
-      int l3_src_offs = is6 ? 22 : 26; /* See the ascii art packet format above to verify these */
+      int l3_src_offs = get_l3_src_offset(is6);
       memset (mask, 0, sizeof (mask));
       memcpy (&mask[6], a->rules[i].src_mac, 6);
+      memset (&mask[12], 0xff, 2); /* ethernet protocol */
       if (is6)
        {
          memcpy (&mask[l3_src_offs], &a->rules[i].src_ip_addr.ip6, 16);
+         mask[12] = 0x86;
+         mask[13] = 0xdd;
        }
       else
        {
          memcpy (&mask[l3_src_offs], &a->rules[i].src_ip_addr.ip4, 4);
+         mask[12] = 0x08;
+         mask[13] = 0x00;
        }
       match_type_index =
        macip_find_match_type (mvec, a->rules[i].src_mac_mask,
@@ -1183,6 +1217,19 @@ macip_create_classify_tables (acl_main_t * am, u32 macip_acl_index)
       vnet_classify_add_del_session (cm, mvec[match_type_index].table_index,
                                     mask, a->rules[i].is_permit ? ~0 : 0, i,
                                     0, action, metadata, 1);
+      /* add ARP table entry too */
+      if (!is6 && (mvec[match_type_index].arp_table_index != ~0))
+        {
+          memset (mask, 0, sizeof (mask));
+          memcpy (&mask[6], a->rules[i].src_mac, 6);
+          mask[12] = 0x08;
+          mask[13] = 0x06;
+          memcpy (&mask[14 + 8], a->rules[i].src_mac, 6);
+          memcpy (&mask[14 + 14], &a->rules[i].src_ip_addr.ip4, 4);
+          vnet_classify_add_del_session (cm, mvec[match_type_index].arp_table_index,
+                                    mask, a->rules[i].is_permit ? ~0 : 0, i,
+                                    0, action, metadata, 1);
+        }
     }
   return 0;
 }
@@ -1236,8 +1283,10 @@ macip_acl_add_list (u32 count, vl_api_macip_acl_rule_t rules[],
       r->is_ipv6 = rules[i].is_ipv6;
       memcpy (&r->src_mac, rules[i].src_mac, 6);
       memcpy (&r->src_mac_mask, rules[i].src_mac_mask, 6);
-
-      memcpy (&r->src_ip_addr, rules[i].src_ip_addr, sizeof (r->src_ip_addr));
+      if(rules[i].is_ipv6)
+        memcpy (&r->src_ip_addr.ip6, rules[i].src_ip_addr, 16);
+      else
+        memcpy (&r->src_ip_addr.ip4, rules[i].src_ip_addr, 4);
       r->src_prefixlen = rules[i].src_ip_prefix_len;
     }
 
@@ -1258,6 +1307,29 @@ macip_acl_add_list (u32 count, vl_api_macip_acl_rule_t rules[],
 }
 
 
+/* No check for validity of sw_if_index - the callers were supposed to validate */
+
+static int
+macip_acl_interface_del_acl (acl_main_t * am, u32 sw_if_index)
+{
+  int rv;
+  u32 macip_acl_index;
+  macip_acl_list_t *a;
+  vec_validate_init_empty (am->macip_acl_by_sw_if_index, sw_if_index, ~0);
+  macip_acl_index = am->macip_acl_by_sw_if_index[sw_if_index];
+  /* No point in deleting MACIP ACL which is not applied */
+  if (~0 == macip_acl_index)
+    return -1;
+  a = &am->macip_acls[macip_acl_index];
+  /* remove the classifier tables off the interface L2 ACL */
+  rv =
+    vnet_set_input_acl_intfc (am->vlib_main, sw_if_index, a->ip4_table_index,
+                             a->ip6_table_index, a->l2_table_index, 0);
+  /* Unset the MACIP ACL index */
+  am->macip_acl_by_sw_if_index[sw_if_index] = ~0;
+  return rv;
+}
+
 /* No check for validity of sw_if_index - the callers were supposed to validate */
 
 static int
@@ -1272,6 +1344,9 @@ macip_acl_interface_add_acl (acl_main_t * am, u32 sw_if_index,
     }
   a = &am->macip_acls[macip_acl_index];
   vec_validate_init_empty (am->macip_acl_by_sw_if_index, sw_if_index, ~0);
+  /* If there already a MACIP ACL applied, unapply it */
+  if (~0 != am->macip_acl_by_sw_if_index[sw_if_index])
+    macip_acl_interface_del_acl(am, sw_if_index);
   am->macip_acl_by_sw_if_index[sw_if_index] = macip_acl_index;
   /* Apply the classifier tables for L2 ACLs */
   rv =
@@ -1280,17 +1355,6 @@ macip_acl_interface_add_acl (acl_main_t * am, u32 sw_if_index,
   return rv;
 }
 
-static int
-macip_acl_interface_del_acl (acl_main_t * am, u32 sw_if_index)
-{
-  int rv;
-  vec_validate_init_empty (am->macip_acl_by_sw_if_index, sw_if_index, ~0);
-  am->macip_acl_by_sw_if_index[sw_if_index] = ~0;
-  /* remove the classifier tables off the interface L2 ACL */
-  rv = vnet_set_input_acl_intfc (am->vlib_main, sw_if_index, ~0, ~0, ~0, 0);
-  return rv;
-}
-
 static int
 macip_acl_del_list (u32 acl_list_index)
 {
@@ -1377,16 +1441,18 @@ static void
 vl_api_acl_interface_add_del_t_handler (vl_api_acl_interface_add_del_t * mp)
 {
   acl_main_t *sm = &acl_main;
+  vnet_interface_main_t *im = &sm->vnet_main->interface_main;
+  u32 sw_if_index = ntohl (mp->sw_if_index);
   vl_api_acl_interface_add_del_reply_t *rmp;
   int rv = -1;
-  VALIDATE_SW_IF_INDEX (mp);
 
-  rv =
-    acl_interface_add_del_inout_acl (ntohl (mp->sw_if_index), mp->is_add,
+  if (pool_is_free_index(im->sw_interfaces, sw_if_index))
+    rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
+  else
+    rv =
+      acl_interface_add_del_inout_acl (sw_if_index, mp->is_add,
                                     mp->is_input, ntohl (mp->acl_index));
 
-  BAD_SW_IF_INDEX_LABEL;
-
   REPLY_MACRO (VL_API_ACL_INTERFACE_ADD_DEL_REPLY);
 }
 
@@ -1398,20 +1464,23 @@ vl_api_acl_interface_set_acl_list_t_handler
   vl_api_acl_interface_set_acl_list_reply_t *rmp;
   int rv = 0;
   int i;
-  VALIDATE_SW_IF_INDEX (mp);
+  vnet_interface_main_t *im = &sm->vnet_main->interface_main;
   u32 sw_if_index = ntohl (mp->sw_if_index);
 
-  acl_interface_reset_inout_acls (sw_if_index, 0);
-  acl_interface_reset_inout_acls (sw_if_index, 1);
-
-  for (i = 0; i < mp->count; i++)
+  if (pool_is_free_index(im->sw_interfaces, sw_if_index))
+    rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
+  else
     {
-      acl_interface_add_del_inout_acl (sw_if_index, 1, (i < mp->n_input),
+      acl_interface_reset_inout_acls (sw_if_index, 0);
+      acl_interface_reset_inout_acls (sw_if_index, 1);
+
+      for (i = 0; i < mp->count; i++)
+        {
+          acl_interface_add_del_inout_acl (sw_if_index, 1, (i < mp->n_input),
                                       ntohl (mp->acls[i]));
+        }
     }
 
-  BAD_SW_IF_INDEX_LABEL;
-
   REPLY_MACRO (VL_API_ACL_INTERFACE_SET_ACL_LIST_REPLY);
 }
 
@@ -1567,7 +1636,6 @@ vl_api_acl_interface_list_dump_t_handler (vl_api_acl_interface_list_dump_t *
   vnet_sw_interface_t *swif;
   vnet_interface_main_t *im = &am->vnet_main->interface_main;
 
-  int rv = -1;
   u32 sw_if_index;
   unix_shared_memory_queue_t *q;
 
@@ -1588,17 +1656,9 @@ vl_api_acl_interface_list_dump_t_handler (vl_api_acl_interface_list_dump_t *
     }
   else
     {
-      VALIDATE_SW_IF_INDEX (mp);
       sw_if_index = ntohl (mp->sw_if_index);
-      send_acl_interface_list_details (am, q, sw_if_index, mp->context);
-    }
-  return;
-
-  BAD_SW_IF_INDEX_LABEL;
-  if (rv == -1)
-    {
-      /* FIXME API: should we signal an error here at all ? */
-      return;
+      if (!pool_is_free_index(im->sw_interfaces, sw_if_index))
+        send_acl_interface_list_details (am, q, sw_if_index, mp->context);
     }
 }
 
@@ -1642,14 +1702,16 @@ vl_api_macip_acl_interface_add_del_t_handler
   acl_main_t *sm = &acl_main;
   vl_api_macip_acl_interface_add_del_reply_t *rmp;
   int rv = -1;
-  VALIDATE_SW_IF_INDEX (mp);
+  vnet_interface_main_t *im = &sm->vnet_main->interface_main;
+  u32 sw_if_index = ntohl (mp->sw_if_index);
 
-  rv =
-    macip_acl_interface_add_del_acl (ntohl (mp->sw_if_index), mp->is_add,
+  if (pool_is_free_index(im->sw_interfaces, sw_if_index))
+    rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
+  else
+    rv =
+      macip_acl_interface_add_del_acl (ntohl (mp->sw_if_index), mp->is_add,
                                     ntohl (mp->acl_index));
 
-  BAD_SW_IF_INDEX_LABEL;
-
   REPLY_MACRO (VL_API_MACIP_ACL_INTERFACE_ADD_DEL_REPLY);
 }
 
@@ -1683,9 +1745,12 @@ send_macip_acl_details (acl_main_t * am, unix_shared_memory_queue_t * q,
          memcpy (rules[i].src_mac, &r->src_mac, sizeof (r->src_mac));
          memcpy (rules[i].src_mac_mask, &r->src_mac_mask,
                  sizeof (r->src_mac_mask));
-
-         memcpy (rules[i].src_ip_addr, &r->src_ip_addr,
-                 sizeof (r->src_ip_addr));
+          if (r->is_ipv6)
+            memcpy (rules[i].src_ip_addr, &r->src_ip_addr.ip6,
+                 sizeof (r->src_ip_addr.ip6));
+          else
+            memcpy (rules[i].src_ip_addr, &r->src_ip_addr.ip4,
+                 sizeof (r->src_ip_addr.ip4));
          rules[i].src_ip_prefix_len = r->src_prefixlen;
        }
     }
@@ -1767,8 +1832,6 @@ vl_api_macip_acl_interface_get_t_handler (vl_api_macip_acl_interface_get_t *
   vl_msg_api_send_shmem (q, (u8 *) & rmp);
 }
 
-
-
 /* Set up the API message handling tables */
 static clib_error_t *
 acl_plugin_api_hookup (vlib_main_t * vm)
@@ -1835,7 +1898,11 @@ acl_setup_nodes (void)
 
   feat_bitmap_init_next_nodes (vm, acl_in_node.index, L2INPUT_N_FEAT,
                               l2input_get_feat_names (),
-                              am->acl_in_node_input_next_node_index);
+                              am->acl_in_node_feat_next_node_index);
+
+  feat_bitmap_init_next_nodes (vm, acl_out_node.index, L2OUTPUT_N_FEAT,
+                              l2output_get_feat_names (),
+                              am->acl_out_node_feat_next_node_index);
 
   memset (&am->acl_in_ip4_match_next[0], 0,
          sizeof (am->acl_in_ip4_match_next));