jvpp: make shm_prefix configurable (VPP-591) 15/5815/15
authorJan Srnicek <jsrnicek@cisco.com>
Fri, 24 Mar 2017 09:18:11 +0000 (10:18 +0100)
committerJan Srnicek <jsrnicek@cisco.com>
Mon, 14 Aug 2017 12:19:31 +0000 (12:19 +0000)
svm.c - set default map region root path only if root path is not
already present
memory_shared.c - added option for tests to send memory region name
and root path in one variable, if so name and root path are
separated here and set to map region structure so find function
can find it properly
jvpp-registry.c - added parameters shmPrefix to be able pass +
removed sudo restriction
specific shared memory prefix that is used while starting
python tests(see framework.py)
JVppRegistyImpl - added option to specify shmPrefix
VppJNIConnection - added option to specify shmPrefix

Change-Id: I3f89f867fb9b20eef00fbd497cb0e41b25d6eab7
Signed-off-by: Jan Srnicek <jsrnicek@cisco.com>
Signed-off-by: Matej Perina <mperina@cisco.com>
src/svm/svm.c
src/vlibmemory/memory_shared.c
src/vpp-api/java/jvpp-registry/io/fd/vpp/jvpp/JVppRegistryImpl.java
src/vpp-api/java/jvpp-registry/io/fd/vpp/jvpp/VppJNIConnection.java
src/vpp-api/java/jvpp-registry/jvpp_registry.c

index 600fa74..0442ecb 100644 (file)
@@ -862,7 +862,8 @@ svm_region_find_or_create (svm_map_region_args_t * a)
   ASSERT (mp);
 
   /* Map the named region from the correct chroot environment */
