ikev2: add support for custom ipsec-over-udp port
[vpp.git] / src / vppinfra / maplog.c
index 41ee075..6891336 100644 (file)
@@ -27,7 +27,7 @@
 int
 clib_maplog_init (clib_maplog_init_args_t * a)
 {
-  int i, fd;
+  int i, fd, limit;
   int rv = 0;
   u8 zero = 0;
   u32 record_size_in_cache_lines;
@@ -42,7 +42,7 @@ clib_maplog_init (clib_maplog_init_args_t * a)
   if (mm->flags & CLIB_MAPLOG_FLAG_INIT)
     return (-2);
 
-  memset (mm, 0, sizeof (*mm));
+  clib_memset (mm, 0, sizeof (*mm));
 
   record_size_in_cache_lines =
     (a->record_size_in_bytes + CLIB_CACHE_LINE_BYTES -
@@ -54,7 +54,6 @@ clib_maplog_init (clib_maplog_init_args_t * a)
   /* Round up file size in records to a power of 2, for speed... */
   mm->log2_file_size_in_records = max_log2 (file_size_in_records);
   file_size_in_records = 1ULL << (mm->log2_file_size_in_records);
-
   a->file_size_in_bytes = file_size_in_records * record_size_in_cache_lines
     * CLIB_CACHE_LINE_BYTES;
 
@@ -68,9 +67,19 @@ clib_maplog_init (clib_maplog_init_args_t * a)
   mm->file_size_in_records = file_size_in_records;
   mm->flags |= CLIB_MAPLOG_FLAG_INIT;
   mm->record_size_in_cachelines = record_size_in_cache_lines;
+  limit = 2;
+  if (a->maplog_is_circular)
+    {
+      mm->log2_file_size_in_records = 63;
+      mm->flags |= CLIB_MAPLOG_FLAG_CIRCULAR;
+      limit = 1;
+    }
 
-  /* Map two files */
-  for (i = 0; i < 2; i++)
+  /*
+   * Map the one and only file for a circular log,
+   * two files for a normal log.
+   */
+  for (i = 0; i < limit; i++)
     {
       mm->filenames[i] = format (0, "%v_%d", mm->file_basename,
                                 mm->current_file_index++);
@@ -104,7 +113,7 @@ clib_maplog_init (clib_maplog_init_args_t * a)
       (void) close (fd);
     }
 
-  memset (h, 0, sizeof (*h));
+  clib_memset (h, 0, sizeof (*h));
   h->maplog_major_version = MAPLOG_MAJOR_VERSION;
   h->maplog_minor_version = MAPLOG_MINOR_VERSION;
   h->maplog_patch_version = MAPLOG_PATCH_VERSION;
@@ -117,6 +126,7 @@ clib_maplog_init (clib_maplog_init_args_t * a)
   h->file_size_in_records = file_size_in_records;
   h->number_of_records = ~0ULL;
   h->number_of_files = ~0ULL;
+  h->maplog_flag_circular = a->maplog_is_circular;
   memcpy (h->file_basename, mm->file_basename, vec_len (mm->file_basename));
 
   mm->header_filename = format (0, "%v_header", mm->file_basename);
@@ -143,7 +153,7 @@ fail:
   if (fd >= 0)
     (void) close (fd);
 
-  for (i = 0; i < 2; i++)
+  for (i = 0; i < limit; i++)
     {
       if (mm->file_baseva[i])
        (void) munmap ((u8 *) mm->file_baseva[i], a->file_size_in_bytes);
@@ -171,6 +181,9 @@ _clib_maplog_get_entry_slowpath (clib_maplog_main_t * mm, u64 my_record_index)
   u64 file_size_in_bytes = mm->file_size_in_records
     * mm->record_size_in_cachelines * CLIB_CACHE_LINE_BYTES;
 
+  /* This should never happen */
+  ASSERT ((mm->flags & CLIB_MAPLOG_FLAG_CIRCULAR) == 0);
+
   /*
    * Kill some time by calling format before we make the previous log
    * segment disappear. Obviously it won't do to call clib_maplog_get_entry(),
@@ -224,35 +237,20 @@ _clib_maplog_get_entry_slowpath (clib_maplog_main_t * mm, u64 my_record_index)
 }
 
 /**
- * @brief Close a mapped log, and update the log header file
+ * @brief Update a mapped log header file
  *
- * Unmap the current log segments.
  * Read the log header. Update the number of records, and number of files
- *
  * @param[in/out] mm   mapped log object
  */
 void
-clib_maplog_close (clib_maplog_main_t * mm)
+clib_maplog_update_header (clib_maplog_main_t * mm)
 {
-  int i, rv;
-  u64 file_size_in_bytes;
-  int fd;
+  int fd, rv;
   clib_maplog_header_t _h, *h = &_h;
 
   if (!(mm->flags & CLIB_MAPLOG_FLAG_INIT))
     return;
 
-  file_size_in_bytes =
-    mm->file_size_in_records * mm->record_size_in_cachelines *
-    CLIB_CACHE_LINE_BYTES;
-
-  /* unmap current + next segments */
-  for (i = 0; i < 2; i++)
-    {
-      (void) munmap ((u8 *) mm->file_baseva[i], file_size_in_bytes);
-      vec_free (mm->filenames[i]);
-    }
-
   /* Open the log header */
   fd = open ((char *) mm->header_filename, O_RDWR, 0600);
   if (fd < 0)
@@ -271,6 +269,7 @@ clib_maplog_close (clib_maplog_main_t * mm)
   /* Fix the header... */
   h->number_of_records = mm->next_record_index;
   h->number_of_files = mm->current_file_index;
+  h->maplog_flag_wrapped = (mm->flags & CLIB_MAPLOG_FLAG_WRAPPED) ? 1 : 0;
 
   /* Back to the beginning of the log header... */
   if (lseek (fd, 0, SEEK_SET) < 0)
@@ -286,10 +285,43 @@ clib_maplog_close (clib_maplog_main_t * mm)
 out:
   if (fd >= 0)
     (void) close (fd);
+}
+
+/**
+ * @brief Close a mapped log, and update the log header file
+ *
+ * Unmap the current log segments.
+ * Read the log header. Update the number of records, and number of files
+ *
+ * @param[in/out] mm   mapped log object
+ */
+void
+clib_maplog_close (clib_maplog_main_t * mm)
+{
+  int i, limit;
+  u64 file_size_in_bytes;
+
+  if (!(mm->flags & CLIB_MAPLOG_FLAG_INIT))
+    return;
+
+  clib_maplog_update_header (mm);
+
+  file_size_in_bytes =
+    mm->file_size_in_records * mm->record_size_in_cachelines *
+    CLIB_CACHE_LINE_BYTES;
+
+  limit = (mm->flags & CLIB_MAPLOG_FLAG_CIRCULAR) ? 1 : 2;
+
+  /* unmap current + next segments */
+  for (i = 0; i < limit; i++)
+    {
+      (void) munmap ((u8 *) mm->file_baseva[i], file_size_in_bytes);
+      vec_free (mm->filenames[i]);
+    }
 
   vec_free (mm->file_basename);
   vec_free (mm->header_filename);
-  memset (mm, 0, sizeof (*mm));
+  clib_memset (mm, 0, sizeof (*mm));
 }
 
 /**
@@ -308,13 +340,15 @@ format_maplog_header (u8 * s, va_list * args)
   if (!verbose)
     goto brief;
   s = format (s, "basename %s ", h->file_basename);
-  s = format (s, "log ver %d.%d.%d app id %u ver %d.%d.%d\n",
+  s = format (s, "log ver %d.%d.%d app id %u ver %d.%d.%d %s %s\n",
              h->maplog_major_version,
              h->maplog_minor_version,
              h->maplog_patch_version,
              h->application_id,
              h->application_major_version,
-             h->application_minor_version, h->application_patch_version);
+             h->application_minor_version, h->application_patch_version,
+             h->maplog_flag_circular ? "circular" : "linear",
+             h->maplog_flag_wrapped ? "wrapped" : "not wrapped");
   s = format (s, "  records are %d %d-byte cachelines\n",
              h->record_size_in_cachelines, h->cacheline_size);
   s = format (s, "  files are %lld records long, %lld files\n",
@@ -335,6 +369,14 @@ brief:
  * Reads the maplog header. Map and process all log segments in order.
  * Calls the callback function once per file with a record count.
  *
+ * Note: if the file header isn't updated by calling
+ * clib_maplog_close(), it will appear to have an infinite
+ * number of records in an infinite number of files.
+ *
+ * So long as the callback function understands that possibility
+ * - by simply ignoring NULL records - the scheme still
+ * works...
+ *
  * @param [in] file_basename Same basename supplied to clib_maplog_init
  * @param [in] fp_arg Callback function pointer
  */
@@ -347,7 +389,7 @@ clib_maplog_process (char *file_basename, void *fp_arg)
   u64 file_size_in_bytes;
   u8 *header_filename, *this_filename = 0;
   u8 *file_baseva;
-  void (*fp) (clib_maplog_header_t *, void *data, u64 count);
+  int (*fp) (clib_maplog_header_t *, void *data, u64 count);
   u64 records_this_file, records_left;
   ASSERT (fp_arg);
 
@@ -370,6 +412,7 @@ clib_maplog_process (char *file_basename, void *fp_arg)
       goto out;
     }
   (void) close (fd);
+  fd = -1;
 
   file_size_in_bytes = h->file_size_in_records
     * h->record_size_in_cachelines * CLIB_CACHE_LINE_BYTES;
@@ -384,7 +427,6 @@ clib_maplog_process (char *file_basename, void *fp_arg)
       fd = open ((char *) this_filename, O_RDONLY, 0600);
       if (fd < 0)
        {
-         clib_unix_warning ("open maplog file");
          rv = -3;
          goto out;
        }
@@ -392,6 +434,7 @@ clib_maplog_process (char *file_basename, void *fp_arg)
       file_baseva =
        mmap (0, file_size_in_bytes, PROT_READ, MAP_SHARED, fd, 0);
       (void) close (fd);
+      fd = -1;
       if (file_baseva == (u8 *) MAP_FAILED)
        {
          clib_unix_warning ("mmap");
@@ -402,7 +445,27 @@ clib_maplog_process (char *file_basename, void *fp_arg)
       records_this_file = (records_left > h->file_size_in_records) ?
        h->file_size_in_records : records_left;
 
-      (*fp) (h, file_baseva, records_this_file);
+      /*
+       * Normal log, or a circular non-wrapped log, or a circular
+       * wrapped log which happens to be exactly linear
+       */
+      if (h->maplog_flag_circular == 0 || h->maplog_flag_wrapped == 0 ||
+         ((h->number_of_records % h->file_size_in_records) == 0))
+       (*fp) (h, file_baseva, records_this_file);
+      else
+       {
+         /* "Normal" wrapped circular log */
+         u64 first_chunk_record_index = h->number_of_records &
+           (h->file_size_in_records - 1);
+         u64 first_chunk_number_of_records = records_this_file -
+           first_chunk_record_index;
+         u8 *chunk_baseva = file_baseva +
+           first_chunk_record_index * h->record_size_in_cachelines *
+           h->cacheline_size;
+         (*fp) (h, chunk_baseva, first_chunk_number_of_records);
+         (*fp) (h, file_baseva,
+                records_this_file - first_chunk_number_of_records);
+       }
 
       if (munmap (file_baseva, file_size_in_bytes) < 0)
        {
@@ -416,7 +479,7 @@ clib_maplog_process (char *file_basename, void *fp_arg)
     }
 
 out:
-  if (fd > 0)
+  if (fd >= 0)
     (void) close (fd);
 
   vec_free (this_filename);