+ p = hash_get (mm->socket_file_index_by_sock_id, args->socket_id);
+ if (p == 0)
+ {
+ rv = VNET_API_ERROR_INVALID_ARGUMENT;
+ goto done;
+ }
+
+ msf = vec_elt_at_index (mm->socket_files, p[0]);
+
+ /* existing socket file can be either master or slave but cannot be both */
+ if (msf->ref_cnt > 0)
+ {
+ if ((!msf->is_listener != !args->is_master))
+ {
+ rv = VNET_API_ERROR_SUBIF_ALREADY_EXISTS;
+ goto done;
+ }
+
+ p = mhash_get (&msf->dev_instance_by_id, &args->id);
+ if (p)
+ {
+ rv = VNET_API_ERROR_SUBIF_ALREADY_EXISTS;
+ goto done;
+ }
+ }
+
+ /* Create new socket file */
+ if (msf->ref_cnt == 0)
+ {
+ struct stat file_stat;
+
+ /* If we are creating listener make sure file doesn't exist or if it
+ * exists thn delete it if it is old socket file */
+ if (args->is_master && (stat ((char *) msf->filename, &file_stat) == 0))
+ {
+ if (S_ISSOCK (file_stat.st_mode))
+ {
+ unlink ((char *) msf->filename);
+ }
+ else
+ {
+ error = clib_error_return (0, "File exists for %s",
+ msf->filename);
+ rv = VNET_API_ERROR_VALUE_EXIST;
+ goto done;
+ }
+ }
+
+ mhash_init (&msf->dev_instance_by_id, sizeof (uword),
+ sizeof (memif_interface_id_t));
+ msf->dev_instance_by_fd = hash_create (0, sizeof (uword));
+ msf->is_listener = (args->is_master != 0);
+
+ memif_log_debug (0, "initializing socket file %s", msf->filename);
+ }
+
+ if (mm->per_thread_data == 0)
+ {
+ int i;
+ vlib_buffer_free_list_t *fl;
+
+ vec_validate_aligned (mm->per_thread_data, tm->n_vlib_mains - 1,
+ CLIB_CACHE_LINE_BYTES);
+
+ fl =
+ vlib_buffer_get_free_list (vm, VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX);
+ for (i = 0; i < tm->n_vlib_mains; i++)
+ {
+ memif_per_thread_data_t *ptd =
+ vec_elt_at_index (mm->per_thread_data, i);
+ vlib_buffer_t *bt = &ptd->buffer_template;
+ vlib_buffer_init_for_free_list (bt, fl);
+ bt->flags = VLIB_BUFFER_TOTAL_LENGTH_VALID;
+ bt->total_length_not_including_first_buffer = 0;
+ vnet_buffer (bt)->sw_if_index[VLIB_TX] = (u32) ~ 0;
+
+ /* initially prealloc copy_ops so we can use
+ _vec_len instead of vec_elen */
+ vec_validate_aligned (ptd->copy_ops, 0, CLIB_CACHE_LINE_BYTES);
+ vec_reset_length (ptd->copy_ops);
+ vec_validate_aligned (ptd->buffers, 0, CLIB_CACHE_LINE_BYTES);
+ vec_reset_length (ptd->buffers);
+ }
+ }