-  a->root_path = (char *) mp->root_path;
+  if (a->root_path == NULL)
+    a->root_path = (char *) mp->root_path;
 
   /*
    * See if this region is already known. If it is, we're
index 41aa123..9bab657 100644 (file)
@@ -341,12 +341,25 @@ vl_map_shmem (const char *region_name, int is_vlib)
   struct timespec ts, tsrem;
   u32 vlib_input_queue_length;
 
+  memset (a, 0, sizeof (*a));
+
+  if (strstr (region_name, "-vpe-api"))
+    {
+      char root_path[strlen (region_name)];
+      strncpy (root_path, region_name, strlen (region_name) - 8);
+      a->root_path = root_path;
+      am->root_path = root_path;
+    }
+
   if (is_vlib == 0)
     svm_region_init_chroot (am->root_path);
 
-  memset (a, 0, sizeof (*a));
-
-  a->name = region_name;
+  if (a->root_path != NULL)
+    {
+      a->name = "/vpe-api";
+    }
+  else
+    a->name = region_name;
   a->size = am->api_size ? am->api_size : (16 << 20);
   a->flags = SVM_FLAGS_MHEAP;
   a->uid = am->api_uid;
index 98ef1c1..6e938ae 100644 (file)
@@ -48,6 +48,13 @@ public final class JVppRegistryImpl implements JVppRegistry, ControlPingCallback
         pingCalls = new HashMap<>();
     }
 
+    public JVppRegistryImpl(final String clientName, final String shmPrefix) throws IOException {
+        connection = new VppJNIConnection(clientName, shmPrefix);
+        connection.connect();
+        pluginRegistry = new ConcurrentHashMap<>();
+        pingCalls = new HashMap<>();
+    }
+
     @Override
     public VppConnection getConnection() {
         return connection;
index 320c128..53eaa79 100644 (file)
 package io.fd.vpp.jvpp;
 
 import static io.fd.vpp.jvpp.NativeLibraryLoader.loadLibrary;
+import static java.lang.String.format;
 
 import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Objects;
@@ -30,13 +33,14 @@ import java.util.logging.Logger;
  */
 public final class VppJNIConnection implements VppConnection {
     private static final Logger LOG = Logger.getLogger(VppJNIConnection.class.getName());
+    private static final String DEFAULT_SHM_PREFIX = "/vpe-api";
 
     static {
         final String libName = "libjvpp_registry.so";
         try {
             loadLibrary(libName, VppJNIConnection.class);
         } catch (IOException e) {
-            LOG.log(Level.SEVERE, String.format("Can't find vpp jni library: %s", libName), e);
+            LOG.log(Level.SEVERE, format("Can't find vpp jni library: %s", libName), e);
             throw new ExceptionInInitializerError(e);
         }
     }
@@ -44,6 +48,7 @@ public final class VppJNIConnection implements VppConnection {
     private ConnectionInfo connectionInfo;
 
     private final String clientName;
+    private final String shmPrefix;
     private volatile boolean disconnected = false;
 
     /**
@@ -54,6 +59,12 @@ public final class VppJNIConnection implements VppConnection {
      */
     public VppJNIConnection(final String clientName) {
         this.clientName = Objects.requireNonNull(clientName, "Null clientName");
+        this.shmPrefix = DEFAULT_SHM_PREFIX;
+    }
+
+    public VppJNIConnection(final String clientName, final String shmPrefix) {
+        this.clientName = Objects.requireNonNull(clientName, "Null clientName");
+        this.shmPrefix = Objects.requireNonNull(shmPrefix, "Null shmPrefix");
     }
 
     /**
@@ -73,16 +84,18 @@ public final class VppJNIConnection implements VppConnection {
 
     @Override
     public void connect() throws IOException {
-        _connect();
+        _connect(shmPrefix);
     }
 
-    private void _connect() throws IOException {
+    private void _connect(final String shmPrefix) throws IOException {
+        Objects.requireNonNull(shmPrefix, "Shared memory prefix must be defined");
+
         synchronized (VppJNIConnection.class) {
             if (connections.containsKey(clientName)) {
                 throw new IOException("Client " + clientName + " already connected");
             }
 
-            connectionInfo = clientConnect(clientName);
+            connectionInfo = clientConnect(shmPrefix, clientName);
             if (connectionInfo.status != 0) {
                 throw new IOException("Connection returned error " + connectionInfo.status);
             }
@@ -130,7 +143,7 @@ public final class VppJNIConnection implements VppConnection {
         }
     }
 
-    private static native ConnectionInfo clientConnect(String clientName);
+    private static native ConnectionInfo clientConnect(String shmPrefix, String clientName);
 
     private static native void clientDisconnect();
 
index 66adfea..1e2c017 100644 (file)
@@ -243,14 +243,13 @@ static int send_initial_control_ping() {
     return rv;
 }
 
-static int connect_to_vpe(char *name) {
+static int connect_to_vpe(char *shm_prefix, char *name) {
     jvpp_main_t * jm = &jvpp_main;
     api_main_t * am = &api_main;
     jvpp_registry_main_t * rm = &jvpp_registry_main;
 
-    if (vl_client_connect_to_vlib("/vpe-api", name, 32) < 0)
+    if (vl_client_connect_to_vlib(shm_prefix, name, 32) < 0)
         return -1;
-
     jm->my_client_index = am->my_client_index;
 
     jm->vl_input_queue = am->shmem_hdr->vl_input_queue;
@@ -268,9 +267,15 @@ static int connect_to_vpe(char *name) {
 }
 
 JNIEXPORT jobject JNICALL Java_io_fd_vpp_jvpp_VppJNIConnection_clientConnect(
-        JNIEnv *env, jclass obj, jstring clientName) {
+        JNIEnv *env, jclass obj, jstring shmPrefix, jstring clientName) {
+    /*
+     * TODO introducing memory prefix as variable can be used in hc2vpp
+     * to be able to run without root privileges
+     * https://jira.fd.io/browse/HC2VPP-176
+     */
     int rv;
     const char *client_name;
+    const char *shm_prefix;
     void vl_msg_reply_handler_hookup(void);
     jvpp_main_t * jm = &jvpp_main;
     jvpp_registry_main_t * rm = &jvpp_registry_main;
@@ -280,15 +285,6 @@ JNIEXPORT jobject JNICALL Java_io_fd_vpp_jvpp_VppJNIConnection_clientConnect(
     jmethodID connectionInfoConstructor = (*env)->GetMethodID(env,
             connectionInfoClass, "<init>", "(JII)V");
 
-    /*
-     * Bail out now if we're not running as root
-     */
-    if (geteuid() != 0) {
-        return (*env)->NewObject(env, connectionInfoClass,
-                connectionInfoConstructor, 0, 0,
-                VNET_API_ERROR_NOT_RUNNING_AS_ROOT);
-    }
-
     if (rm->is_connected) {
         return (*env)->NewObject(env, connectionInfoClass,
                 connectionInfoConstructor, 0, 0,
@@ -296,17 +292,25 @@ JNIEXPORT jobject JNICALL Java_io_fd_vpp_jvpp_VppJNIConnection_clientConnect(
     }
 
     client_name = (*env)->GetStringUTFChars(env, clientName, 0);
+    shm_prefix = (*env)->GetStringUTFChars(env, shmPrefix, 0);
+
     if (!client_name) {
         return (*env)->NewObject(env, connectionInfoClass,
-                connectionInfoConstructor, 0, 0, VNET_API_ERROR_INVALID_VALUE);
+                connectionInfoConstructor, 0, 0, VNET_API_ERROR_INVALID_VALUE, shmPrefix);
+    }
+
+    if (!shm_prefix) {
+        return (*env)->NewObject(env, connectionInfoClass,
+                connectionInfoConstructor, 0, 0, VNET_API_ERROR_INVALID_VALUE, shmPrefix);
     }
 
-    rv = connect_to_vpe((char *) client_name);
+    rv = connect_to_vpe((char *) shm_prefix, (char *) client_name);
 
     if (rv < 0)
         clib_warning("connection failed, rv %d", rv);
 
     (*env)->ReleaseStringUTFChars(env, clientName, client_name);
+    (*env)->ReleaseStringUTFChars(env, shmPrefix, shm_prefix);
 
     return (*env)->NewObject(env, connectionInfoClass,
             connectionInfoConstructor, (jlong) pointer_to_uword (jm->vl_input_queue),