VPP-86: fix array copy in generated JNI code
Change-Id: Ic67b3c0623d98c5ee3f1ffa1e1bd9cfb96b233bd Signed-off-by: Marek Gradzki <mgradzki@cisco.com>
This commit is contained in:
@ -89,7 +89,8 @@ u64_struct_setter_template = Template("""
|
||||
u8_array_struct_setter_template = Template("""
|
||||
{
|
||||
jsize cnt = (*env)->GetArrayLength (env, ${java_name});
|
||||
if (cnt > sizeof(mp->${c_name})) cnt = sizeof(mp->${c_name});
|
||||
size_t max_size = ${field_length};
|
||||
if (max_size != 0 && cnt > max_size) cnt = max_size;
|
||||
(*env)->GetByteArrayRegion(env, ${java_name}, 0, cnt, (jbyte *)mp->${c_name});
|
||||
}
|
||||
""")
|
||||
@ -97,8 +98,11 @@ u8_array_struct_setter_template = Template("""
|
||||
u32_array_struct_setter_template = Template("""
|
||||
jint * ${java_name}ArrayElements = (*env)->GetIntArrayElements(env, ${java_name}, NULL);
|
||||
{
|
||||
int _i;
|
||||
for (_i = 0; _i < 0; _i++) {
|
||||
size_t _i;
|
||||
jsize cnt = (*env)->GetArrayLength (env, ${java_name});
|
||||
size_t max_size = ${field_length};
|
||||
if (max_size != 0 && cnt > max_size) cnt = max_size;
|
||||
for (_i = 0; _i < cnt; _i++) {
|
||||
mp->${c_name}[_i] = clib_host_to_net_u32(${java_name}ArrayElements[_i]);
|
||||
}
|
||||
}
|
||||
@ -180,16 +184,18 @@ def generate_jni_impl(func_list, inputfile):
|
||||
jni_getter=jni_getter)
|
||||
|
||||
# field setters
|
||||
for t in zip(f['c_types'], f['args']):
|
||||
for t in zip(f['c_types'], f['args'], f['lengths']):
|
||||
c_type = t[0]
|
||||
c_name = t[1]
|
||||
field_length = t[2]
|
||||
java_field_name = util.underscore_to_camelcase(c_name)
|
||||
|
||||
struct_setter_template = struct_setter_templates[c_type]
|
||||
|
||||
struct_setters += struct_setter_template.substitute(
|
||||
c_name=c_name,
|
||||
java_name=java_field_name)
|
||||
java_name=java_field_name,
|
||||
field_length=field_length)
|
||||
|
||||
jni_impl.append(jni_impl_template.substitute(
|
||||
inputfile=inputfile,
|
||||
@ -221,23 +227,23 @@ u64_dto_field_setter_template = Template("""
|
||||
""")
|
||||
|
||||
u8_array_dto_field_setter_template = Template("""
|
||||
jbyteArray ${java_name} = (*env)->NewByteArray(env, sizeof(mp->${c_name}));
|
||||
(*env)->SetByteArrayRegion(env, ${java_name}, 0, sizeof(mp->${c_name}), (const jbyte*)mp->${c_name});
|
||||
jbyteArray ${java_name} = (*env)->NewByteArray(env, ${field_length});
|
||||
(*env)->SetByteArrayRegion(env, ${java_name}, 0, ${field_length}, (const jbyte*)mp->${c_name});
|
||||
(*env)->SetObjectField(env, dto, ${java_name}FieldId, ${java_name});
|
||||
""")
|
||||
|
||||
# For each u64 array we get its elements. Then we convert values to host byte order.
|
||||
# All changes to jint* buffer are written to jlongArray (isCopy is set to NULL)
|
||||
u64_array_dto_field_setter_template = Template("""
|
||||
jlongArray ${java_name} = (*env)->NewLongArray(env, sizeof(mp->${c_name}));
|
||||
{
|
||||
jlongArray ${java_name} = (*env)->NewLongArray(env, ${field_length});
|
||||
jlong * ${java_name}ArrayElements = (*env)->GetLongArrayElements(env, ${java_name}, NULL);
|
||||
int _i;
|
||||
for (_i = 0; _i < 0; _i++) {
|
||||
unsigned int _i;
|
||||
for (_i = 0; _i < ${field_length}; _i++) {
|
||||
${java_name}ArrayElements[_i] = clib_net_to_host_u64(mp->${c_name}[_i]);
|
||||
}
|
||||
(*env)->SetObjectField(env, dto, ${java_name}FieldId, ${java_name});
|
||||
}
|
||||
(*env)->SetObjectField(env, dto, ${java_name}FieldId, ${java_name});
|
||||
""")
|
||||
|
||||
dto_field_setter_templates = {'u8': default_dto_field_setter_template,
|
||||
@ -282,10 +288,11 @@ def generate_msg_handlers(func_list, inputfile):
|
||||
|
||||
dto_setters = ''
|
||||
# dto setters
|
||||
for t in zip(f['c_types'], f['types'], f['args']):
|
||||
for t in zip(f['c_types'], f['types'], f['args'], f['lengths']):
|
||||
c_type = t[0]
|
||||
jni_type = t[1]
|
||||
c_name = t[2]
|
||||
field_length = t[3]
|
||||
|
||||
java_field_name = util.underscore_to_camelcase(c_name)
|
||||
jni_signature = util.jni_2_signature_mapping[jni_type]
|
||||
@ -302,7 +309,8 @@ def generate_msg_handlers(func_list, inputfile):
|
||||
java_name=java_field_name,
|
||||
jni_signature=jni_signature,
|
||||
c_name=c_name,
|
||||
jni_setter=jni_setter)
|
||||
jni_setter=jni_setter,
|
||||
field_length=field_length)
|
||||
|
||||
handlers.append(msg_handler_template.substitute(
|
||||
inputfile=inputfile,
|
||||
|
@ -72,16 +72,19 @@ def get_args(t, filter):
|
||||
def get_types(t, filter):
|
||||
types_list = []
|
||||
c_types_list = []
|
||||
lengths_list = []
|
||||
for i in t:
|
||||
if not filter(i[1]):
|
||||
continue
|
||||
if len(i) is 3: # array type
|
||||
types_list.append(vpp_2_jni_type_mapping[i[0]] + 'Array')
|
||||
c_types_list.append(i[0] + '[]')
|
||||
lengths_list.append(i[2])
|
||||
else: # primitive type
|
||||
types_list.append(vpp_2_jni_type_mapping[i[0]])
|
||||
c_types_list.append(i[0])
|
||||
return types_list, c_types_list
|
||||
lengths_list.append(0)
|
||||
return types_list, c_types_list, lengths_list
|
||||
|
||||
|
||||
def get_definitions():
|
||||
@ -96,18 +99,18 @@ def get_definitions():
|
||||
|
||||
# For replies include all the arguments except message_id
|
||||
if util.is_reply(java_name):
|
||||
types, c_types = get_types(a[1:], is_response_field)
|
||||
types, c_types, lengths = get_types(a[1:], is_response_field)
|
||||
func_name[a[0]] = dict(
|
||||
[('name', a[0]), ('java_name', java_name),
|
||||
('args', get_args(a[1:], is_response_field)), ('full_args', get_args(a[1:], lambda x: True)),
|
||||
('types', types), ('c_types', c_types)])
|
||||
('types', types), ('c_types', c_types), ('lengths', lengths)])
|
||||
# For requests skip message_id, client_id and context
|
||||
else:
|
||||
types, c_types = get_types(a[1:], is_request_field)
|
||||
types, c_types, lengths = get_types(a[1:], is_request_field)
|
||||
func_name[a[0]] = dict(
|
||||
[('name', a[0]), ('java_name', java_name),
|
||||
('args', get_args(a[1:], is_request_field)), ('full_args', get_args(a[1:], lambda x: True)),
|
||||
('types', types), ('c_types', c_types)])
|
||||
('types', types), ('c_types', c_types), ('lengths', lengths)])
|
||||
|
||||
# Indexed by name
|
||||
func_list.append(func_name[a[0]])
|
||||
|
142
vpp-api/java/jvpp/org/openvpp/jvpp/test/L2AclTest.java
Normal file
142
vpp-api/java/jvpp/org/openvpp/jvpp/test/L2AclTest.java
Normal file
@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Cisco and/or its affiliates.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.openvpp.jvpp.test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import org.openvpp.jvpp.JVppImpl;
|
||||
import org.openvpp.jvpp.VppJNIConnection;
|
||||
import org.openvpp.jvpp.dto.ClassifyAddDelSession;
|
||||
import org.openvpp.jvpp.dto.ClassifyAddDelSessionReply;
|
||||
import org.openvpp.jvpp.dto.ClassifyAddDelTable;
|
||||
import org.openvpp.jvpp.dto.ClassifyAddDelTableReply;
|
||||
import org.openvpp.jvpp.dto.InputAclSetInterface;
|
||||
import org.openvpp.jvpp.dto.InputAclSetInterfaceReply;
|
||||
import org.openvpp.jvpp.dto.JVppReply;
|
||||
import org.openvpp.jvpp.future.FutureJVppFacade;
|
||||
import org.openvpp.jvpp.future.FutureJVppFacadeCallback;
|
||||
|
||||
/**
|
||||
* <p>Tests L2 ACL creation.<br>
|
||||
* Equivalent to the following vppctl commands:<br>
|
||||
*
|
||||
* <pre>{@code
|
||||
* vppctl classify table mask l2 src
|
||||
* vppctl classify session acl-hit-next deny opaque-index 0 table-index 0 match l2 src 01:02:03:04:05:06
|
||||
* vppctl vppctl set int input acl intfc local0 l2-table 0
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* To verify invoke:<br>
|
||||
* {@code vppctl sh class table verbose}
|
||||
*/
|
||||
public class L2AclTest {
|
||||
|
||||
private static ClassifyAddDelTable createClassifyTable() {
|
||||
ClassifyAddDelTable request = new ClassifyAddDelTable();
|
||||
request.isAdd = 1;
|
||||
request.tableIndex = ~0; // default
|
||||
request.nbuckets = 2;
|
||||
request.memorySize = 2 << 20;
|
||||
request.nextTableIndex = ~0; // default
|
||||
request.missNextIndex = ~0; // default
|
||||
request.skipNVectors = 0;
|
||||
request.matchNVectors = 1;
|
||||
request.mask =
|
||||
new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
|
||||
(byte) 0xff, (byte) 0xff, 0x00, 0x00, 0x00, 0x00};
|
||||
return request;
|
||||
}
|
||||
|
||||
private static ClassifyAddDelSession createClassifySession(final int tableIndex) {
|
||||
ClassifyAddDelSession request = new ClassifyAddDelSession();
|
||||
request.isAdd = 1;
|
||||
request.tableIndex = tableIndex;
|
||||
request.hitNextIndex = 0; // deny
|
||||
request.opaqueIndex = 0;
|
||||
request.advance = 0; // default
|
||||
// match 01:02:03:04:05:06 mac address
|
||||
request.match =
|
||||
new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04,
|
||||
(byte) 0x05, (byte) 0x06, 0x00, 0x00, 0x00, 0x00};
|
||||
return request;
|
||||
}
|
||||
|
||||
private static InputAclSetInterface aclSetInterface() {
|
||||
InputAclSetInterface request = new InputAclSetInterface();
|
||||
request.isAdd = 1;
|
||||
request.swIfIndex = 0;
|
||||
request.ip4TableIndex = ~0; // skip
|
||||
request.ip6TableIndex = ~0; // skip
|
||||
request.l2TableIndex = 0;
|
||||
return request;
|
||||
}
|
||||
|
||||
private static void print(ClassifyAddDelTableReply reply) {
|
||||
System.out.printf("ClassifyAddDelTableReply: context=%d, retval=%d, " +
|
||||
"newTableIndex=%d, skipNVectors=%d, matchNVectors=%d\n",
|
||||
reply.context,
|
||||
reply.retval,
|
||||
reply.newTableIndex,
|
||||
reply.skipNVectors,
|
||||
reply.matchNVectors);
|
||||
}
|
||||
|
||||
private static void print(ClassifyAddDelSessionReply reply) {
|
||||
System.out.printf("ClassifyAddDelSessionReply: context=%d, retval=%d\n",
|
||||
reply.context,
|
||||
reply.retval);
|
||||
}
|
||||
|
||||
private static void print(final InputAclSetInterfaceReply reply) {
|
||||
System.out.printf("InputAclSetInterfaceReply: context=%d, retval=%d\n",
|
||||
reply.context,
|
||||
reply.retval);
|
||||
|
||||
}
|
||||
|
||||
private static void testL2Acl() throws Exception {
|
||||
System.out.println("Testing L2 ACLs using Java callback API");
|
||||
final Map<Integer, CompletableFuture<? extends JVppReply<?>>> map = new HashMap<>();
|
||||
final JVppImpl jvpp = new JVppImpl(VppJNIConnection.create("FutureApiTest", new FutureJVppFacadeCallback(map)));
|
||||
final FutureJVppFacade jvppFacade = new FutureJVppFacade(jvpp, map);
|
||||
System.out.println("Successfully connected to VPP");
|
||||
Thread.sleep(1000);
|
||||
|
||||
final ClassifyAddDelTableReply classifyAddDelTableReply =
|
||||
jvppFacade.classifyAddDelTable(createClassifyTable()).toCompletableFuture().get();
|
||||
print(classifyAddDelTableReply);
|
||||
|
||||
final ClassifyAddDelSessionReply classifyAddDelSessionReply =
|
||||
jvppFacade.classifyAddDelSession(createClassifySession(classifyAddDelTableReply.newTableIndex))
|
||||
.toCompletableFuture().get();
|
||||
print(classifyAddDelSessionReply);
|
||||
|
||||
final InputAclSetInterfaceReply inputAclSetInterfaceReply =
|
||||
jvppFacade.inputAclSetInterface(aclSetInterface()).toCompletableFuture().get();
|
||||
print(inputAclSetInterfaceReply);
|
||||
|
||||
System.out.println("Disconnecting...");
|
||||
jvpp.close();
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
testL2Acl();
|
||||
}
|
||||
}
|
@ -2,12 +2,11 @@ This package contains basic tests for jvpp. To run the tests:
|
||||
|
||||
- Make sure VPP is running
|
||||
- From VPP's build-root/ folder execute:
|
||||
- sudo java -cp .:build-vpp-native/vpp-api/java/jvpp-1.0.0.jar org.openvpp.jvpp.test.ControlPingTest
|
||||
- sudo java -cp .:build-vpp-native/vpp-api/java/jvpp-1.0.0.jar org.openvpp.jvpp.test.FutureApiTest
|
||||
- sudo java -cp .:build-vpp-native/vpp-api/java/jvpp-1.0.0.jar org.openvpp.jvpp.test.CallbackApiTest
|
||||
- sudo java -cp build-vpp-native/vpp-api/java/jvpp-16.06.jar org.openvpp.jvpp.test.[test name]
|
||||
|
||||
Available tests:
|
||||
ControlPingTest - Simple test executing a single control ping using low level JVpp APIs
|
||||
CallbackApiTest - Similar to ControlPingTest, invokes more complex calls (e.g. interface dump) using low level JVpp APIs
|
||||
FutureApiTest - Execution of more complex calls using Future based JVpp facade
|
||||
CallbackJVppFacadeTest - Execution of more complex calls using Callback based JVpp facade
|
||||
CallbackJVppFacadeTest - Execution of more complex calls using Callback based JVpp facade
|
||||
L2AclTest - Tests L2 ACL creation
|
Reference in New Issue
Block a user